【问题标题】:Overcoming the restriction on bulk inserts over a database link克服通过数据库链接进行批量插入的限制
【发布时间】:2012-05-19 01:09:57
【问题描述】:

当通过数据库链接使用时,似乎存在禁止在 Oracle 上使用 forall .. insert 的实现限制。这是一个简单的例子来演示:

connect schema/password@db1

create table tmp_ben_test (
   a number
 , b number
 , c date
 , constraint pk_tmp_ben_test primary key (a, b)
    );

Table created.

connect schema/password@db2
Connected.

declare

   type r_test is record ( a number, b number, c date);
   type t__test is table of r_test index by binary_integer;
   t_test t__test;

   cursor c_test is
    select 1, level, sysdate
      from dual
   connect by level <= 10
           ;

begin

   open c_test;
   fetch c_test bulk collect into t_test;

   forall i in t_test.first .. t_test.last
     insert into tmp_ben_test@db1
     values t_test(i)
            ;

   close c_test;

end;
/

非常令人困惑的是,这在 9i 中失败并出现以下错误:

第 1 行出现错误:ORA-01400:无法将 NULL 插入 ("SCHEMA"."TMP_BEN_TEST"."A") ORA-02063: DB1 的前一行 ORA-06512:在第 18 行

如果只有在签入 11g 之后我才意识到这是一个实现限制。

第 18 行出现错误:ORA-06550:第 18 行,第 4 列:PLS-00739:FORALL 远程表不支持 INSERT/UPDATE/DELETE

真正明显的解决方法是将forall .. 更改为:

for i in t_test.first .. t_test.last loop
    insert into tmp_ben_test@db1
    values t_test(i);
end loop;

但是,如果可能的话,我宁愿将其保留为单个插入。 Tom Kyte suggests the use of a global temporary table。将数据插入 GTT,然后通过 DB 链接,对于已经属于用户定义类型的一组数据来说似乎是一种过度杀伤。

只是为了澄清这个例子与实际发生的事情相比非常简单化了。我们无法做一个简单的insert into,也无法在 GTT 上完成所有操作。大部分代码必须以用户定义的类型完成。

是否有另一种更简单或更少 DMLy 的方法绕过此限制?

【问题讨论】:

  • 您尝试过 GTT 理念吗?比较 11g 中的性能。我想这不是矫枉过正,而是一种快速移动日期的方法。
  • 不,我没试过。如果没有其他选择,我显然会。从记忆中获取某些东西似乎很奇怪。将其移动到不同的内存中,然后执行一些 DML。我希望有一个更简单的解决方案。如果存在。
  • 想一想。 GTT 部分是纯 SQL,速度很快(有 dblink 惩罚)。缓慢的是带有数组的 ps/sql 部分...

标签: oracle plsql oracle11g oracle9i


【解决方案1】:

您在远程数据库上面临哪些限制?如果你可以在那里创建对象,你有一个解决方法:在远程数据库上创建集合类型和一个将集合作为参数并执行 FORALL 语句的过程。

【讨论】:

  • 我在任何地方都没有限制;这些只是处理数据库而不连接到外部世界。我花了几秒钟才明白你的意思;从 db2` 对 db1 执行一个过程,该过程将类型作为参数并为我插入?
【解决方案2】:

如果您在 db2 中创建 t__test/r_test 类型,然后在 db1 上为它们创建公共同义词,那么您应该能够调用从 db1 到 db2 的过程来填充 t_table 并返回到 db1。然后你应该能够插入到你的本地表中。

我假设您会在现实世界中使用打包的类型和过程,而不是匿名块。

另外,它不是大数据集的理想解决方案,GTT 或类似的会更好。

【讨论】:

    猜你喜欢
    • 2012-11-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-17
    • 1970-01-01
    • 2016-02-08
    相关资源
    最近更新 更多