テーブルに同じレコード番号がない場合はinse

Writer: admin Type: 友人関係の悩み Date: 2018-12-14 00:00
テーブルに同じレコード番号がない場合はinsert、ある場合はエラーにせず0件となるSQLを作成したいのですが、うまくいきません。【明細テーブル】レコード番号ㅤㅤVARCHAR2(10) ㅤㅤNOT NULL ㅤㅤPRIMARY KEY備考 ㅤㅤㅤㅤㅤㅤVARCHAR2(60)更新日時 ㅤㅤㅤㅤDATE明細テーブルには、以下のように登録されています。レコード番号ㅤㅤㅤㅤ備考 ㅤㅤㅤㅤㅤㅤㅤㅤ更新日時111111111 ㅤㅤㅤㅤㅤ注文は翌日扱い ㅤㅤㅤ2018/07/17 10:30:30222222222 ㅤㅤㅤㅤㅤ支払済 ㅤㅤㅤㅤㅤㅤㅤ2018/07/18 15:40:55333333333 ㅤㅤㅤㅤ(NULL)ㅤㅤㅤㅤㅤㅤㅤ 2018/07/19 11:25:10【ワークテーブル】レコード番号 VARCHAR2(10) NOT NULLワークテーブルには、明細テーブルと同じレコード番号の一部が格納されています。レコード番号111111111上記の例で、ワークテーブルに存在するレコード番号が明細テーブルに存在する場合、レコード番号の末尾に「A」をつけて、明細テーブルに登録を行います。※備考と更新日時は、元レコードの値をコピーします。よって、明細テーブルは以下の通りになります。レコード番号 ㅤㅤㅤㅤ備考 ㅤㅤㅤㅤㅤㅤㅤ更新日時111111111 ㅤㅤㅤㅤㅤ注文は翌日扱いㅤㅤ 2018/07/17 10:30:30222222222 ㅤㅤㅤㅤㅤ支払済 ㅤㅤㅤㅤㅤㅤ2018/07/18 15:40:55333333333 ㅤㅤㅤㅤ(NULL) ㅤㅤㅤㅤㅤㅤ2018/07/19 11:25:10111111111A ㅤㅤㅤㅤ注文は翌日扱い ㅤㅤㅤ2018/07/17 10:30:30これを実現するSQLは、INSERT INTO 明細テーブル( ㅤㅤㅤレコード番号, ㅤㅤㅤ備考, ㅤㅤㅤ更新日時 ) SELECT ㅤㅤㅤa.レコード番号 || 'A', ㅤㅤㅤㅤㅤㅤㅤa.備考,ㅤㅤㅤㅤㅤㅤㅤ a.更新日時 FROMㅤㅤㅤ 明細テーブル ㅤㅤㅤa WHERE ㅤㅤEXISTS ( ㅤㅤㅤㅤㅤㅤㅤSELECTㅤㅤㅤ 'X' ㅤㅤㅤㅤㅤㅤㅤFROM ㅤㅤㅤ明細テーブル ㅤㅤㅤb, ㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤワークテーブル ㅤㅤc ㅤㅤㅤㅤㅤㅤㅤWHEREㅤㅤ a.レコード番号 = b.レコード番号 ㅤㅤㅤㅤㅤㅤㅤAND ㅤㅤㅤc.レコード番号 = b.レコード番号 )で可能だと思うのですが、このSQLを2回目に実行すると「一意制約に反しています」のエラーとなってしまいます。※テーブルの内容が変わらなければ、1回目は「1件が登録されました」、2回目以降は「0件が登録されました」となってほしい条件が何か間違っていて2回目もinsert文が実行されてしまっているためにこのようなエラーが出ているのですが、どのように修正すればよろしいでしょうか?よろしくお願いします。共感した0###nora1962jpさん 2018/7/1919:04:14この手の処理をよく見かけますが、insertでの一意制約違反について絶対に起こさないようにすることはoracleでは困難です。ほぼ同時に複数のrセッションが処理を行おうとすると、同じ値をinsertしようとするのを防げません。レコード番号について付加するのがアルファベットでも数字でも変わりません。レコード番号が数値の場合insert into テーブル名 select max(レコード番号)+1とする例を見ますがOracleなどは他のセッション(トランザクション)が同時に読み取りに行くことをブロックしないので、一意制約違反が生じてしまいます。トランザクションの分離レベルをSERIALIZABLEにすればというのはあるかもしれませんが同時実行性が極端に落ちるので普通使いません。枝番を管理するテーブルを作る方法もありますが、その管理テーブルに新規にレコード番号を登録する場合にも一意制約違反が発生する可能性があります。レコード番号が何を意味しているか次第ですが一意制約違反は起きる前提で考えたほうがいいと思います。ナイス0
###この質問は投票によってベストアンサーに選ばれました!###ワークテーブルからだったらそんな事しないでmerge into文使えば?ナイス0

 

TAG