码迷,mamicode.com
首页 > 数据库 > 详细

PLSQL NOTE----cursor

时间:2015-12-18 14:41:52      阅读:159      评论:0      收藏:0      [点我收藏+]

标签:

oracle plsql cursor usage

目录

一、游标的相关概念及特性

  1.定义

  2.游标的分类

  3.游标使用的一般过程

  4.游标的属性

    (1)公共的属性

    (2)额外的属性

二、隐式游标

  1.隐式游标定义

  2.隐式游标的属性

  3.SELECT INTO时使用隐式游标

三、显式游标

  1.显式游标的属性

  2.显式游标的使用步骤

    (1) 声明游标

    (2)打开游标

    (3)读取游标数据

    (4)关闭游标

  3.显式游标完整的使用示例

四、游标FOR循环

五、SELECT FOR UPDATE

   1.定义

  2.语法

  3.使用例子

 六、WHERE CURRENT OF 语句

   1.语法

  2.使用例子

一、游标的相关概念及特性
        1.定义
        映射在结果集中某一行数据的具体位置,类似于C语言中的指针。即通过游标方式定位到结果集中某个特定的行,然后根据业务需求对该行进行相应特定的操作。
        2.游标的分类
        在Oracel中,游标可以分为两大类:静态游标 和 REF游标(动态游标)。REF游标是一种引用类型,类似于指针。而静态游标又分为显式游标和隐式游标两种。
        3.游标使用的一般过程:
        显式游标:声明--->打开--->读取--->关闭。
        隐式游标:直接使用读取,声明、打开、关闭都是系统自动进行的。
        4.游标的属性:
            (1)公共的属性:%FOUND,%NOTFOUND,%ISOPEN,%ROWCOUNT。
       %FOUND 布尔型属性,返回TRUE如果INSERT或UPDATE DELETE语句影响了一行或多行或SELECT INTO语句返回一行或多行;否则,返回FALSE。
       %NOTFOUND 布尔型属性,与%FOUND相反。返回TRUE,如果INSERT或UPDATE DELETE语句没有影响任何行,或SELECT INTO语句没有返回任何行;否则,返回FALSE
       %ISOPEN 布尔型属性,判断游标的状态,当游标已经打开时返回TRUE,游标关闭时则返回FALSE。隐式游标总是返回FALSE,因为系统在执行后自动关闭游标。
       %ROWCOUNT 数字型属性,返回受SQL影响的行数。
       注:当使用隐式游标的属性时,需要在属性前加上SQL。因为Oracle在创建隐式游标时,默认的游标名为SQL。比如:SQL%NOTFOUND;
      (2)额外的属性:%BULK_ROWCOUNT,%BULK_EXCEPTIONS。
          %BULK_ROWCOUNT被用于FORALL语句。此属性的第i个元素存储 FORALL LOOP中第 i个执行中的处理的行数UPDATE或DELETE语句。如果第 i个执行不会影响任何行%BULK_ROWCOUNT(i)返回零。
          %BULK_EXCEPTIONS被用于FORALL语句。此属性存储FORALL LOOP中第i个执行的异常,%BULK_EXCEPTIONS(i).ERROR_CODE对应错误代 码,%BULK_EXCEPTIONS(i).ERROR_INDEX对应错误信息。

技术分享

技术分享

注:

  1.不能比较两个游标变量是否相等或者不等。(cv1   emps_rc;   cv2   emps_rc;  IF cv1 = cv2)

  2.CURSOR 类型不能够用于COLLECTION。(TYPE cvs_t IS TABLE OF SYS_REFCURSOR;)

   3.基于REF CURSOR的游标变量无法在PACKAGE的级别被定义,只能够定义在过程,函数,匿名块或触发器里面。(CREATE OR REPLACE PACKAGE plch_pkg  IS  g_cursor   SYS_REFCURSOR; END;)                                                                                                                      回到顶部 

