不幸的是,INSERT 语句的 returning into 子句只能与 values 子句一起使用,所以这不会像可能是。
如果您想重复使用插入的数据而不选择它两次,则需要将其放置在可以重复使用的位置。这可以是GLOBAL TEMPORARY TABLE (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 在 cmets 中的(很棒的)建议,您还可以使用多表 INSERT,以便您可以同时 INSERT 和您的表:
insert all
into gtt_stuff values (a, ..., fn) -- only necessary columns
into somewhere_else values (a, b, ..., fn)
select a, b, ..., fn
from somewhere