2

我在使用许多函数和关系的各种表中使用 INSERT 作为 SELECT。选择一次返回大约 10 行。

查询看起来像

INSERT INTO EIM_TABLE(certain columns)
select a,b,...,fn(x,y,)

现在我需要收集返回的值fn(x,y),将每个值连接成一个变量,并在此基础上进行进一步的处理。

性能是一个非常关键的标准,因此要避免不必要的开销。

4

1 回答 1

1

不幸的是,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
于 2013-08-31T11:08:03.930 回答