This question提出了一个非常有趣的观点;在Oracle文档中似乎存在一个矛盾,即在获取后%NOTFOUND
是否可能为空。是吗?
注意:在例6-16中,如果FETCH从不提取行,则c1%NOTFOUND 始终为NULL并且永远不会退出循环。防止无限 循环,改为使用此EXIT语句:EXIT WHEN c1%NOTFOUND OR (c1%NOTFOUND为空);
文档似乎直接与自身相矛盾,因为它还说明了以下内容,这意味着在获取%NOTFOUND
之后 不能为空。
%NOTFOUND(%FOUND的逻辑反面)返回:
显式游标打开后但在第一次获取之前为NULL 如果最近从显式游标中获取的行返回了一行,则为FALSE 否则为
10g documentation有一个类似的警告,这不一定是直接的矛盾,因为它警告说,为了展示这种行为,获取可能无法成功执行。
在第一次获取之前,%NOTFOUND的计算结果为NULL。如果FETCH永远不会 执行成功后,EXIT WHEN条件永远不会为TRUE而且 循环永远不会退出。为安全起见,您可能需要使用以下内容 改为EXIT语句:
当c1%NOTFOUND或c1%NOTFOUND为空时退出;
在fetch执行后,在什么情况下获取“失败”或者%NOTFOUND
可能会返回null?
答案 0 :(得分:7)
我可以找到提取失败的情况:
declare
i integer;
cursor c is
select 1 / 0 from dual;
begin
open c;
begin
fetch c
into i;
exception
when others then
dbms_output.put_line('ex');
end;
if c%notfound is null then
dbms_output.put_line('null');
elsif c%notfound then
dbms_output.put_line('true');
else
dbms_output.put_line('false');
end if;
close c;
end;
但是这只会使你的问题变得更强,因为它会在10g或11g中评估为null ...
答案 1 :(得分:0)
我认为绊倒你的部分是:
如果FETCH从未成功执行,则EXIT WHEN条件永远不会为TRUE,并且永远不会退出循环。
过去的某个地方肯定有一个代码示例,如下所示:
LOOP
FETCH c1 INTO name;
EXIT WHEN c1%NOTFOUND;
-- Do stuff
END LOOP;
鉴于这段代码,声明仍然是真的。如果提取从未执行(失败),则%NOTFOUND将为null。 EXIT WHEN
条件不会计算为TRUE(null计算结果为false)。然后,确实,循环将永远持续。
答案 2 :(得分:-1)
这种情况很容易测试:
SET SERVEROUT ON;
DECLARE
-- this cursor returns a single row
CURSOR c1 IS
SELECT 1 FROM dual WHERE rownum = 1;
-- this cursor returns no rows
CURSOR c2 IS
SELECT 1 FROM dual WHERE 1=0;
v1 number;
BEGIN
OPEN c1;
FETCH c1 INTO v1; -- this returns a record
FETCH c1 INTO v1; -- this does not return a record
IF c1%NOTFOUND THEN
dbms_output.put_line('c1%NOTFOUND: TRUE');
ELSIF c1%NOTFOUND IS NULL THEN
dbms_output.put_line('c1%NOTFOUND: NULL');
ELSE
dbms_output.put_line('c1%NOTFOUND: FALSE');
END IF;
CLOSE c1;
OPEN c2;
FETCH c2 INTO v1; -- this does not return a record
IF c2%NOTFOUND THEN
dbms_output.put_line('c2%NOTFOUND: TRUE');
ELSIF c2%NOTFOUND IS NULL THEN
dbms_output.put_line('c2%NOTFOUND: NULL');
ELSE
dbms_output.put_line('c2%NOTFOUND: FALSE');
END IF;
CLOSE c2;
END;
/
Oracle APEX 4.1上脚本的输出是(我认为APEX运行的是Oracle 11gR2,但您可以在任何版本上轻松运行脚本):
c1%NOTFOUND: TRUE
c2%NOTFOUND: TRUE
根据此测试,执行fetch后%NOTFOUND
不会为NULL。这与10g和11g文档在%NOTFOUND
属性的初始描述中所述的内容相匹配。关于循环永远不会退出的注释必须来自该示例的旧版本。由于它只是一个注释,我说可以安全地信任初始描述并忽略该注释。