簡體   English   中英

ORACLE:從存儲過程返回的 REF CURSOR 中選擇

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

我有一些返回 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

您需要為游標獲取正確的列數:

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<> 在這里擺弄

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM