显式游标必须用 CURSOR 关键字声明,漏写会导致 PLS-00103 编译错误;其本质是用户定义的命名查询,需 OPEN/FETCH/CLOSE 成对使用,循环结束判断应依赖 %NOTFOUND 而非 %ROWCOUNT。 显式游标必须用 CURSOR 关键字声明,不能只写 DECLARE c1
CURSOR 关键字声明,不能只写 DECLARE c1在 Oracle PL/SQL 的世界里,显式游标和隐式游标完全是两码事。简单来说,前者是开发者自己定义并命名的查询,后者则由 SQL 引擎在幕后自动打理。如果漏掉了那个关键的 CURSOR 关键字,编译器可不会客气,直接就会抛出 PLS-00103: encountered the symbol "is" 之类的语法错误。
一个常见的误区,是把显式游标当成普通变量来声明。比如写成 DECLARE c1 SYS_REFCURSOR; —— 这其实声明的是一个游标变量(REF CURSOR),属于动态游标的范畴,并非我们这里讨论的静态显式游标。更典型的错误是写成 DECLARE c1 IS SELECT ...,直接少了 CURSOR,语法上根本行不通。
长期稳定更新的攒劲资源: >>>点此立即查看<<<
CURSOR c1 IS SELECT empno, ename FROM emp WHERE deptno = 10; 这才是正确的声明方式。DECLARE c1 SYS_REFCURSOR; → 这种声明之后,需要用 OPEN c1 FOR ... 来动态关联 SQL,它属于另一种游标类型。PLS-00320 错误。OPEN/FETCH/CLOSE 必须成对出现,且 FETCH 前必须 OPEN显式游标的工作机制需要明确:它不是“一打开就自动把所有数据都给你”,而是通过 OPEN 操作定位到结果集的起点,然后每次执行 FETCH 才获取一行数据并向前移动。如果没执行 OPEN 就直接 FETCH,会引发运行时异常 ORA-01001: invalid cursor。至于 CLOSE,虽然忘记关闭不一定会立刻报错,但在长期运行的程序(尤其是包中反复调用)里,可能会逐渐耗尽数据库的游标资源,这可是个隐藏的性能杀手。
OPEN c1;,然后才能 FETCH c1 INTO v_empno, v_ename;。%NOTFOUND 属性,而不是 %ROWCOUNT。CLOSE c1; 应该放在所有数据获取完毕之后,稳妥起见,最好在异常处理分支中也加上关闭操作。OPEN 和 CLOSE 同一个游标,这种写法对性能很不友好。OPEN 传参顺序和类型必须严格匹配声明给显式游标加上参数(比如 CURSOR c1(p_deptno NUMBER) IS SELECT ... WHERE deptno = p_deptno;)能让它更灵活,看起来有点像函数。但调用时可得小心:它没有智能的类型推导,完全依赖参数的位置和声明的类型严格匹配。如果顺序错了或者类型不兼容,编译阶段可能发现不了,但运行时要么查不到数据,要么就因隐式转换失败而报错。
OPEN c1(10); 这样传参,完美匹配 p_deptno NUMBER 的声明。OPEN c1('10'); → 虽然字符串‘10’通常能隐式转成数字,但如果字段是 VARCHAR2 且包含了字母,那麻烦就来了。name => value)的语法。FETCH 后直接用 %ROWCOUNT 判断是否取到数据这里有个细节很容易踩坑:%ROWCOUNT 属性返回的是自游标打开后,成功 FETCH 到的行数累计值。在第一次 FETCH 之前,它是0;成功取到第一行后,它就变成1。问题在于,你无法单纯通过这个数值来区分“刚刚成功取到第一行数据”和“已经取完所有数据、最后一次 FETCH 失败了”这两种情况。真正可靠、用于判断循环是否应该结束的“信号灯”,是 %NOTFOUND 属性。
IF c1%ROWCOUNT = 0 THEN ... —— 即使游标里确实有数据,但只要还没执行 FETCH,%ROWCOUNT 就一直是0,这并不能证明结果集为空。FETCH c1 INTO ...; EXIT WHEN c1%NOTFOUND; 这才是控制循环退出的标准写法。%FOUND 和 %NOTFOUND 这两个属性,只有在执行了一次 FETCH 操作后才有效,在首次 FETCH 之前,它们的状态是未定义的。FETCH 就会立即将 %NOTFOUND 置为 TRUE,这个过程不会抛出任何异常。在实际编码中,最容易疏忽的两点,恰恰是异常处理路径里忘记 CLOSE 游标,以及参数传递时的隐式类型转换——代码可能在某些测试数据下运行良好,一旦换一套数据,就可能瞬间崩溃,值得高度警惕。
侠游戏发布此文仅为了传递信息,不代表侠游戏网站认同其观点或证实其描述