二、隐式游标
    1.隐式游标定义
       隐式游标由系统自动定义,其过程由oracle控制,完全自动化。比如当DML被使用时,Oracle为每一个不属于显式游标的DML语句都创建一个隐式 游标,其声明、打开、关闭都是系统自动进行。另外,隐式游标默认的名称是SQL,不能对SQL游标显式地执行OPEN,FETCH,CLOSE语句。

    2.隐式游标的属性
        类似于显式游标,隐式游标同样具有四种属性,只不过隐式游标以SQL%开头,而显示游标以Cursor_name%开头。
        并且,通过SQL%总是只能访问前一个DML操作或单行SELECT操作的游标属性,用于判断DML执行的状态和结果,进而控制程序的流程。
        SQL%ISOPEN
                游标是否打开。当执行select into、insert、update、delete这些DML操作时,Oracle会隐含地打开游标,且在该语句执行完毕或隐含地关闭游标。
                因为是隐式游标,故SQL%ISOPEN总是FALSE。
        SQL%FOUND     
                判断SQL语句是否成功执行。当有作用行时则成功执行为TRUE,否则为FALSE。
        SQL%NOTFOUND  
                判断SQL语句是否成功执行。当有作用行时否其值为FALSE,否则其值为TRUE。
        SQL%ROWCOUNT
                在执行任何DML语句之前,SQL%ROWCOUNT的值都是NULL。
                对于SELECTINTO语句,如果执行成功,SQL%ROWCOUNT的值为1;
                如果没有成功,SQL%ROWCOUNT的值为0,同时产生一个异常NO_DATA_FOUND。              
 3.SELECT INTO时使用隐式游标
SELECT INTO用于将单行结果集放置到变量之中。SELECT INTO处理的结果包括三种情况
            查询结果返回单行,SELECT INTO被成功执行;
            查询结果没有返回行,PL/SQL将抛出no_data_found异常;
            查询结果返回多行,PL/SQL将抛出too_many_rows 异常。
        对于上述两种异常发生时,类似于普通异常处理,程序控制权转移到异常处理部分(如没有异常处理则程序中断)。对于异常被激后发,SQL游标的四个属性在此将不可使用,如下面的例子:

 1      DECLARE  
 2        v_ename emp.ename%TYPE;  
 3      BEGIN  
 4        SELECT ename INTO v_ename FROM emp WHERE empno=&no;  
 5        IF  SQL%ROWCOUNT=0 OR SQL%NOTFOUND THEN  
 6          DBMS_OUTPUT.PUT_LINE(The record ||&no|| is not exist!);  
 7        ELSE  
 8          DBMS_OUTPUT.PUT_LINE(The name for record ||&no|| is ||v_ename );  
 9        END IF;  
10      EXCEPTION  
11        WHEN NO_DATA_FOUND THEN  
12          DBMS_OUTPUT.PUT_LINE(No data found for ||&no);  
13      END;  
14   操作及结果:
15      Enter value for no:70  
16      No data found for 70  
17            
18      Enter value for no:7788  
19      The name for record 7788 is SCOTT 

从上面的演示中可以看到,当select into没有返回行时,IF  SQL%ROWCOUNT=0OR SQL%NOTFOUND THEN 语句并没有被执行。
        使用下面改进过的代码来执行,即可以将SQL游标属性判断放置到EXCEPTION部分。

 1     DECLARE  
 2       v_ename emp.ename%TYPE;  
 3     BEGIN  
 4       SELECT ename INTO v_ename FROM emp WHERE empno=&no;  
 5       IF SQL%NOTFOUND THEN  
 6         DBMS_OUTPUT.PUT_LINE(The record ||&no|| is not exist!);  
 7       ELSE  
 8         DBMS_OUTPUT.PUT_LINE(The name for record ||&no|| is ||v_ename );  
 9       END IF;  
