如何将ref_游标提取到Oracle的WITH子句中
是否可以将ref_游标与ORACLE with子句一起使用。例如,我有以下场景。首先,我有一个返回ref_游标的过程如何将ref_游标提取到Oracle的WITH子句中,oracle,plsql,Oracle,Plsql,是否可以将ref_游标与ORACLE with子句一起使用。例如,我有以下场景。首先,我有一个返回ref_游标的过程 PROCEDURE p_return_cursor(p_id IN NUMBER, io_cursor OUT t_cursor) AS BEGIN OPEN io_cursor FOR SELECT col1, col2 FROM Table1 t WHERE t.id = p_id; END; 第二,我有另一个过程,在这个过程中我调用
PROCEDURE p_return_cursor(p_id IN NUMBER, io_cursor OUT t_cursor)
AS
BEGIN
OPEN io_cursor FOR
SELECT col1, col2
FROM Table1 t
WHERE t.id = p_id;
END;
第二,我有另一个过程,在这个过程中我调用p_return_cursor:
PROCEDURE p_test(p_cid IN NUMBER)
AS
l_cursor t_cursor;
l_rec Table1%ROWTYPE;
BEGIN
p_return_cursor(p_id => p_cid, io_cursor => l_cursor);
-- CODE GOES HERE
...
现在,我的问题是,我可以使用Oracle的WITH子句使用游标创建一个临时表吗;比如:
...
WITH data AS (
LOOP
FETCH l_cursor INTO l_rec;
EXIT WHEN l_cursor%NOTFOUND;
SELECT l_rec.col1, l_rec.col2 FROM DUAL;
END LOOP;
CLOSE l_cursor;
)
你不能直接做。但是,您可以将游标大容量收集到PL/SQL表变量中,并在WITH子句中使用该变量 如果光标包含多行,请注意内存使用情况 完整示例:
CREATE TABLE table1 ( col1 NUMBER, col2 NUMBER );
INSERT INTO table1 ( col1, col2 ) SELECT rownum, 100+rownum FROM DUAL CONNECT BY ROWNUM <= 15;
COMMIT;
CREATE OR REPLACE PACKAGE se_example AS
TYPE t_cursor IS REF CURSOR
RETURN table1%ROWTYPE;
TYPE l_rec_tab IS TABLE OF table1%ROWTYPE;
PROCEDURE p_test (p_cid IN NUMBER);
END se_example;
CREATE OR REPLACE PACKAGE BODY se_example AS
-- private
PROCEDURE p_return_cursor (p_id IN NUMBER, io_cursor OUT t_cursor) AS
BEGIN
OPEN io_cursor FOR
SELECT col1,
col2
FROM table1 t;
--WHERE t.id = p_id; -- I didn't put "id" column in my sample table, sorry...
END p_return_cursor;
PROCEDURE p_test (p_cid IN NUMBER) IS
l_cursor t_cursor;
l_tab l_rec_tab;
l_dummy NUMBER;
BEGIN
p_return_cursor (p_id => p_cid, io_cursor => l_cursor);
FETCH l_cursor BULK COLLECT INTO l_tab;
-- *** instead of this
-- WITH data AS (
-- LOOP
-- FETCH l_cursor INTO l_rec;
-- EXIT WHEN l_cursor%NOTFOUND;
-- SELECT l_rec.col1, l_rec.col2 FROM DUAL;
-- END LOOP;
-- CLOSE l_cursor;
-- )
-- '
--
-- *** do this
WITH data AS
( SELECT col1, col2 FROM TABLE(l_tab) )
SELECT sum(col1 * col2) INTO l_dummy
FROM data;
dbms_output.put_line('result is ' || l_dummy);
END p_test;
END se_example;
begin
se_example.p_test(100);
end;
你不能直接做。但是,您可以将游标大容量收集到PL/SQL表变量中,并在WITH子句中使用该变量 如果光标包含多行,请注意内存使用情况 完整示例:
CREATE TABLE table1 ( col1 NUMBER, col2 NUMBER );
INSERT INTO table1 ( col1, col2 ) SELECT rownum, 100+rownum FROM DUAL CONNECT BY ROWNUM <= 15;
COMMIT;
CREATE OR REPLACE PACKAGE se_example AS
TYPE t_cursor IS REF CURSOR
RETURN table1%ROWTYPE;
TYPE l_rec_tab IS TABLE OF table1%ROWTYPE;
PROCEDURE p_test (p_cid IN NUMBER);
END se_example;
CREATE OR REPLACE PACKAGE BODY se_example AS
-- private
PROCEDURE p_return_cursor (p_id IN NUMBER, io_cursor OUT t_cursor) AS
BEGIN
OPEN io_cursor FOR
SELECT col1,
col2
FROM table1 t;
--WHERE t.id = p_id; -- I didn't put "id" column in my sample table, sorry...
END p_return_cursor;
PROCEDURE p_test (p_cid IN NUMBER) IS
l_cursor t_cursor;
l_tab l_rec_tab;
l_dummy NUMBER;
BEGIN
p_return_cursor (p_id => p_cid, io_cursor => l_cursor);
FETCH l_cursor BULK COLLECT INTO l_tab;
-- *** instead of this
-- WITH data AS (
-- LOOP
-- FETCH l_cursor INTO l_rec;
-- EXIT WHEN l_cursor%NOTFOUND;
-- SELECT l_rec.col1, l_rec.col2 FROM DUAL;
-- END LOOP;
-- CLOSE l_cursor;
-- )
-- '
--
-- *** do this
WITH data AS
( SELECT col1, col2 FROM TABLE(l_tab) )
SELECT sum(col1 * col2) INTO l_dummy
FROM data;
dbms_output.put_line('result is ' || l_dummy);
END p_test;
END se_example;
begin
se_example.p_test(100);
end;
WITH是SQL的一部分,而不是PL/SQL。WITH是SQL的一部分,而不是PL/SQL。很好!非常感谢你的帮助。我实现了前面提到的代码,但我得到错误:包体WEBLOSSRT.JNS_的编译错误测试错误:PLS-00642:SQL语句行中不允许使用本地集合类型:49 Text:SELECT col1,table中的col2错误:PL/SQL:ORA-22905:无法访问非嵌套表项行中的行:49 Text:SELECT col1,来自TABLEl_选项卡的col2错误:PL/SQL:SQL语句忽略行:48 Text:数据为Oracle的哪个版本?我写的东西只适用于12c。在早期版本中,您需要将该类型移出包规范,并通过createtype命令将其替换为数据库对象类型。我们在Oracle的v11中工作。但是谢谢,这种方法正是我想要的。很好!非常感谢你的帮助。我实现了前面提到的代码,但我得到错误:包体WEBLOSSRT.JNS_的编译错误测试错误:PLS-00642:SQL语句行中不允许使用本地集合类型:49 Text:SELECT col1,table中的col2错误:PL/SQL:ORA-22905:无法访问非嵌套表项行中的行:49 Text:SELECT col1,来自TABLEl_选项卡的col2错误:PL/SQL:SQL语句忽略行:48 Text:数据为Oracle的哪个版本?我写的东西只适用于12c。在早期版本中,您需要将该类型移出包规范,并通过createtype命令将其替换为数据库对象类型。我们在Oracle的v11中工作。但是谢谢,这种方法正是我想要的。