2016-08-18 58 views
2

我有10.000行要插入到表中。恢復未插入的行Oracle

對於插入帶有FORALL在Oracle ...

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).val1values()子句中拋出ORA-00911,因爲%人物 - 所以你要麼必須做for循環內個體插入,或複製將值傳遞給另一個集合並批量插入。除非您希望得到很多拒絕,否則個別插入可能會足夠好。