PL/SQL 隐式游标

哈哈 今天了解了下sql%rowcount  感觉很多地方很有用哈  

以下是部分

sql%rowcount用于记录修改的条数,就如你在sqlplus下执行delete from之后提示已删除xx行一样, 这个参数必须要在一个修改语句和commit之间放置,否则你就得不到正确的修改行数。
例如:
SQL> declare n number;
  2  begin
  3  insert into test_a select level lv from dual connect by level<500;
  4  n:=sql%rowcount;
  5  commit;
  6  dbms_output.put_line(n);
  7  end;
  8  /
499

PL/SQL procedure successfully completed.
SQL> declare n number;
  2  begin
  3  insert into test_a select level lv from dual connect by level<500;
  4  commit;
  5  n:=sql%rowcount;
  6  dbms_output.put_line(n);
  7  end;
  8  /
0

PL/SQL procedure successfully completed.

 这里提到select语句是用不了sql%rowcount的  所以我又去找了下 

 找到http://blog.csdn.net/robinson_0612/article/details/6092066 

 嗯  这个比较多  MARK下哈

在PL/SQL中,游标的使用分为两种,一种是显示游标,一种是隐式游标,显示游标的使用需要事先使用declare来进行声明,其过程包括

声明游标,打开游标,从游标提取数据,关闭游标。该方式多用于处理select语句返回的多行数据的情形。而隐式游标则由则由系统自动定义

,当DML被使用时,Oracle为每一个不属于显示游标的DML语句都创建一个隐式游标,其声明、打开、关闭都是系统自动进行。多用于配合DML

返回单行数据的处理。

 有关显示游标的使用,请参考:PL/SQL --> 游标



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

 定义

 隐式游标则由则由系统自动定义,非显示定义游标的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的值为,如果没有

 成功,SQL%ROWCOUNT的值为,同时产生一个异常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

 





  

posted @ 2012-02-24 11:32  lavandachen  阅读(332)  评论(0编辑  收藏  举报