PL/SQL-->隐式游标(SQL%FOUND)

PL/SQL-->隐式游标(SQL%FOUND)
      在PL/SQL中,游标的使用分为两种,一种是显式游标,一种是隐式游标,显式游标的使用需要事先使用declare来进行声明,其过程包括声明游标,打开游标,从游标提取数据,关闭游标。
      显式游标多用于处理select语句返回的多行数据的情形。
      隐式游标则由则由系统自动定义,当使用DML时,Oracle为每一个不属于显式游标的DML语句都创建一个隐式游标,其声明、打开、关闭都是系统自动进行。
      隐式游标多用于配合DML返回单行数据。

一、隐式游标的定义及其属性

      定义

              隐式游标由系统自动定义,非显式定义游标的DML语句即被赋予隐式游标属性,其过程由oracle控制,完全自动化。
            隐式游标的名称是SQL,不能对SQL游标显式地执行OPEN,FETCH,CLOSE语句。

      属性

              类似于显式游标,隐式游标同样具有四种属性,只不过隐式游标以SQL%开头,而显式游标以Cursor_name%开头
              通过SQL%只能访问前一个DML操作或单行SELECT操作的游标属性,用于判断DML执行的状态和结果,进而控制程序的流程

              SQL%ISOPEN     
                      判断游标是否打开。当执行select into ,insert,update,delete时,Oracle会隐含地打开游标,且在该语句执行完毕后隐含地关闭
游标,因为是隐式游标,故SQL%ISOPEN总是false   

              SQL%FOUND           
                      判断SQL语句是否成功执行。当有作用行时则成功执行为true,否则为false。

              SQL%NOTFOUND     
                      判断SQL语句是否成功执行。当有作用行时其值为false,否则其值为true。

              SQL%ROWCOUNT   
                      在执行任何DML语句之前,SQL%ROWCOUNT的值都是NULL,对于SELECT INTO语句,如果执行成功,SQL%ROWCOUNT的值为1,如果没有
                      成功,SQL%ROWCOUNT的值为0,同时产生一个异常NO_DATA_FOUND。

