我想在PL / SQL包中使用多个长SQL选择查询(150行+)。该包具有执行SQL查询并将结果插入单独的表,将SQL结果与另一个表进行比较,删除行等的过程
使用以下方法存储SQL结果相当容易:
INSERT into TABLE1
SELECT .... (150 line ugly select query goes here)
问题是,我想将选择SQL存储在游标/函数/视图/无论什么工作中,因此我不必将150行查询粘贴到使用SQL的每个过程中。
我可以将SQL存储为游标,然后在包过程中循环遍历游标,获取每一行,例如插入到我的表中。但是考虑到我使用游标的唯一动机是减少我的包的行数,这似乎非常低效。
是否有更好的方法可以在不同的过程中调用SQL select查询而无需复制&粘贴所有150条线?如果这是一个脚本,我会将SQL存储在一个文本文件中,然后将文本文件读入一个变量,并在需要时将该变量传递给sqlplus。但我对PL / SQL不是很熟悉。
代码:
CREATE OR REPLACE PACKAGE BODY MyPackage
as
Cursor my_cursor
select (150+ lines goes here)
PROCEDURE PopulateTable
is
TYPE fetch_array IS TABLE OF my_cursor%ROWTYPE;
s_array fetch_array;
BEGIN
open my_cursor;
LOOP
FETCH tran_cursor BULK COLLECT INTO s_array;
FORALL counter in 1..s_array.COUNT
INSERT INTO my_table VALUES s_array(counter);
EXIT when s_array%NOTFOUND;
END LOOP;
close my_cursor;
COMMIT;
END PopulateTable;
END MyPackage;
答案 0 :(得分:2)
我不确定这是否是最好的方法,但我想到的是一个可变光标。你可以使用SYS_REFCURSOR来做到这一点。您可以构建一个包含查询的函数,并返回ref curosr。在所有程序中,您只需调用该函数即可。这将节省您在每个过程中编写150多行查询。更重要的是,它会将您的程序限制为一个查询副本,因此易于维护。
返回引用游标的函数可能是这样的:
CREATE OR REPLACE FUNCTION my_ugly_query()
RETURN SYS_REFCURSOR
AS
my_cursor_ref SYS_REFCURSOR;
BEGIN
OPEN my_cursor_ref FOR
SELECT -- 150+ lines of query;
RETURN my_cursor_ref;
END;
这是如何使用它:
CREATE OR REPLACE PACKAGE BODY MyPackage
as
PROCEDURE PopulateTable
IS
l_cur_refcur SYS_REFCURSOR;
s_array fetch_array;
BEGIN
l_cur_refcur := my_ugly_query();
LOOP
FETCH tran_cursor BULK COLLECT INTO s_array;
EXIT when s_array%NOTFOUND;
FORALL counter in 1..s_array.COUNT
INSERT INTO my_table VALUES s_array(counter);
END LOOP;
CLOSE my_cursor;
COMMIT;
END PopulateTable;
END MyPackage;
答案 1 :(得分:0)
在包规范中创建游标而不是包体。然后,您可以使用package_name.cursor_name
从任何程序包/函数中引用它