Oracle PL/SQL将循环中的值收集到游标中

bmvo0sr5  于 2023-05-16  发布在  Oracle
关注(0)|答案(2)|浏览(117)

我有一个包含文档ID的PL/SQL TABLE TYPE结果集。
我可以毫无问题地循环结果集,但问题是我必须从函数返回sys_refcursor,但我无法将循环中的值收集到游标中。

TYPE table_typ IS TABLE OF DOCUMENT_QUEUE.ENV_ID%TYPE INDEX BY PLS_INTEGER;

FUNCTION GET_DOCS()
RETURN SYS_REFCURSOR
IS
   LS_CUR SYS_REFCURSOR;
   LR_UPDATED_ROWS table_typ;
BEGIN
      UPDATE DOCUMENT_QUEUE DQ
      ...
      RETURNING DQ.ENV_ID BULK COLLECT INTO LR_UPDATED_ROWS;               

      -- Need to collect all of the following rows into the cursor
      FOR indx IN NVL (LR_UPDATED_ROWS.FIRST, 0) .. NVL (LR_UPDATED_ROWS.LAST, -1)
      LOOP
          SELECT * FROM DOCUMENT_QUEUE DQ WHERE DQ.ENV_ID = LR_UPDATED_ROWS(indx);
      END LOOP;

      RETURN LS_CUR;        
END GET_DOCS;

所有的帮助和提示都是受欢迎的。

jvidinwx

jvidinwx1#

FOR indx IN NVL (LR_UPDATED_ROWS.FIRST, 0) .. NVL (LR_UPDATED_ROWS.LAST, -1)
      LOOP
          SELECT * FROM DOCUMENT_QUEUE DQ WHERE DQ.ENV_ID = LR_UPDATED_ROWS(indx);
      END LOOP;

      RETURN LS_CUR;

不需要游标FOR LOOP。可以使用OPEN CURSOR FOR语句返回SYS_REFCURSOR
比如说

OPEN LS_CUR FOR SELECT * FROM DOCUMENT_QUEUE DQ 
WHERE DQ.ENV_ID IN (SELECT * FROM TABLE(LR_UPDATED_ROWS));

RETURN LS_CUR;

或者,

OPEN LS_CUR FOR SELECT * FROM DOCUMENT_QUEUE DQ 
WHERE DQ.ENV_ID MEMBER OF LR_UPDATED_ROWS;

RETURN LS_CUR;

但要做到这一点,必须在SQL级别而不是PL/SQL级别CREATE类型。否则,您将收到PLS-00642: local collection types not allowed in SQL statements
一个小demo:
创建SQL级别类型

SQL> CREATE OR REPLACE TYPE table_typ AS TABLE OF NUMBER
  2  /

Type created.

使用refcursor获取SQL*Plus中的输出:
使用MEMBER OF语法

SQL> variable r refcursor
SQL> DECLARE
  2    l_typ table_typ;
  3  TYPE numbers IS TABLE OF NUMBER;
  4    n numbers;
  5  BEGIN
  6    SELECT empno BULK COLLECT INTO l_typ FROM emp;
  7    OPEN :r FOR SELECT empno,
  8    ename FROM emp WHERE empno member OF l_typ;
  9  END;
 10  /

PL/SQL procedure successfully completed.

SQL> print r

     EMPNO ENAME
---------- ----------
      7369 SMITH
      7499 ALLEN
      7521 WARD
      7566 JONES
      7654 MARTIN
      7698 BLAKE
      7782 CLARK
      7788 SCOTT
      7839 KING
      7844 TURNER
      7876 ADAMS
      7900 JAMES
      7902 FORD
      7934 MILLER

14 rows selected.

使用TABLE函数

SQL> variable r refcursor
SQL> DECLARE
  2    l_typ table_typ;
  3  TYPE numbers IS TABLE OF NUMBER;
  4    n numbers;
  5  BEGIN
  6    SELECT empno BULK COLLECT INTO l_typ FROM emp;
  7    OPEN :r FOR SELECT empno,
  8    ename FROM emp WHERE empno IN (SELECT * from TABLE(l_typ));
  9  END;
 10  /

PL/SQL procedure successfully completed.

SQL> print r

     EMPNO ENAME
---------- ----------
      7369 SMITH
      7499 ALLEN
      7521 WARD
      7566 JONES
      7654 MARTIN
      7698 BLAKE
      7782 CLARK
      7788 SCOTT
      7839 KING
      7844 TURNER
      7876 ADAMS
      7900 JAMES
      7902 FORD
      7934 MILLER

14 rows selected.
qc6wkl3g

qc6wkl3g2#

对于提到的要求,我在下面提到了一个片段,这将有助于为每个rowid将所有行提取到ref游标中。如果有帮助就告诉我。

CREATE OR REPLACE TYPE table_typ
IS
  TABLE OF DOCUMENT_QUEUE.ENV_ID%TYPE INDEX BY PLS_INTEGER;

CREATE OR REPLACE FUNCTION GET_DOCS
RETURN SYS_REFCURSOR
IS
  LS_CUR SYS_REFCURSOR;
  LR_UPDATED_ROWS table_typ;
  lv_rows_lst VARCHAR2(32676);
BEGIN
  SELECT <COL1> BULK COLLECT INTO LR_UPDATED_ROWS FROM <TABLE_NAME>;
  FOR I IN LR_UPDATED_ROWS.FIRST..LR_UPDATED_ROWS.LAST
  LOOP
    lv_rows_lst:=lv_rows_lst||','||LR_UPDATED_ROWS(I);
  END LOOP;
  lv_rows_lst:=SUBSTR(lv_rows_lst,2,LENGTH(lv_rows_lst));
  OPEN LS_CUR FOR 'SELECT * FROM DOCUMENT_QUEUE DQ WHERE DQ.ENV_ID IN ('||lv_rows_lst||')';
  RETURN LS_CUR;
END GET_DOCS;

相关问题