【问题标题】:INSERT the results of multiple functions but do further processing on the result插入多个函数的结果,但对结果进行进一步处理
【发布时间】:2013-09-03 23:18:59
【问题描述】:

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

查询看起来像

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

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

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

【问题讨论】:

  • 您需要做什么样的进一步处理?

标签: sql performance oracle plsql


【解决方案1】:

不幸的是,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

【讨论】:

  • 我建议使用 GTT 路由并增强流程 - 使用多表插入来加载 EIM_TABLE 和全局临时表。只需将所需的最低限度加载到 GTT 中(可能只是函数结果)。
  • 多表插入是一个伟大的想法@David!
猜你喜欢
  • 2020-06-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-21
  • 2013-04-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多