二、演示

      1.SQL%FOUND的使用

              DECLARE
                  v_empno emp.empno%TYPE:=&no;
              BEGIN
                  UPDATE emp SET sal=sal 200        --根据给定的empno,更新一条记录
                  WHERE empno=v_empno;
                  IF SQL%FOUND THEN                          --使用SQL游标属性SQL%FOUND作为判断条件
                      COMMIT;
                      DBMS_OUTPUT.PUT_LINE('SQL code is executed successful');
                  ELSE
                      DBMS_OUTPUT.PUT_LINE('The Employee is not exist');
                      ROLLBACK;
                  END IF;
              END;

              Enter value for no: 7788
              old    2:    v_empno emp.empno%TYPE:=&no;
              new    2:    v_empno emp.empno%TYPE:=7788;
              SQL code is executed successful
              PL/SQL procedure successfully completed
           
      2.SQL游标的综合应用(根据SQL游标的不同属性返回不同的结果)

              DECLARE
                  v_dept emp.deptno%TYPE := &no;
              BEGIN
                  IF SQL%ROWCOUNT >= 0 THEN  --判断更新前SQL%ROWCOUNT的属性
                      DBMS_OUTPUT.PUT_LINE('SQL%ROWCOUNT value is ' || SQL%ROWCOUNT ||
                                                                'before updated');
                  ELSE
                      DBMS_OUTPUT.PUT_LINE('SQL%ROWCOUNT value is NULL before updated');
                  END IF;

                  UPDATE emp SET sal = sal 200 WHERE deptno = v_dept;

                  IF SQL%FOUND THEN      --判断SQL%FOUND的属性
                      DBMS_OUTPUT.PUT_LINE('SQL code is executed successful');
                      DBMS_OUTPUT.PUT_LINE('SQL%Found is TRUE');
                  ELSE
                      DBMS_OUTPUT.PUT_LINE('No such department');
                      DBMS_OUTPUT.PUT_LINE('SQL%Found is FALSE');
                  END IF;

                  IF SQL%NOTFOUND THEN      --判断SQL%NOTFOUND的属性
                      DBMS_OUTPUT.PUT_LINE('SQL%NotFound is TRUE');
                  ELSE
                      DBMS_OUTPUT.PUT_LINE('SQL%NotFound is FALSE');
                  END IF;

                  IF SQL%ISOPEN THEN      --判断SQL%ISOPEN的属性
                      DBMS_OUTPUT.PUT_LINE('SQL%ISOPEN is TRUE');
                  ELSE
                      DBMS_OUTPUT.PUT_LINE('SQL%ISOPEN is FALSE');
                  END IF;
             
                  DBMS_OUTPUT.PUT_LINE('The rows updated is :' || SQL%ROWCOUNT ||
                                                            ' rows by SQL Cursor'); --判断SQL%ROWCOUNT的属性
              END;

              Enter value for no: 10    --下面是成功更新后的结果
              SQL%ROWCOUNT value is NULL before updated
              SQL code is executed successful
              SQL%Found is TRUE
              SQL%NotFound is FALSE
              SQL%ISOPEN is FALSE
              The rows updated is :3 rows by SQL Cursor

              Enter value for no: 80    --下面是未成功更新后的结果
              SQL%ROWCOUNT value is NULL before updated
              No such department
              SQL%Found is FALSE
              SQL%NotFound is TRUE
              SQL%ISOPEN is FALSE
              The rows updated is :0 rows by SQL Cursor   

      3.SELECT INTO时,隐式游标的使用

              SELECT INTO用于将单行结果集放置到变量之中。
              SELECT INTO处理的结果包括以下情况
                      查询结果返回单行,SELECT INTO被成功执行
                      查询结果没有返回行,PL/SQL将抛出no_data_found异常
                      查询结果返回多行,PL/SQL将抛出too_many_rows 异常
              对于上述两种异常发生时,类似于普通异常处理,程序控制权转移到异常处理部分(如没有异常处理则程序中断)。
            异常被激发后,SQL游标的四个属性在此将不可使用,如下面的例子:

                      DECLARE
                          v_ename emp.ename%TYPE;
                      BEGIN
                          SELECT ename INTO v_ename FROM emp WHERE empno=&no;
                          IF  SQL%ROWCOUNT=0 OR SQL%NOTFOUND THEN
                              DBMS_OUTPUT.PUT_LINE('The record '||&no||' is not exist!');
                          ELSE
                              DBMS_OUTPUT.PUT_LINE('The name for record '||&no||' is '||v_ename );
                          END IF;
                      EXCEPTION  
                          WHEN NO_DATA_FOUND THEN
                              DBMS_OUTPUT.PUT_LINE('No data found for '||&no);
                      END;             

                      Enter value for no:70
                      No data found for 70

                      Enter value for no:7788
                      The name for record 7788 is SCOTT

              从上面的演示中可以看到,当select into没有返回行时,IF  SQL%ROWCOUNT=0 OR SQL%NOTFOUND THEN 语句并没有被执行。

              使用下面改进过的代码来执行,即可以将SQL游标属性判断放置到EXCEPTION部分

                      DECLARE
                          v_ename emp.ename%TYPE;
                      BEGIN
                          SELECT ename INTO v_ename FROM emp WHERE empno=&no;
                          IF SQL%NOTFOUND THEN
                              DBMS_OUTPUT.PUT_LINE('The record '||&no||' is not exist!');
                          ELSE
                              DBMS_OUTPUT.PUT_LINE('The name for record '||&no||' is '||v_ename );
                          END IF;
                      EXCEPTION  
                          WHEN NO_DATA_FOUND THEN
                              IF SQL%NOTFOUND THEN
                                  DBMS_OUTPUT.PUT_LINE('The record '||&no||' is not exist!');
                                  DBMS_OUTPUT.PUT_LINE('No data found for '||&no);
                              ELSE
                                  DBMS_OUTPUT.PUT_LINE('The name for record '||&no||' is '||v_ename );
                              END IF;
                      END;
                      Enter value for no:80
                      The record 80 is not exist!
                      No data found for 80     

              更多关于隐式游标的探讨,请参考:IMPLICIT CURSOR ATTRIBUTE SQL%NOTFOUND NOT WORKING  

转自:http://blog.csdn.net/robinson_0612/article/details/6092066
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值