forall .. insert
当通过数据库链接使用时,似乎存在禁止在 Oracle 上使用的实现限制。这是一个简单的示例来演示:
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 建议使用全局临时表。将数据插入 GTT,然后通过 DB 链接,对于已经属于用户定义类型的一组数据来说似乎是一种过度杀伤。
只是为了澄清这个例子与实际发生的事情相比非常简单。我们不可能做一个简单的事情insert into
,也不可能所有的操作都可以在 GTT 上完成。大部分代码必须以用户定义的类型完成。
是否有另一种更简单或更少 DMLy 的方法来绕过这个限制?