PL / SQL - 将两个结果集缓存到集合中并将它们连接在一起?

时间:2010-02-24 18:16:36

标签: sql database oracle collections plsql

我有两个非常大的表,我需要从这些表中处理一个小的结果集。但是,处理是在几个函数中完成的,函数必须进行一些连接才能以适当的方式格式化数据。

我肯定需要以某种方式缓存初始结果集,以便它可以被函数重用。我想要做的是将第一个结果集放在一个集合中,将第二个结果集放在另一个集合中,然后通过SQL查询操作这些集合,就好像它们是真正的SQL表一样。

你能建议如何做到这一点吗?

3 个答案:

答案 0 :(得分:5)

听起来像临时表的工作:

CREATE GLOBAL TEMPORARY TABLE table_name (...) ON ...

ON有两种选择,具有不同的影响:

  1. ON COMMIT DELETE ROWS指定临时表是特定于事务的。数据在表内持续到交易结束时间。如果结束事务,数据库将截断表(删除所有行)。假设您发出提交或运行ddl,则临时表中的数据将丢失。它是默认选项。

  2. ON COMMIT PRESERVE ROWS指定临时表是特定于会话的。数据在表内持续到会话结束时间。如果结束会话,数据库将截断表(删除所有行)。假设您在SQL * Plus中键入exit,那么临时表中的数据将会丢失。

  3. 参考:

    ...但您可能不需要使用临时表。派生表/内联视图/子查询(可能是流水线)可以做你想要的,但信息含糊不清,所以我不推荐一种特定的方法。

答案 1 :(得分:3)

如果使用SQL类型声明集合,则可以在带有TABLE()函数的SQL语句中使用它们。在Oracle 10g中,我们可以使用MULTISET UNION运算符合并集合。以下代码显示了这两种技术的示例......

SQL> declare
  2      v1 sys.dbms_debug_vc2coll;
  3      v2 sys.dbms_debug_vc2coll;
  4      v3 sys.dbms_debug_vc2coll := sys.dbms_debug_vc2coll();
  5  begin
  6      select ename
  7      bulk collect into v1
  8      from emp;
  9      select dname
 10      bulk collect into v2
 11      from dept;
 12
 13      -- manipulate connects using SQL
 14
 15      for r in ( select * from table(v1)
 16                 intersect
 17                 select * from table(v2)
 18               )
 19      loop
 20          dbms_output.put_line('Employee '|| r.column_value ||' has same name as a department');
 21      end loop;
 22
 23      -- combine two collections into one
 24
 25      dbms_output.put_line('V3 has '|| v3.count() ||' elements');
 26      v3 := v1 multiset union v2;
 27      dbms_output.put_line('V3 now has '|| v3.count() ||' elements');
 28  end;
 29  /
Employee SALES has same name as a department
V3 has 0 elements
V3 now has 23 elements

PL/SQL procedure successfully completed.

SQL>

您可以采用其他一些方法。通常最好使用SQL而不是PL / SQL,因此OMG Ponies建议使用临时表可能是合适的。这实际上取决于您处理需求的确切细节。

答案 2 :(得分:1)

您需要创建一个架构级类型(不在包内)作为嵌套表。您可以填充它们,然后您可以使用“table()”语句在查询中将它们用作普通表。

link 解释了您的需求。一个简单的例子

create type foo as table of number;-- or a record type, data%rowtype, whatever
...
myfoo1 foo := foo (1,2,3);
myfoo2 foo := foo(3,4,5)

select column_value
into bar
from table(foo1) join table(foo2) using (column_value)