PL/SQL Append_Values Hint выдает сообщение об ошибке
У меня проблемы с выполнением большого количества вставок в таблицу Oracle с использованием PL/SQL. Мой запрос выполняется построчно, и для каждой строки запрос выполняет вычисление, чтобы определить количество строк, которое необходимо вставить в другую таблицу. Обычные вставки работают, но выполнение кода занимает много времени для большого количества строк. Чтобы ускорить вставки, я попытался использовать Append_Values
подсказка как в следующем примере:
BEGIN
FOR iter in 1..100 LOOP
INSERT /*+ APPEND_VALUES*/ INTO test_append_value_hint values (iter);
END LOOP;
END;
При этом я получаю следующее сообщение об ошибке:
ORA-12838: cannot read/modify an object after modifying it in parallel
ORA-06512: at line 3
12838. 00000 - "cannot read/modify an object after modifying it in parallel"
*Cause: Within the same transaction, an attempt was made to add read or
modification statements on a table after it had been modified in parallel
or with direct load. This is not permitted.
*Action: Rewrite the transaction, or break it up into two transactions
one containing the initial modification and the second containing the
parallel modification operation.
У кого-нибудь есть идеи, как заставить этот код работать или как быстро вставить большое количество строк в другую таблицу?
3 ответа
Вы получаете эту ошибку, потому что каждый ваш INSERT выполняется как отдельный оператор DML. Oracle предотвращает чтение / запись в таблицу, в которую были добавлены данные, используя прямую вставку пути до фиксации. Технически вы можете использовать коллекции PL/SQL и FORALL:
SQL> declare
2 type array_t is table of number index by pls_integer;
3 a_t array_t;
4 begin
5 for i in 1..100 loop
6 a_t(i) := i;
7 end loop;
8 forall i in 1..100
9 insert /*+ append_values */ into t values (a_t(i));
10 end;
11 /
Но вопрос, который задал Джастин, находится в действии - откуда поступают ваши данные и почему вы не можете использовать обычный INSERT /*+ append */ INTO ... SELECT FROM подход?
Привет, прошу вас использовать коммит после вставки, как показано ниже:
BEGIN
FOR iter in 1..100 LOOP
INSERT /*+ APPEND_VALUES*/ INTO test_append_value_hint values (iter);
COMMIT;
END LOOP;
END;
Мы не можем выполнить 2 транзакции DML в таблице без фиксации первой транзакции. И, следовательно, эта ошибка будет брошена.
Итак, зафиксируйте предыдущую транзакцию в этой таблице и продолжите вторую транзакцию.