在存储过程/代码块(SP / CB)中,我需要一种方法来存储查询的中间结果(我使用的是Oracle 11g)。我的想法是我选择一些数据,存储它们(在一个变量中),然后在我的SP / CB中我将它们用在其他查询中。并且不想为此创建任何模式级对象(类型,甚至更少 - 表)。
在MS SQL中,临时表可以正常运行,但在Oracle中,它不是一个选项,因为Oracle临时表是在模式级别创建的。对象和集合可以,但我也必须在模式级别创建对象类型。接下来,可以选择嵌套表格':
DECLARE
TYPE MyRowType IS RECORD (<some fields here>);
TYPE MyTableType IS TABLE OF MyRowType;
myTable MyTableType;
我可以通过BULK COLLECT INTO在myTable中选择我需要的任何数据,但是我希望我无法实现从myTable中选择数据。
SELECT * FROM myTable WHERE <some constraint>
此操作失败,并显示没有此类表格的消息&#39; myTable&#39;。另一种变体:
SELECT * FROM table(myTable) WHERE <some constraint>
- 也失败了(它说myTable不是嵌套表)。
我不能使用WITH子句的原因是我需要来自myTable的数据的查询遍布整个SP。我能想到的唯一选择是创建MyTableType(类似于CREATE OR REPLACE TYPE MyTableType AS TABLE OF MyRowType),但这会在DB方案级别创建一个对象。
所以基本上,有人可以指出我的解决方法,这样我就不必创建任何永久对象并使用本地定义的类型和对象进行管理吗?
答案 0 :(得分:0)
您可以使用流水线功能来执行此操作。例如:
CREATE OR REPLACE package TEST_PKG AS
TYPE t_num_tab IS TABLE OF number;
num_tab t_num_tab;
function get_nums(i_cnt in number) return t_num_tab pipelined;
procedure run_test;
procedure init_num_tab;
END;
身体:
CREATE OR REPLACE package body TEST_PKG AS
FUNCTION get_nums(i_cnt in number)
return t_num_tab pipelined IS
l_cnt number := 0;
BEGIN
if (num_tab.count = 0) then
return;
end if;
for i in num_tab.first .. num_tab.last
loop
l_cnt := l_cnt + 1;
if (l_cnt > i_cnt) then
return;
end if;
pipe row(i);
end loop;
END;
PROCEDURE run_test IS
l_my_local_num_tab t_num_tab;
BEGIN
select *
bulk collect into l_my_local_num_tab
from table (get_nums(5));
for i in 1 .. l_my_local_num_tab.count
loop
dbms_output.put_line('Value is: ' || i);
end loop;
END run_test;
PROCEDURE init_num_tab IS
BEGIN
select level
bulk collect into num_tab
from dual
connect by level <= 10;
END init_num_tab;
-- INIT tables
BEGIN
init_num_tab;
END;
程序run_test显示在包中使用它。包装外面会是类似的:
select * from table(test_pkg.get_nums(5));
输出:
COLUMN_VALUE
1
2
3
4
5