我在使用许多函数和关系的各种表中使用 INSERT 作为 SELECT。选择一次返回大约 10 行。
查询看起来像
INSERT INTO EIM_TABLE(certain columns)
select a,b,...,fn(x,y,)
现在我需要收集返回的值fn(x,y)
,将每个值连接成一个变量,并在此基础上进行进一步的处理。
性能是一个非常关键的标准,因此要避免不必要的开销。
我在使用许多函数和关系的各种表中使用 INSERT 作为 SELECT。选择一次返回大约 10 行。
查询看起来像
INSERT INTO EIM_TABLE(certain columns)
select a,b,...,fn(x,y,)
现在我需要收集返回的值fn(x,y)
,将每个值连接成一个变量,并在此基础上进行进一步的处理。
性能是一个非常关键的标准,因此要避免不必要的开销。
不幸的是,INSERT语句的返回到子句只能与values子句一起使用,所以这不会像它可能的那样漂亮。
如果你想重复使用你插入的数据而不选择它两次,你需要把它放在可以重复使用的地方。这可以是全局临时表 (GTT)或用户定义的类型。
就个人而言,我更喜欢一种类型,因为我认为它们更灵活;你想做什么取决于你之后要做的处理。如果您需要对结果执行 SQL,那么 GTT 会更合适。
如果您想使用用户定义的类型做某事,请将其与BULK COLLECT结合使用;它可能如下所示。
关键是声明一个游标,它是您要创建的 SELECT 语句;然后声明一个可以保存该 SELECT 语句值的类型。然后,您将所有数据收集到类型中。完成后,您可以在任何地方插入它并执行您希望的任何其他操作。通常,最好在 SQL 中做所有可以做的事情,而不是 PL/SQL。除非您确定使用 PL/SQL 更快,否则不要进行进一步处理。
declare
cursor c_stuff is
select a, b, ..., fn(x, y) as fn
from somewhere;
type t__stuff is table of c_stuff%rowtype index by binary_integer;
t_stuff t__stuff;
l_new_stuff varchar2(100);
begin
open c_stuff;
fetch c_stuff bulk collect into t_stuff;
close t_stuff;
forall i in t_stuff.first .. t_stuff.last
insert into somewhere_else values (t_stuff(i));
for i in t_stuff.first .. t_stuff.last loop
l_new_stuff := l_new_stuff || t_stuff(i).fn;
end loop;
...
如果你沿着 GTT 路线走,那么它看起来会更容易一些。创建一个与 SELECT 语句返回的数据类型相同的表:
create global temporary table gtt_stuff (
a number
, b ...
, fn ... )
on commit delete rows;
然后 INSERT 到这个表中;您将能够操作表格中的数据并像使用普通表格一样使用它。当您使用 DELETE ROWS 时,数据将持续到事务结束,如果您指定 PRESERVE ROWS,则直到会话结束。
你说你正在连接结果,fn()
所以它可能看起来像这样:
select listagg(fn) within group (order by 1)
into l_new_stuff
from gtt_stuff;
还要注意评论中 David Aldridge 的(伟大的)建议,您还可以使用多表 INSERT 以便您可以同时 INSERT 到 GTT和您的表中:
insert all
into gtt_stuff values (a, ..., fn) -- only necessary columns
into somewhere_else values (a, b, ..., fn)
select a, b, ..., fn
from somewhere