トップページに戻る    次のSQLパズルへ    前のSQLパズルへ

2-2-6 条件付きinsert(複数レコード)

SQLパズル

UniqTable2のCol1,Col2に、以下の3レコードで一意制約違反が発生しないレコードのみを追加する。
レコード1(1,2)
レコード2(3,4)
レコード3(5,6)
Table1のプライマリキーは、Col1とする。


データ作成スクリプト

create table UniqTable2(Col1 primary key,Col2) as
select 3,4 from dual;


SQL

insert into UniqTable2(Col1,Col2)
select val1,val2 from (select 1 as val1,2 as val2 from dual
                       union all select 3,4 from dual
                       union all select 5,6 from dual) a
where not exists(select 1 from UniqTable2 b
                  where b.Col1=a.val1);


解説

インラインビューで作成した集合の中で、
一意制約違反が発生しないレコードを、まとめてinsertしてます。

ただし、ファントムリードやアンリピータブルリードによる一意制約違反を完全に防ぐには、
for updateを使って、ロックをかける必要があります。


Oracle11gR2からは、IGNORE_ROW_ON_DUPKEY_INDEXヒントを使って、一意制約違反を完全に防げるようです。 INSERT文のIGNORE_ROW_ON_DUPKEY_INDEXヒント INSERT INTO TARGET...SELECT...FROM SOURCEでは、 挿入する行の一意キーが既存の行と衝突することがあります。 IGNORE_ROW_ON_DUPKEY_INDEXにより、警告なしに衝突を無視して、衝突のない行を挿入できます。