zoukankan      html  css  js  c++  java
  • Oracle_集合

    游标遍历select语句

    set serveroutput on;
    
    declare type sp_test1_cursor is ref cursor;
            test1_cursor sp_test1_cursor;
            v_name user_tables.TABLE_NAME%type;
            v_count number;
            strsql varchar2(100);
    begin
      open test1_cursor for select table_name from user_tables;
      loop
        fetch test1_cursor into v_name;
        if v_name is not null then
          strsql:='select count(*) from ' || v_name;
          execute immediate strsql into v_count;
         end if;
         exit when test1_cursor%notfound;
         dbms_output.put_line(v_name||'          '||v_count);
      end loop;
      close test1_cursor;
    end;

    全信息

    declare 
       cursor mysor is select * from emp;
     begin
        for i in mysor
          loop
             dbms_output.put_line(i.ename||e.deptno);
          end loop; 
     end;
     create or replace procedure test_procedure_job
    
    as
    v1 varchar2(50);
    v2 varchar2(50);
    v3 varchar2(50);
    begin
       for v1 in
       (select t.id
              from test_table t) 
       loop
           select t.username,t.password into v2,v3 from sshtest t where t.id = v1.id;
           
           dbms_output.put_line(v1.id || ',' || v2 || ',' || v3);
         
       end loop;
       
    end test_procedure_job;

    一维数组

    SET SERVEROUT ON SIZE 100000
    
    DECLARE
    
      TYPE T_VARRAY IS VARRAY(3) OF VARCHAR2(20);
    
      V_VAR T_VARRAY := T_VARRAY('I', 'LOVE', 'STUDY');
    
    BEGIN
    
      FOR I IN 1 .. V_VAR.COUNT LOOP
    
        DBMS_OUTPUT.PUT_LINE(V_VAR(I));
    
      END LOOP;
    
    END;
    
     

     For 循环

       PL/SQL中有两种类型的FOR循环:数字型FOR循环和游标型FOR循环。数值型FOR循环式传统的大家熟悉的“计数”循环,这种FOR循环的迭代次数在循环开始的时候就知道了。如果在FOR循环的范围处没有设置循环索引的递进方向从低到高或者从高到低(reverse将范围条件置反)。语法如下:
    
    FOR loopIndex    IN [REVERSE] lowest_number..heighest_number 
    
    LOOP
    
        . . . 可以执行的语句
    
    END LOOP;
    
    使用这种循环的原因:
    
        如果只想有限次的执行一段代码,又不想过早的结束循环,就可以使用数值型的FOR循环。
    
    【如】输出从satrtIndex开始到endIndex的数字
    
    PROCEDURE display_number(
    
        startIndex    IN    INTEGER,
    
        endIndex     IN    INTEGER
    
    )AS
    
    BEGIN
    
    FOR currentIndex IN startIndex.. endIndex
    
        LOOP
    
            DBMS_OUTPUT.PUT_LINE(currentIndex );
    
    END LOOP;
    
    END;
    
    FOR info IN (SELECT * FROM student)
    
    LOOP
    
        . . . info.C_NAME
    
    END LOOP;
    
    使用数字型FOR循环的规则:
    
    a、不要声明循环索引,PL/SQL会自动、隐式的用一个INTEGER类型的局部变量作为循环索引。作用范围就是该循环本省,不能在循环之外使用
    
    b、在范围部分使用的表达式会在循环开始时被求值一次。范围部分不会随着循环的反复执行而被重复求值,如果在循环体内部改变范围表达式使用的变量,这种改变对范围边界没有任何作用
    
    c、在循环体内部不要改变索引值或者范围边界值。
    
    d、使用reverse关键字可以迫使循环从上边界到下边界递减进行,但是你必须保证上边界大于下边界
    
    处理非平滑增长:
    
        PL/SQL并没有提供可以指定特殊的累进步幅得“进步”语法。在PL/SQL中数值型的FOR循环的各种变体中,递进步幅总是为1为单位进步。如果让循环只有当遇到1到100之间的偶数时才执行?你可以使用MOD函数。如:
    
    FOR loop_index IN 1..100 LOOP
    
        IF MOD (loop_index, 2) = 0 THEN
    
           calc_values(loop_index);
    
        END IF;
    
    END LOOP;
    
    或者
    
    FOR loop_index IN 1..50 LOOP
    
        calc_values(loop_index*2);
    
    END LOOP;
    
    游标型FOR循环:
    
        游标型FOR循环是和一个现实游标或者直接放在循环边界中的SELECT语句关联在一起的循环。如果你需要取出游标的每条记录依次处理,就可以使用游标FOR循环,而这种也是游标的主要用法。语法如下:
    
    FOR record IN {cursor_name | select statement}
    
    LOOP
    
        executable statements
    
    END LOOP;
    
    其中record是一个记录,这个记录是PL/SQL根据cursor_name这个游标%ROWTYPE属性隐式声明出来的。注意:不要现实的声明一个与循环索引(record)同名的记录,会导致逻辑错误。直接在循环中嵌套SELECT语句。
    
    FOR student INSELECT * FROM students)
    
    LOOP
    
        DBMS_OUTPUT.PUT_LINE( student.N_USERNAME );
    
    END LOOP;
    
    然而,应该避免使用这种方式,因为SELECT出现在了不该出现的地方,维护难以理解。
    
    如:我们将更新所有员工的薪水。
    
    方式一:
    
    DECLARE
    
        CURSOR student_cursor IS
    
            SELECT id, name, salaray FROM employers;
    
        student    student_cursor%ROWTYPE;
    
    BEGIN
    
        OPEN student_cursor;
    
        LOOP
    
            FETCH student_cursor INTO student;
    
            EXIT WHEN student_cursor%NOTFOUND;
    
            UPDATE students SET salary= student .salary*0.3 WHERE id=student.id;    
    
        END LOOP;
    
        CLOSE student_cursor;
    
    END;
    
    方式二:
    
    DECLARE
    
        CURSOR student_cursor IS
    
            SELECT id, name, salaray FROM employers;
    
    BEGIN
    
        LOOP student IN student_cursor 
    
            UPDATE students SET salary= student .salary*0.3 WHERE id=student.id;    
    
        END LOOP;
    
    END;

     游标

    SET SERVEROUTPUT ON;
    
    DECLARE
      v_empno emp.empno%TYPE;
      v_ename emp.ename%TYPE;
      
      CURSOR emp_cursor IS
      SELECT empno,ename from emp where empno<>1000;
      
    BEGIN
    
    LOOP
    
      IF NOT emp_cursor%ISOPEN  THEN
         OPEN emp_cursor;
      END IF; 
      
      FETCH emp_cursor INTO  v_empno,v_ename; 
      EXIT WHEN emp_cursor%NOTFOUND;
     
      dbms_output.put_line('empno is:' || v_empno || ' emp name is:' || v_ename);
        
    END LOOP;
    
    END;
    /

    运行结果

    anonymous block completed
    empno is:7369 emp name is:SMITH
    empno is:7499 emp name is:ALLEN
    empno is:7521 emp name is:WARD
    empno is:7566 emp name is:JONES
    empno is:7654 emp name is:MARTIN
    empno is:7698 emp name is:BLAKE
    empno is:7782 emp name is:CLARK
    empno is:7788 emp name is:SCOTT
    empno is:7839 emp name is:KING
    empno is:7844 emp name is:TURNER
    empno is:7876 emp name is:ADAMS
    empno is:7900 emp name is:JAMES
    empno is:7902 emp name is:FORD
    empno is:7934 emp name is:MILLER
    要注意的一点:FETCH 后,马上进行EXIT 比较好。这是因为如果不是这样,在循环中还有来一次,此时可能有干了一些操作,这回导致出现问题。
    
    还有一点,由于 第一次FETCH之前,%NOTFOUND 的值为空。
    
    所以如果 FETCH 从来没有真的成功过,那么 EXIT WHEN emp_cusor%NOTFOUND 有可能一直为NULL,这样就一直在循环里无法退出。所以,更好的写法是:
    
    EXIT WHEN emp_cursor%NOTFOUND OR emp_cursor%NOTFOUND IS NULL
    
    结束 
  • 相关阅读:
    【leetcode】1295. Find Numbers with Even Number of Digits
    【leetcode】427. Construct Quad Tree
    【leetcode】1240. Tiling a Rectangle with the Fewest Squares
    【leetcode】1292. Maximum Side Length of a Square with Sum Less than or Equal to Threshold
    【leetcode】1291. Sequential Digits
    【leetcode】1290. Convert Binary Number in a Linked List to Integer
    【leetcode】1269. Number of Ways to Stay in the Same Place After Some Steps
    【leetcode】1289. Minimum Falling Path Sum II
    【leetcode】1288. Remove Covered Intervals
    【leetcode】1287. Element Appearing More Than 25% In Sorted Array
  • 原文地址:https://www.cnblogs.com/MarchThree/p/4934824.html
Copyright © 2011-2022 走看看