10     EXCEPTION  
11       WHEN NO_DATA_FOUND THEN  
12         IF SQL%NOTFOUND THEN  
13           DBMS_OUTPUT.PUT_LINE(The record ||&no|| is not exist!);  
14           DBMS_OUTPUT.PUT_LINE(No data found for ||&no);  
15         ELSE  
16           DBMS_OUTPUT.PUT_LINE(The name for record ||&no|| is ||v_ename );  
17         END IF;  
18     END;  
19         操作及结果:
20     Enter value for no:80  
21     The record 80 is not exist!  
22     No data found for 80  

                                                                                   回到顶部

三、显式游标
       1.显式游标的属性
           显式游标的也是4个属性(%FOUND,%NOTFOUND,%ISOPEN,%ROWCOUNT),与隐式游标的相同。      
   2.显式游标的使用步骤:声明(定义)--->打开--->读取--->关闭。
          (1) 声明游标
          格式如下:

 1  CURSOR cursor_name [(parameter[, parameter]...)]  
 2  [RETURN return_type]  
 3  IS select_statement 
 4  例子:
 5  DECLARE  
 6     CURSOR emp_cursor(department IN number2 DEFAULT 20)
 7  return emp%rowtype  
 8  IS   
 9     SELECT *   
10     FROM emp   
11     WHERE deptno=department;

     (2)打开游标
          格式:OPEN cursor_name[(VALUE[,VALUE]...)];
          例子:OPEN emp_cursor;
          (3)读取游标数据
          格式:FETCH cursor_name INTO { variable_list | record_variable };
          例子:FETCH emp_cursor INTO emp_row;

  注:游标使用的参数在执行中变化并不影响结果。如下例中:即使 factor一直在增加,但salary一直是乘2。

 1 DECLARE
 2   my_sal employees.salary%TYPE;
 3   my_job employees.job_id%TYPE;
 4   factor INTEGER := 2;
 5   CURSOR c1 IS
 6     SELECT factor*salary FROM employees WHERE job_id = my_job;
 7 BEGIN
 8    OPEN c1;  -- factor initially equals 2
 9    LOOP
10       FETCH c1 INTO my_sal;
11       EXIT WHEN c1%NOTFOUND;
12       factor := factor + 1;  -- does not affect FETCH
13    END LOOP;
14    CLOSe c1;
15 END;
16 /

          (4)关闭游标
          格式:CLOSE cursor_name;
          例子:CLOSE emp_cursor;

  3.显式游标完整的使用示例: 

 1         --下面的程序将显示声明一个游标,并在循环中使用SELECT语句提取所有部门为30的员工信息。  
 2         DECLARE  
 3           CURSOR emp_cursor(department IN NUMBER DEFAULT 20) IS  
 4             SELECT empno, ename, job, sal  
 5               FROM emp  
 6              WHERE deptno = department;  
 7           
 8           TYPE employee IS RECORD(  
 9             id   emp.empno%TYPE,  
10             NAME emp.ename%TYPE,  
11             job  emp.job%TYPE,  
12             sal  emp.sal%TYPE);  
13           emp_row employee;  
14         BEGIN  
15           OPEN emp_cursor(30);  
16           FETCH emp_cursor INTO emp_row;  
17           WHILE emp_cursor%FOUND LOOP  
18             dbms_output.put(员工编号 || emp_row.id);  
19             dbms_output.put( 姓名 || emp_row.name);  
20             dbms_output.put( 职位 || emp_row.job);  
21             dbms_output.put( 薪金 || emp_row.sal);  
22             --填充下一条记录  
23             FETCH emp_cursor INTO emp_row;  
24           END LOOP;  
25           CLOSE emp_cursor;  
26         END; 

                                                                                回到顶部

 四、游标FOR循环

       在大多数时候我们在自定义显示游标的时候都遵循下面的步骤:
        1、打开游标
        2、开始循环
        3、从游标中取值
        4、检查那一行被返回
        5、处理
        6、关闭循环
        7、关闭游标
        可以简单的把这一类代码称为游标用于循环。但还有一种循环与这种类型不相同,这就是FOR循环,用于FOR循环的游标按照正常的声明方式声明,它的优点在 于不需要显式的打开、关闭、取数据,测试数据的存在、定义存放数据的变量等等。游标FOR 循环的语法如下:

 1  FOR record_index in cursor_name
 2  LOOP
 3     {...statements...}
 4  END LOOP;
 5    使用例子:
 6  CREATE OR REPLACE Function TotalIncome
 7     ( name_in IN varchar2 )
 8     RETURN varchar2
 9  IS
