如何检查 SYS_REFCURSOR 是否为空

how to check if SYS_REFCURSOR is empty

我有一个通用的SYS_REFCURSOR,我想检查它是否为空。

代码是这样的:

declare
    v_cursor SYS_REFCURSOR;
begin
   OPEN v_cursor FOR <any select statement>.
   check if v_cursor is empty.
end;

有人能告诉我如何检查弱游标是否为空吗? 我必须提到基本 SELECT 语句可以是任何 table 中的任何内容。 列号或类型仅在运行时已知。

谢谢,

尝试获取一行然后使用v_cursor%NOTFOUND确定游标为空:

DECLARE
    v_cursor SYS_REFCURSOR;
    v_value  DUAL.DUMMY%TYPE;
BEGIN
   OPEN v_cursor FOR SELECT DUMMY FROM DUAL WHERE 1 = 0;
   FETCH v_cursor INTO v_value;
   IF v_cursor%NOTFOUND THEN
     DBMS_OUTPUT.PUT_LINE('Cursor empty');
   ELSE
     DBMS_OUTPUT.PUT_LINE('Cursor not empty');
   END IF;
END;
/

DECLARE
  CURSOR v_cursor IS
    SELECT DUMMY FROM DUAL WHERE 1 = 0;
  v_row v_cursor%ROWTYPE;
BEGIN
  OPEN v_cursor;
  FETCH v_cursor INTO v_row;
  IF v_cursor%NOTFOUND THEN
    DBMS_OUTPUT.PUT_LINE('Cursor empty');
  ELSE
    DBMS_OUTPUT.PUT_LINE('Cursor not empty');
  END IF;
END;
/

双输出:

Cursor empty

db<>fiddle here

您无法查看引用游标是否包含数据而不从中提取数据并消耗至少一行。

如果您确实需要在打开游标时确定这一点,而不知道此时的结构,您可以执行修改后的查询,该查询只计算您的真实查询返回的行数 - 可能仅限于单个row if that helps performance - 作为一个简单的 execute immediate ... into ... 或单独的 open/fetch/close 以保持一致性;类似于:

declare
  v_cursor SYS_REFCURSOR;
  v_query VARCHAR2(4000);
  v_count PLS_INTEGER;
begin
  v_query := <any select statement>;

  -- see if the query finds any data
  OPEN v_cursor FOR 'select count(*) from (' || v_query || ')'; -- could limit rows
  FETCH v_cursor INTO v_count;
  CLOSE v_cursor;
  if v_count = 0 then
    dbms_output.put_line('No data');
    return;
  end if;
  
  dbms_output.put_line('Found data, opening cursor for real');
  OPEN v_cursor FOR v_query;
  -- loop over results, return to caller, etc.
end;
/

db<>fiddle