Похоже, что существует ограничение реализации, которое запрещает использование forall .. insert
для Oracle при использовании по ссылке базы данных. Это простой пример, чтобы продемонстрировать:Преодоление ограничения на объемные вставки по ссылке базы данных
connect schema/[email protected]
create table tmp_ben_test (
a number
, b number
, c date
, constraint pk_tmp_ben_test primary key (a, b)
);
Table created.
connect schema/[email protected]
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 [email protected]
values t_test(i)
;
close c_test;
end;
/
Очень смешения это терпит неудачу в 9i со следующей ошибкой:
ERROR at line 1: ORA-01400: cannot insert NULL into ("SCHEMA"."TMP_BEN_TEST"."A") ORA-02063: preceding line from DB1 ORA-06512: at line 18
Если было только после проверки в 11g, что я понял, что это было ограничение реализации ,
ERROR at line 18: ORA-06550: line 18, column 4: PLS-00739: FORALL INSERT/UPDATE/DELETE not supported on remote tables
Действительно очевидный способ обойти это изменить forall ..
к:
for i in t_test.first .. t_test.last loop
insert into [email protected]
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. Я надеялся на более упрощенное решение. Если он существует. – Ben
Подумайте немного об этом. Часть GTT - чистый SQL, и она будет быстрой (с dblink штрафом). Медленная часть ps/sql с массивами ... –