[英]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
异常)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.