如何管理PL/SQL游标属性_SQL%FOUND与SQL%NOTFOUND判断

轻枫小哥_8471

轻枫小哥_8471

2026-03-24

597人浏览

原创

SQL%FOUND和SQL%NOTFOUND判断上一条DML或SELECT INTO是否影响至少一行;显式游标须用c1%FOUND/c1%NOTFOUND,且循环中应FETCH后立即EXIT WHEN c1%NOTFOUND。

SQL%FOUND 和 SQL%NOTFOUND 到底在判断什么

它们不是在判断“游标有没有打开”或“结果集是否为空”,而是在判断**上一条 dml 或 select into 语句是否影响了至少一行数据**。也就是说,sql%found 和 sql%notfound 是隐式游标的属性,跟显式声明的 declare cursor ... 游标无关——除非你用的是 select into 这种单行查询。

常见错误现象:
– 显式游标循环中直接写 IF SQL%FOUND THEN ...,结果永远为 FALSE(因为 FETCH 不改变隐式游标状态);
– 在 OPEN c1; FETCH c1 INTO ...; 后立刻查 SQL%FOUND,但此时它反映的是前一条非游标语句(比如前面的 UPDATE)的结果。

  • SQL%FOUND 为 TRUE 当且仅当上一条 INSERT/UPDATE/DELETE 或 SELECT INTO 影响了 ≥1 行
  • SQL%NOTFOUND 是 SQL%FOUND 的逻辑反,但注意:对 SELECT INTO,没查到会抛 NO_DATA_FOUND 异常,根本走不到判断这步
  • 显式游标要用自己的属性,比如 c1%FOUND、c1%NOTFOUND,别混用 SQL% 前缀

显式游标该用 c1%FOUND 还是 c1%NOTFOUND 做循环退出条件

用 c1%NOTFOUND 更安全。因为 FETCH 每次只取一行,取完后游标位置停在“下一行尚未读取”的状态;只有当 FETCH 尝试读取却无数据可读时,c1%NOTFOUND 才变为 TRUE。

常见错误现象:
– 写成 EXIT WHEN c1%FOUND,导致只处理第一行就退出;
– 在 FETCH 前就检查 c1%NOTFOUND,此时恒为 FALSE(游标刚打开,还没取过数据)。

  • 标准写法是:先 FETCH c1 INTO ...,再立即 EXIT WHEN c1%NOTFOUND
  • 不要在 FETCH 前判断,也不要把它放在循环条件里(比如 WHILE NOT c1%NOTFOUND LOOP),容易漏最后一行
  • c1%FOUND 可用于确认本次 FETCH 是否成功取到数据,但不建议作为主循环退出依据

SELECT INTO + SQL%NOTFOUND 能不能替代显式游标

能,但只适用于**预期最多一行**的场景。一旦可能返回多行,SELECT INTO 会直接报 TOO_MANY_ROWS 错误,程序中断。

使用场景:
– 验证主键是否存在(SELECT id INTO v_id FROM t WHERE pk = ?);
– 查询配置项、单条状态记录等确定性单行结果。

  • 如果 SELECT INTO 没查到,会触发 NO_DATA_FOUND 异常,SQL%NOTFOUND 根本不会被执行到
  • 想安全捕获“没查到”,必须用 EXCEPTION WHEN NO_DATA_FOUND THEN ...,而不是依赖 SQL%NOTFOUND
  • 性能上,SELECT INTO 比显式游标开销略小(省去 OPEN/CLOSE),但差别微乎其微,别为此牺牲可读性

PL/SQL 中游标属性的兼容性陷阱

不同 Oracle 版本对游标属性行为基本一致,但有两处容易被忽略:

  • %ROWCOUNT 在 OPEN 后为 0,FETCH 第一次后才变成 1;但 SQL%ROWCOUNT 在 SELECT INTO 前是未定义的,执行后才是 1 或报错
  • 动态 SQL(EXECUTE IMMEDIATE)执行 SELECT INTO 后,SQL%FOUND 可用;但执行 OPEN ... FOR 动态查询后,得到的是显式游标,得用 cur%FOUND,不是 SQL%
  • 包内游标变量(SYS_REFCURSOR)没有 %FOUND 属性,只能靠 FETCH 后的 SQL%ROWCOUNT 或额外计数器判断是否还有数据

最常被绕过的点:把显式游标和隐式游标的状态混在一起理解,以为 SQL% 系列能反映任意游标动作——其实它只忠于最后那条非游标 DML 或 SELECT INTO 语句。

PHP速学视频免费教程(入门到精通)
PHP速学视频免费教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
数据分析工具有哪些
数据分析工具有哪些

数据分析工具有Excel、SQL、Python、R、Tableau、Power BI、SAS、SPSS和MATLAB等。详细介绍:1、Excel,具有强大的计算和数据处理功能;2、SQL,可以进行数据查询、过滤、排序、聚合等操作;3、Python,拥有丰富的数据分析库;4、R,拥有丰富的统计分析库和图形库;5、Tableau,提供了直观易用的用户界面等等。

2023.10.12

4283

8

SQL中distinct的用法
SQL中distinct的用法

SQL中distinct的语法是“SELECT DISTINCT column1, column2,...,FROM table_name;”。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2023.10.27

891

4

SQL中months_between使用方法
SQL中months_between使用方法

在SQL中,MONTHS_BETWEEN 是一个常见的函数,用于计算两个日期之间的月份差。想了解更多SQL的相关内容,可以阅读本专题下面的文章。

2024.02.23

1109

5

SQL出现5120错误解决方法
SQL出现5120错误解决方法

SQL Server错误5120是由于没有足够的权限来访问或操作指定的数据库或文件引起的。想了解更多sql错误的相关内容,可以阅读本专题下面的文章。

2024.03.06

6201

10

sql procedure语法错误解决方法
sql procedure语法错误解决方法

sql procedure语法错误解决办法:1、仔细检查错误消息;2、检查语法规则;3、检查括号和引号;4、检查变量和参数;5、检查关键字和函数;6、逐步调试;7、参考文档和示例。想了解更多语法错误的相关内容,可以阅读本专题下面的文章。

2024.03.06

3043

4

oracle数据库运行sql方法
oracle数据库运行sql方法

运行sql步骤包括:打开sql plus工具并连接到数据库。在提示符下输入sql语句。按enter键运行该语句。查看结果,错误消息或退出sql plus。想了解更多oracle数据库的相关内容,可以阅读本专题下面的文章。

2024.04.07

6160

11

sql中where的含义
sql中where的含义

sql中where子句用于从表中过滤数据,它基于指定条件选择特定的行。想了解更多where的相关内容,可以阅读本专题下面的文章。

2024.04.29

8341

6

sql中删除表的语句是什么
sql中删除表的语句是什么

sql中用于删除表的语句是drop table。语法为drop table table_name;该语句将永久删除指定表的表和数据。想了解更多sql的相关内容,可以阅读本专题下面的文章。

2024.04.29

1130

5

sql中删除一列的命令是什么
sql中删除一列的命令是什么

在sql中,使用alter table语句可以删除一列,语法为:alter table table_name drop column column_name。想了解更多sql的相关内容,可以阅读本专题下面的文章。

2024.04.29

992

5

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
热门推荐
/
最新课程
phpStudy极速入门视频教程
phpStudy极速入门视频教程

共6课时 | 54.7万人学习

独孤九贱(4)_PHP视频教程
独孤九贱(4)_PHP视频教程

共89课时 | 133.7万人学习