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 в таблице без фиксации первой транзакции. И, следовательно, эта ошибка будет брошена.

Итак, зафиксируйте предыдущую транзакцию в этой таблице и продолжите вторую транзакцию.

Другие вопросы по тегам