【问题标题】:ORACLE: Select from REF CURSOR returned from stored procedureORACLE:从存储过程返回的 REF CURSOR 中选择
【发布时间】:2022-07-21 16:35:01
【问题描述】:

我有一些返回 REF CURSOR 的程序(我无法更改或避免使用它),但内容可能不同(列数),具体取决于 IN 变量。传递一个值我们将得到两列,传递另一个值我们将得到三列。 我需要使用普通的 SELECT 语句从该游标中获取结果,所以我最终得到了 PIPLINE FUNCTION。但我找不到动态更改从游标获得的列集的解决方案。有没有其他方法可以从光标中“选择”或正确处理动态更改的列集?非常感谢!

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

【问题讨论】:

    标签: oracle stored-procedures oracle-cursor


    【解决方案1】:

    您需要为游标获取正确的列数:

    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;
    /
    

    注意:如果在游标耗尽之前停止调用流水线函数,还需要确保游标关闭(即捕获NO_DATA_NEEDED异常)。

    db小提琴here

    【讨论】:

      猜你喜欢
      • 2012-01-13
      • 2012-01-23
      • 1970-01-01
      • 2022-08-24
      • 2011-01-31
      • 2011-01-31
      • 2013-11-02
      • 2012-03-27
      • 1970-01-01
      相关资源
      最近更新 更多