2017-05-03 10 views
1

Oracleを使用すると、あるテーブルの値を別のテーブルに挿入し、挿入されたテーブルからID値を取得して元の列を更新する方法はありますか?あるテーブルの値を別のテーブルに挿入して元のテーブルを更新する方法は?

TABLE_1がTABLE_2から

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

値...

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

... TABLE_1に挿入されます(ID列を持つ)

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

そしてアップデート空でありますIDを持つTABLE_2

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.IDT2に正しい行に適用されることを確実にする最も簡単な方法です。T1が小さく、かつ/または、これはオン・オフである場合表2にした場合、おそらく大丈夫です。しかし、パフォーマンスが問題であれば利用できるチューニングがある。

+0

ありがとう、私はそれを避けることができるかどうか、または私ができる素晴らしいマージがあるかどうかを知りたいと思ったカーソルは、私が行くつもりだった方法でした。 – JonathanPeel

+0

また、 'for update 'にもありがとうございます。私はカーソルでそれについて知らなかったし、私はそれがないと私がしばらく固執していただろうと推測している。 – JonathanPeel

+0

私は疑いがある、トリガーはより良いアプローチだろうか?つまり、メインテーブルでは、2番目のテーブルに値を挿入し、2番目のテーブルで別のトリガを使用してメインテーブルの値を更新するトリガを入力します。 – user75ponic

1

運動は、私はあなたが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:1回のフェッチで複数の行を取得し、データ検索の速度を向上させるSELECT文 コンテンツを保存してローカルに検索するには配列が必要です。 'cur_table2大量収集をvt_table2制限500に取り込みます。 ' – cport93

+0

基本的に、カーソルのすべてのレコードを一度に取得してループスルーしますか? – JonathanPeel

関連する問題