The road to C# master trapemiya

C#を中心に、.NETの話題を取り上げます。

ホーム 連絡をする 同期する ( RSS 2.0 ) Login
投稿数  256  : 記事  1  : コメント  10248  : トラックバック  30

ニュース

Since 2005年10月26日

わんくま同盟

わんくま同盟

Microsoft MVP


Visual Developer - Visual C#

記事カテゴリ

書庫

日記カテゴリ

SQLサーバーのテーブルにおいて、ほとんどの場合はレコードの追加であるが、ごくまれに更新があるかもしれないといった場合、いちいちレコードの存在チェックをしてから、レコードの追加または更新をするのは無駄である。これが1件ぐらいの処理であればいいが、数万件の処理ということになると、かなり無駄に感じる。
そこでストアドプロシージャを以下のようにしてみた。hoge1にはUNIQUE KEY制約を付けてある。

  insert into table1 (hoge1, hoge2) values (@hoge1, @hoge2)

  if @@ERROR = 0 GOTO skip

  update table1 hoge2=@hoge2 where hoge1 = @hoge1

skip:


確かにこれで思った通りに動いている。しかし、C#からこのストアドプロシージャを呼ぶと、UNIQUE KEY制約違反の例外が発生する。しょうがないので、以下のようにして逃げた。

try
{
   sqlCommand1.ExecuteNonQuery(); 
}
catch(System.Data.SqlClient.SqlException ex)
{
   if (ex.Number != 2627) throw ex; //2627は、UNIQUE KEY制約違反
}

#何か指摘があれば、コメントをお願いします。(^^;
投稿日時 : 2006年2月23日 18:53

コメント

# re: ストアドプロシージャでレコードの存在チェックをせずに追加・更新する。 2006/02/24 13:04 マリウス
はじめまして。
ご存知でしょうが、INSERTとUPDATEの順序を逆にすればエラーは発生しません。
(順序を逆にする場合は、@@ERRORの代わりに@@ROWCOUNTを使用します)
でも、追加がメインならINSERTが先の方が良いのでしょうね


# re: ストアドプロシージャでレコードの存在チェックをせずに追加・更新する。 2006/02/24 15:34 trapemiya
コメントありがとうございます。確かにそのとおりですね。今回は99%が追加なので、無駄を省くためにInsertを前に置いています。処理時間が短くなるように、いろいろと悩んでます。(^^;
SQL server 2005では、try catchが使えるようなので、これを使うとどうなるのかな?と思っているのですが、現在のバージョンが2000なので、ちょっと先に楽しみにとっておきます。

# re: ストアドプロシージャでレコードの存在チェックをせずに追加・更新する。 2006/02/24 15:37 trapemiya
そうだ。言い忘れました。UPDATEをINSERTの前に置くという発想はありませんでした。(^^; 今度、使わせてもらいます。勉強になりました。m(_ _)m

# re: ストアドプロシージャでレコードの存在チェックをせずに追加・更新する。 2006/04/02 17:48 中博俊
>UPDATEをINSERTの前に置くという
深刻な問題があります。
Updateに失敗して、Insertにも失敗する可能性があります。
それはUpdateに失敗したときに、Insertするよりも前にInsertされうるからです。



# re: ストアドプロシージャでレコードの存在チェックをせずに追加・更新する。 2006/04/03 12:20 trapemiya
お~、なるほど。確かにそうですね。分離レベルできっちりとロックかけなきゃダメっぽいですね。

Post Feedback

タイトル
名前
Url:
コメント