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

--===============================

-- 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

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

三、更多参考

有关SQL请参考

SQL 基础--> 子查询

SQL 基础-->多表查询

SQL基础-->分组与分组函数

SQL 基础-->常用函数

SQL 基础--> ROLLUP与CUBE运算符实现数据汇总

SQL基础-->层次化查询(START BY ... CONNECT BY PRIOR)

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏闻道于事

PL/SQL 编程(二)游标、存储过程、函数

游标--数据的缓存区 游标:类似集合,可以让用户像操作数组一样操作查询出来的数据集,实质上,它提供了一种从集合性质的结果中提取单条记录的手段。 可以将游标形象的...

4906
来自专栏杨建荣的学习笔记

深度解析dba_segments和sys.seg$中的细节差异(上) (r5笔记第27天)

今天在查看系统空间使用情况的时候,发现一个细节的问题,自己死磕了一把,还是发现了不少有价值的东西。 事情的起因是我在使用脚本在某个环境中查看每个用户所占有的空间...

3548
来自专栏JAVA后端开发

结合swagger,实现shiro权限资源的导入功能

做shiro权限控制时,shiro的权限RequiresPermissions都写在Controller的方法内,如果做动态的权限管理时,每个shiro的权限资...

2644
来自专栏安恒网络空间安全讲武堂

Sqli_labs65关通关详解(上)

Less-1 这个题目是基于错误,单引号,字符型注入, http://127.0.0.1/sqli/Less-1/?id=1' //报错 http://...

6466
来自专栏杨建荣的学习笔记

使用awk来解析dump文件 (73天)

dump文件是平时工作中经常碰见的,有时候得到一个dump,但是没有提供一些更多的信息,导入的时候就很可能会有问题。 如果某个用户默认表空间是user,但是du...

4178
来自专栏乐沙弥的世界

FORALL 之 SAVE EXCEPTIONS 子句应用一例

     对于大批量的DML操作中出现的错误,除了使用DML error logging特性来记录在DML期间出现的错误之外,使用批量SQL语句FORALL的S...

661
来自专栏乐沙弥的世界

Oracle 回滚(ROLLBACK)和撤销(UNDO)

Oracle使用数据库中的回滚段来实现未提交数据或因系统故障导致实例崩溃时进行回滚操作

1281
来自专栏杨建荣的学习笔记

原来Oracle也不喜欢“蜀黍"(r6笔记第54天)

今天在部署一个脚本的时候,碰到了一个奇怪的问题,脚本运行过程中报了一个ora错误 ORA-01756: quoted string not properly t...

2795
来自专栏杨建荣的学习笔记

ORA-01427问题的分析和解决(r6笔记第51天)

前几天开发的同事反馈一个问题,说前台系统报出了ORA错误,希望我们能看看是什么原因。 java.sql.SQLException: ORA-01427: sin...

2754
来自专栏乐沙弥的世界

PL/SQL-->UTL_FILE包的使用介绍

    在PL/SQL中,UTL_FILE包提供了文本文件输入和输出互功能。也就是说我们可以通过该包实现从操作系统级别来实现文件读取输入或者是写入到操作系统文件...

831

扫码关注云+社区

领取腾讯云代金券