设为首页 收藏本站
查看: 402|回复: 0

[经验分享] PL/SQL -->隐式游标(SQL%FOUND)

[复制链接]
累计签到:1 天
连续签到:1 天
发表于 2014-7-9 09:28:54 | 显示全部楼层 |阅读模式
--===============================
-- PL/SQL -->隐式游标(SQL%FOUND)
--===============================
    在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
            


运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-21850-1-1.html 上篇帖子: PL/SQL --> 游标 下篇帖子: 批量 SQL 之 FORALL 语句
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表