2016-08-18 3 views
2

У меня есть 10.000 строк для вставки в таблицу.Рекуперация Не вставленные строки Oracle

Для вставки с FORALL в оракуле ...

FORALL x IN TABLE_NAME.First .. TABLE_NAME.Last 
    INSERT 
    INTO TABLE_NAME VALUES 
    (
     TABLE_NAME(x).VAL1, 
     TABLE_NAME(x).VAL2, 
     TABLE_NAME(x).VAL3, 
     TABLE_NAME(x).VAL4, 
     TABLE_NAME(x).VAL5 
    ); 

Как я могу восстановить данные из строк, которые не суммируются и не вставить в таблицу из-за нарушения constrainst для того, чтобы вставить эти элементы в не типизированных таблице отклоненных предметов?

ответ

4

Вы можете использовать save exceptions clause of the forall statement, чтобы собрать ошибки, а затем используйте the sql%bulk_exceptions implicit cursor attribute, чтобы узнать, что на самом деле произошло. Там в an example в этой документации, но в вашем случае вы можете сделать (используя составленную таблицу и данные):

create table your_table (val1 number primary key, val2 number, val3 number, val4 number, val5 number); 

declare 
    type l_table_type is table of your_table%rowtype; 
    l_table l_table_type := l_table_type(); 

    dml_errors exception; 
    pragma exception_init(dml_errors, -24381); 
begin 
    l_table.extend; 
    l_table(l_table.count).val1 := 1; 
    l_table(l_table.count).val2 := 1.2; 
    l_table(l_table.count).val3 := 1.3; 
    l_table(l_table.count).val4 := 1.4; 
    l_table(l_table.count).val5 := 1.5; 

    l_table.extend; 
    l_table(l_table.count).val1 := 2; 
    l_table(l_table.count).val2 := 2.2; 
    l_table(l_table.count).val3 := 2.3; 
    l_table(l_table.count).val4 := 2.4; 
    l_table(l_table.count).val5 := 2.5; 

    l_table.extend; 
    l_table(l_table.count).val1 := 1; 
    l_table(l_table.count).val2 := 3.2; 
    l_table(l_table.count).val3 := 3.3; 
    l_table(l_table.count).val4 := 3.4; 
    l_table(l_table.count).val5 := 3.5; 

    forall x in l_table.first .. l_table.last save exceptions 
    insert 
    into your_table values 
     (
     l_table(x).val1, 
     l_table(x).val2, 
     l_table(x).val3, 
     l_table(x).val4, 
     l_table(x).val5 
    ); 

exception 
    when dml_errors then 
    for i in 1..sql%bulk_exceptions.count loop 
     dbms_output.put_line('Index ' || sql%bulk_exceptions(i).error_index 
     || ' error ' || -sql%bulk_exceptions(i).error_code); 
     dbms_output.put_line(' val1: ' || l_table(sql%bulk_exceptions(i).error_index).val1); 
     dbms_output.put_line(' val2: ' || l_table(sql%bulk_exceptions(i).error_index).val2); 
     dbms_output.put_line(' val3: ' || l_table(sql%bulk_exceptions(i).error_index).val3); 
     dbms_output.put_line(' val4: ' || l_table(sql%bulk_exceptions(i).error_index).val4); 
     dbms_output.put_line(' val5: ' || l_table(sql%bulk_exceptions(i).error_index).val5); 
    end loop; 
end; 
/

Это производит вывод:

PL/SQL procedure successfully completed. 

Index 3 error -1 
val1: 1 
val2: 3.2 
val3: 3.3 
val4: 3.4 
val5: 3.5 

Первый элемент коллекции с val1 набора в один был вставлен успешно; второй получил уникальное исключение ограничения и не было - но он был помещен в механизм избыточного исключения вместо того, чтобы вызвать ошибку всего оператора.

Затем вы можете решить, следует ли поднимать исключение (или повторно поднимать) или сразу откат (возможно, до точки сохранения); или зафиксировать вставки, которые не вызвали ошибку.

Вы также можете вставлять те же значения в таблицу отклоненных элементов, но вам нужно быть немного осторожными, если вы откатываете другие изменения (предположительно, вы не были бы в этом сценарии).

Вы не можете непосредственно использовать другой forall, чтобы сделать это - ссылаясь на l_table(sql%bulk_exceptions(i).error_index).val1 внутри пункта values() бросает ORA-00911 из-за % характера - так что вам либо придется делать отдельные вставки внутри цикла for или копия значения для другой коллекции и объемной вставки. Если вы не ожидаете большого количества отклонений, отдельные вставки могут быть достаточно хорошими.

Смежные вопросы