10     total_val number(6);
11     cursor c1 is
12       SELECT monthly_income
13       FROM employees
14       WHERE name = name_in;
15  BEGIN
16     total_val := 0;
17     FOR employee_rec in c1
18     LOOP
19        total_val := total_val + employee_rec.monthly_income;
20     END LOOP;
21     RETURN total_val;
22  END;

 五、SELECT FOR UPDATE
    1.定义
    SELECT FOR UPDATE 语句可以锁住游标结果集。直到下一次 COMMIT 或ROLLBACK 操作执行后,才解锁游标。
    2.语法

1         CURSOR cursor_name
2         IS
3       select_statement
4        FOR UPDATE [OF column_list] [NOWAIT];
5        
6        cursor_name: 游标名。
7         select_statement: SELECT 查询语句。
8         column_list: 游标结果集中想要更新的字段。
9         NOWAIT: 选择游标是否等待资源。

3.使用例子

1 CURSOR c1
2         IS
3          SELECT course_number, instructor
4       FROM courses_tbl
5       FOR UPDATE OF instructor; 
6   注:可以使用 WHERE CURRENT OF 语句 来更新或删除被 SELECT FOR UPDATE 锁住的数据。

                                                                                  回到顶部    

六、WHERE CURRENT OF 语句
    1.语法

1         UPDATE table_name
2       SET set_clause
3       WHERE CURRENT OF cursor_name;
4 5       DELETE FROM table_name
6         WHERE CURRENT OF cursor_name;

        注: WHERE CURRENT OF 语句只更新或删除最后被游标 FETCH 到的记录。
    2.使用例子

 1  (1)Updating using the WHERE CURRENT OF Statement
 2  CREATE OR REPLACE Function FindCourse
 3     ( name_in IN varchar2 )
 4     RETURN number
 5  IS
 6     cnumber number;
 7     CURSOR c1
 8     IS
 9       SELECT course_number
10       FROM courses_tbl
11       WHERE course_name = name_in
12       FOR UPDATE of instructor;
13  BEGIN
14     OPEN c1;
15     FETCH c1 INTO cnumber;
16     if c1%notfound then
17        cnumber := 9999;
18     else
19        UPDATE courses_tbl
20          SET instructor = SMITH21          WHERE CURRENT OF c1;
22        COMMIT;
23     end if;
24     CLOSE c1;
25  RETURN cnumber;
26  END;
27  
28  (2)Deleting using the WHERE CURRENT OF Statement
29  CREATE OR REPLACE Function FindCourse
30     ( name_in IN varchar2 )
31     RETURN number
32  IS
33     cnumber number;
34     CURSOR c1
35     IS
36       SELECT course_number
37       from courses_tbl
38       where course_name = name_in
39       FOR UPDATE of instructor;
40  BEGIN
41     open c1;
42     fetch c1 into cnumber;
43     if c1%notfound then
44        cnumber := 9999;
45     else
46        DELETE FROM courses_tbl
47          WHERE CURRENT OF c1;
48        COMMIT;
49     end if;
50     close c1;
51  RETURN cnumber;
52  END;

                                                                                  回到顶部
 

PLSQL NOTE----cursor

标签:

原文地址:http://www.cnblogs.com/ct-blog/p/5056949.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!