如何检测获取游标是否返回任何值?

How to detect if fetch cursor returned no value?

我有这个:

declare
  toStoreA varchar2(10);
  toStoreB varchar2(10);
  toStoreC varchar2(10);

  cursor c1 is
    select a, b, c
    from table1
    where login = 'myLogin';
begin
  open  c1;
  fetch c1 into toStoreA,
                toStoreB,
                toStoreC
  close c1;

  if toStoreB = NULL then
    dbms_output.put_line('OK, we are in if, toStoreB is null');
  end if;

  dbms_output.put_line('toStoreA:' || toStoreA || '_');
  dbms_output.put_line('toStoreB:' || toStoreB || '_');
  dbms_output.put_line('toStoreC:' || toStoreC || '_');
end;

我的目标是检测 fetch cursor 是否没有返回任何值。

如果我在 sql window 中查询我的 sql 语句,我将得到:

> select a, b, c from table1 where login = 'myLogin';
++++++++++++++++++++++++++++++++++++++++++++
+ some val +               +               +
++++++++++++++++++++++++++++++++++++++++++++

这是我在 DBMS 输出中得到的 window:

toStoreA:some val_
toStoreB:_ 
toStoreC:_

如您所见,我在 DBMS 输出中没有得到字符串 OK, we are in if, toStoreB is null。为什么?好吧,很明显如果没有通过。问题是如何正确检查 fetch cursor 是否返回 null 值(无值)?

我也试过 if toStoreB = '' then 但没有用。

你不能用相等来测试 null; null 永远不等于(或 not 等于)任何东西,包括它自己。并且空字符串 '' 与 null 无法区分,因此您也不能对其使用相等性测试。 See the explanation in the documentation. You can fix the immediate problem by using the is null operator 改为:

  if toStoreB is NULL then

有了这个改变,你会看到:

anonymous block completed
OK, we are in if, toStoreB is null
toStoreA:some val_
toStoreB:_
toStoreC:_

最初我对这个问题有一点误解,以为你的意思是你想检查提取是否没有返回任何行,而不是特定列没有值;所以其余部分并不直接相关。如果您总是期待单行,那么您可以使用 select into ... 而不是命名游标;但是使用游标,您可以更灵活地测试获取的内容...

这只是告诉你,如果 b 不能为 null,则 fetch 没有找到任何东西;即使您现在认为是这种情况,也不是您必须依赖的东西,也不是通用解决方案。

您可以使用 the `%notfound' cursor attribute:

检查是否已获取任何内容
  open  c1;
    fetch c1 into toStoreA,
                  toStoreB,
                  toStoreC;
    if c1%notfound then
      dbms_output.put_line('No row was fetched');
    end if;
  close c1;

请注意,在关闭游标之前必须检查它,通常是在获取之后立即检查。如果在 close 之后尝试检查它会出错。一旦检索到所有数据,这通常用于中断获取循环。

因此,通过更改和未找到任何数据的修改后的查询,您会看到:

anonymous block completed
No row was fetched
OK, we are in if, toStoreB is null
toStoreA:_
toStoreB:_
toStoreC:_