2017-05-03 44 views
1

使用Oracle,是否有辦法將一個表中的值插入另一個表中,然後從插入的表中獲取一個標識值並更新原始列?如何將一個表中的值插入另一個表,然後更新原始表?

TABLE_1是空的從TABLE_2

ID VALUE 
----------- 

值...

ID VALUE 
----------- 
0  Val 1 
0  Val 2 
0  Val 3 

...插入到了TABLE_1(標識列)

ID VALUE 
----------- 
1  Val 1 
2  Val 2 
3  Val 3 

,然後更新TABLE_2與ID

ID VALUE 
----------- 
1  Val 1 
2  Val 2 
3  Val 3 

回答

2

您需要獲得有關此類要求的程序。此解決方案使用SELECT ... FOR UPDATE鎖定源表,以防止另一個會話捕獲我們想要給出新ID的記錄。它還爲我們提供了WHERE CURRENT OF語法,這使得識別我們需要更新的記錄變得容易。

此解決方案假設存在用於填充標識列的序列。我們還有其他選擇(包括12C中的自動增量),但RETURNING子句是獲取新值的關鍵。

declare 
    cursor c2 is 
     select * from table2 
     for update of id; 
    r2 c2%rowtype; 
    new_id t1.id%type; 
begin 
    open c2; 
    loop 
     fetch c2 in r2; 
     exit when c2%notfound; 
     /* new record */ 
     insert into t1 
     values (t1_seq.nextval, t2.value) 
     returning t1.id into new_id; 
     /* update existing record with id*/ 
     update t2 
     set id = new_id 
     where current of c2; 
    end loop; 
    commit; 
end; 
/

該解決方案是行到行」,它是確保新T1.ID被應用到正確的行T2最簡單的方法。如果T1小和/或這是一個開關鍛鍊這可能是罰款。但是如果性能是一個問題有可用的調音。

+0

謝謝,光標是我要去的方式,我想知道我是否可以避免它,或者如果有我想要的MERGE我可以做。 – JonathanPeel

+0

另外,非常感謝'for update'。我並不知道遊標中的內容,我猜測它會讓我在沒有它的情況下停留一段時間。 – JonathanPeel

+0

我確實有疑問,觸發器會是更好的方法嗎?即在主表上觸發器在第二個表中插入值,然後在第二個表上使用另一個觸發器來更新主表中的值,如果我錯了,則糾正我。 – user75ponic

1

如果在表2中有很多行的,我建議你使用bulk collect。 這將幫助你提高數據庫的性能。像這樣:

declare 
type type_table2 is table of table2%rowtype index by binary_integer; 
vt_table2 type_table2; 
cursor cur_table2 is select * from table2; 
begin 
open cur_table2; 
    loop 
    fetch cur_table2 bulk collect into vt_table2 limit 500; 
    for i in 1..vt_table2.count loop 
     begin 
     insert into table1 
     values(i, vt.table2(i).value); 
     update table2 
     set id = i 
     where current of cur_table2; 
     exception when other then 
     excp := SQLERRM; 
     dbms_output.put_line('Error:'||excp); 
     end; 
    end loop; 
    exit when cur_table%notfound; 
    end loop; 
close cur_table2; 
commit; 
exception when other then 
    excp := SQLERRM; 
    dbms_output.put_line('Error:'||excp); 
end; 
+0

謝謝。我將運行這兩種類型並查看是否有任何性能改進。如果你不介意我問,這裏的散裝收集是做什麼的? – JonathanPeel

+0

> BULK COLLECT:SELECT語句通過一次獲取檢索多個行,提高數據檢索的速度 您需要有一個數組來保存內容並在本地進行搜索。 '獲取cur_table2批量收集到vt_table2限制500;' – cport93

+0

所以基本上,立即獲取光標的所有記錄,然後循環? – JonathanPeel

相關問題