PLSQL中%NOTFOUND简单测试案例未按预期工作问题
Oracle游标%NOTFOUND属性使用误区
问题核心在于:游标刚打开时,%NOTFOUND属性不会立即反映结果集是否为空。
当你执行OPEN c_dual2;后,Oracle仅初始化了游标对应的结果集,但并未从结果集中获取任何数据。此时c_dual2%NOTFOUND的值为NULL,而PL/SQL的IF判断会将NULL视为FALSE,因此会执行ELSE分支,输出"2 is found",这和实际结果集为空的情况不符。
要正确判断游标是否返回数据,必须先执行一次FETCH操作,让游标移动到结果集的第一行,之后%NOTFOUND属性才会正确反映是否存在数据。
修正后的代码示例
DECLARE CURSOR c_dual1 IS SELECT 1 FROM DUAL WHERE 1=1; CURSOR c_dual2 IS SELECT 1 FROM DUAL WHERE 1=2; v_num NUMBER; -- 用于存储FETCH的结果 BEGIN OPEN c_dual1; FETCH c_dual1 INTO v_num; -- 先获取第一行数据 IF c_dual1%NOTFOUND THEN DBMS_OUTPUT.PUT_LINE ('1 is not found'); ELSE DBMS_OUTPUT.PUT_LINE ('1 is found'); END IF; CLOSE c_dual1; OPEN c_dual2; FETCH c_dual2 INTO v_num; -- 先获取第一行数据 IF c_dual2%NOTFOUND THEN DBMS_OUTPUT.PUT_LINE ('2 is not found'); ELSE DBMS_OUTPUT.PUT_LINE ('2 is found'); END IF; CLOSE c_dual2; END;
执行上述代码后,会得到你预期的输出:
1 is found 2 is not found
更简洁的替代写法
如果只是判断简单查询是否有结果,也可以直接用COUNT(*)查询,不需要显式游标:
DECLARE v_count NUMBER; BEGIN SELECT COUNT(*) INTO v_count FROM DUAL WHERE 1=1; DBMS_OUTPUT.PUT_LINE (CASE WHEN v_count = 0 THEN '1 is not found' ELSE '1 is found' END); SELECT COUNT(*) INTO v_count FROM DUAL WHERE 1=2; DBMS_OUTPUT.PUT_LINE (CASE WHEN v_count = 0 THEN '2 is not found' ELSE '2 is found' END); END;
内容的提问来源于stack exchange,提问作者Chad
相关产品推荐
相关产品推荐

