简体   繁体   English

ORACLE:从存储过程返回的 REF CURSOR 中选择

[英]ORACLE: Select from REF CURSOR returned from stored procedure

I have some procedure which returns REF CURSOR(I can't change it or avoid using it), but contents may be different (number of columns) depending on an IN variable.我有一些返回 REF CURSOR 的过程(我无法更改或避免使用它),但内容可能不同(列数),具体取决于 IN 变量。 Passing one value we'll get two columns, and passing another value we'll get three columns.传递一个值我们将得到两列,传递另一个值我们将得到三列。 I need to get results from that cursor using a plain SELECT statement so I ended up with PIPLINE FUNCTION.我需要使用普通的 SELECT 语句从该游标中获取结果,所以我最终得到了 PIPLINE FUNCTION。 But I can't find a solution for dynamically changing set of columns got from cursor.但我找不到动态更改从游标获得的列集的解决方案。 Is there any other way to "select" from cursor or correctly handle dynamically changing set of columns?有没有其他方法可以从光标中“选择”或正确处理动态变化的列集? Thanks a lot!非常感谢!

CREATE OR REPLACE package MYPKG as 
    TYPE REC IS RECORD (
      A NUMBER(18),
      B DATE,
      C NUMBER(18) DEFAULT 1
    );
    TYPE TCURSOR IS REF CURSOR;
    type CUR_TAB is table of REC;
    procedure CUR_PROC(CUR OUT TCURSOR, SEL_TYPE IN NUMBER); --some procedure with undefined columns
    FUNCTION CUR_TAB_PIPLINED(P_SEL_TYPE IN NUMBER) RETURN MYPKG.CUR_TAB PIPELINED;

END MYPKG;
/


CREATE OR REPLACE package body MYPKG 
as 
   function CUR_TAB_PIPLINED(P_SEL_TYPE IN NUMBER) return MYPKG.CUR_TAB  PIPELINED
   as 
           TAB_DATA CUR_TAB; 
           TEMP_CUR TCURSOR;
   begin 
           MYPKG.CUR_PROC(TEMP_CUR, P_SEL_TYPE);
           fetch TEMP_CUR bulk collect into TAB_DATA; 
           close TEMP_CUR; 
           pipe row(TAB_DATA(1)); --getting 1 row is enough for example
   end;

   PROCEDURE CUR_PROC (CUR OUT TCURSOR, SEL_TYPE IN NUMBER) as 
   BEGIN
        IF SEL_TYPE = 1 THEN 
           OPEN CUR FOR SELECT 1 AS A, SYSDATE AS B FROM dual;
        ELSE
           OPEN CUR FOR SELECT 1 AS A, SYSDATE AS B, 5 AS C FROM dual;
        END IF;
   end; 
END MYPKG;
/


SELECT * FROM TABLE(MYPKG.CUR_TAB_PIPLINED(1));  --ORA-00942

SELECT * FROM TABLE(MYPKG.CUR_TAB_PIPLINED(2));  --works good

You need to fetch the correct number of columns for the cursor:您需要为游标获取正确的列数:

CREATE OR REPLACE package body MYPKG 
as 
   function CUR_TAB_PIPLINED(P_SEL_TYPE IN NUMBER) return MYPKG.CUR_TAB  PIPELINED
   as 
     v_a NUMBER(18);
     v_b DATE;
     v_c NUMBER(18);
     TEMP_CUR TCURSOR;
   begin
     MYPKG.CUR_PROC(TEMP_CUR, P_SEL_TYPE);
     IF p_sel_type = 2 THEN
       LOOP
         FETCH temp_cur INTO v_a, v_b, v_c;
         EXIT WHEN temp_cur%NOTFOUND;
         PIPE ROW (REC(v_a, v_b, v_c));
       END LOOP;
     ELSE
       LOOP
         FETCH temp_cur INTO v_a, v_b;
         EXIT WHEN temp_cur%NOTFOUND;
         PIPE ROW (REC(v_a, v_b, 1));
       END LOOP;
     END IF;
     CLOSE TEMP_CUR; 
   EXCEPTION
     WHEN NO_DATA_NEEDED THEN
       CLOSE TEMP_CUR;
   end;

   PROCEDURE CUR_PROC (CUR OUT TCURSOR, SEL_TYPE IN NUMBER) as 
   BEGIN
        IF SEL_TYPE = 1 THEN 
           OPEN CUR FOR SELECT 1 AS A, SYSDATE AS B FROM dual;
        ELSE
           OPEN CUR FOR SELECT 1 AS A, SYSDATE AS B, 5 AS C FROM dual;
        END IF;
   end; 
END MYPKG;
/

Note: you also need to ensure the cursor is closed if you stop calling the pipelined function before the cursor is exhausted (ie catch the NO_DATA_NEEDED exception).注意:如果在游标耗尽之前停止调用流水线函数,还需要确保游标已关闭(即捕获NO_DATA_NEEDED异常)。

db<>fiddle here db<> 在这里摆弄

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM