バインド変数を使用したINSERTでORA-00001(一意制約違反)
870553Jun 22 2011 — edited Jun 26 2011タイトル修正しました。元タイトル:プログラムからのINSERTでORA-00001(一意制約違反)
---------------------------------------------
お世話になります。
簡単なプログラムを作っていて、おかしい事象が出ており、識者の方にお聞きしたく思います。
環境:
プログラム側 VB.NET(2010)+ODP.NET(DB付属のものを参照設定して利用。)
DB側:
Oracle 11g R2 Standard Edition One on Windows Server 2008 R2
テーブル: Test
memo_id as varchar2(10),
memo_no as number,
memo_text as varchar2(2000),
primary key (memo_id, memo_no)
プログラム側で発行しているSQLは、memo_idごとにmemo_noを発行し、テキストを登録する、という内容です。
INSERT INTO Test ( memo_id, memo_no, memo_text ) VALUES (
:memoId
,COALESCE((SELECT MAX(memo_no) FROM TEST WHERE memo_id=:memoId), 0) + 1
,:memoText
)
このSQLで以下のようにデータ登録されるものと思っていました。(memo_id ごとに、枝番を発番するイメージ)
1件目の時:
パラメータ --> memoId='id-00001', memoText='メモ内容:00001-1'
期待したデータ --> ('id-00001', 1, 'メモ内容:00001-1')
2件目の時:
パラメータ --> memoId='id-00001', memoText='メモ内容:00001-2'
期待したデータ --> ('id-00001', 2, 'メモ内容:00001-2')
3件目の時:
パラメータ --> memoId='id-00002', memoText='メモ内容:00002-1'
期待したデータ --> ('id-00002', 1, 'メモ内容:00002-1')
4件目の時:
パラメータ --> memoId='id-00001', memoText='メモ内容:00001-3'
期待したデータ --> ('id-00001', 3, 'メモ内容:00001-3)
5件目の時:
パラメータ --> memoId='id-00002', memoText='メモ内容:00002-2'
期待したデータ --> ('id-00002', 2, 'メモ内容:00002-2')
他の環境、他のプログラムではこういうSQLを多用していたので、今回も問題ないだろうと思っていたのですが、
うまくいかずにORA-00001(一意制約違反)のエラーとなってしまいました。
テーブルの主キーを外して試してみると、実際に登録された内容は下のようになりました。
1件目の時:
パラメータ --> memoId='id-00001', memoText='メモ内容:00001-1'
実際のデータ --> ('id-00001', 1, 'メモ内容:00001-1')
2件目の時:
パラメータ --> memoId='id-00001', memoText='メモ内容:00001-2'
実際のデータ --> ('id-00001', 1, 'メモ内容:00001-2')
3件目の時:
パラメータ --> memoId='id-00002', memoText='メモ内容:00002-1'
実際のデータ --> ('id-00002', 1, 'メモ内容:00002-1')
4件目の時:
パラメータ --> memoId='id-00001', memoText='メモ内容:00001-3'
実際のデータ --> ('id-00001', 1, 'メモ内容:00001-3)
5件目の時:
パラメータ --> memoId='id-00002', memoText='メモ内容:00002-2'
実際のデータ --> ('id-00002', 1, 'メモ内容:00002-2')
SQLを下のようにいじって、memo_idごとに発番している部分を固定化すると1,2,3,4,5 と枝番がカウントアップしていくのですが、
それだとシーケンスを使っているのと同じですし・・・
INSERT INTO Test ( memo_id, memo_no, memo_text ) VALUES (
:memoId
,COALESCE((SELECT MAX(memo_no) FROM TEST WHERE memo_id='id-00001'), 0) + 1
,:memoText
)
ちなみに、SQL*Plus で各パラメータを固定して実行すると、意図通りに期待したデータが入ります。
何とか評価順を変えて、意図通りのデータが入れられるようにしたいのですが、SQLを少しいじってみてもうまくいきませんでした。
なんとか評価順を変えて、枝番を発番しながらINSERTできる方法はありますでしょうか?
以上です。よろしくお願いします。
Edited by: user8848963 on 2011/06/23 1:50