1. ホーム
  2. sql

[解決済み] SQL Server の Insert Update ストアド プロシージャ

2022-10-22 18:44:20

質問

私は、レコードが存在する場合は更新を行い、そうでない場合は挿入を行うストアド プロシージャを書きました。それは次のようなものです。

update myTable set Col1=@col1, Col2=@col2 where ID=@ID
if @@rowcount = 0
insert into myTable (Col1, Col2) values (@col1, @col2)

このように記述する背後にある私の論理は、更新がwhere句を使用して暗黙のselectを実行し、それが0を返したら挿入が実行されるというものです。

この方法の代替案は、select を実行し、返された行の数に基づいて更新または挿入を実行することです。更新を行う場合、2 つの選択 (最初の明示的な選択呼び出しと更新の場所での 2 番目の暗黙的な呼び出し) が発生するため、これは非効率的であると考えました。もし、procが挿入を行うのであれば、効率に違いはないでしょう。

私のロジックはここで正しいですか? これは、ストアド プロシージャに挿入と更新を結合する方法ですか?

どのように解決するのですか?

あなたの仮定は正しいです。これは最適な方法で、次のように呼ばれます。 upsert/merge .

UPSERTの重要性 - sqlservercentral.comより :

<ブロッククオート

上記のケースで更新されるたびに、私たちはテーブルから1つの追加の読み取りを削除しています。 テーブルから追加の読み取りを削除していることになります。 の代わりに UPSERT を使用する場合、テーブルから 1 回の読み取りを削除することになります。 残念ながら、挿入の場合、UPSERTとIF EXISTSの両方のメソッドは UPSERT と IF EXISTS の両方のメソッドは、テーブル上で同じ数の読み取りを使用します。 Insertの場合、UPSERTとIF EXISTSの両方のメソッドがテーブル上で同じ数の読み取りを行う。 したがって、存在チェックは を正当化する正当な理由がある場合にのみ実行されるべきです。 存在チェックは、追加I/Oを正当化する非常に有効な理由がある場合にのみ行われるべきです。 存在チェックは、追加のI/Oを正当化する非常に正当な理由がある場合にのみ行われるべきです。最適化された方法は 最適な方法は をできるだけ少なくすることです。 DBにできるだけ読み込まないようにすることです。

を試みることが最良の戦略です。 の更新を試みることです。更新によって影響を受ける行がない場合 を挿入します。ほとんどの場合 行はすでに存在し、1回のI/Oで済みます。 存在し、必要なI/Oは1回だけです。 が必要です。

Edit : をご覧ください。 この回答 とリンクしているブログ記事で、このパターンの問題点と安全に動作させる方法について学んでください。