CRUD 操作を扱うとき、主キーが存在しないときに既存のレコードを更新したり、新しいレコードを挿入したりする必要がある状況がよく発生します。これは、「IF (主キーが存在する) UPDATE else INSERT」ロジックと同等です。
問題は、最適なパフォーマンスでこれを達成するにはどうすればよいでしょうか?
SQL Server はいくつかのソリューションを提供します:
1. MERGE ステートメントを使用します
MERGE ステートメントは、このロジックを実装する簡潔な方法を提供します。主キーが存在する場合は更新操作を実行し、主キーが存在しない場合は挿入操作を実行するように指定できます。
<code class="language-sql">MERGE INTO MyTable WITH (HOLDLOCK) AS Target USING (VALUES (@key, @datafield1, @datafield2)) AS Source(KEY, datafield1, datafield2) ON (Target.KEY = Source.KEY) WHEN MATCHED THEN UPDATE SET datafield1 = Source.datafield1, datafield2 = Source.datafield2 WHEN NOT MATCHED THEN INSERT (KEY, datafield1, datafield2) VALUES (Source.KEY, Source.datafield1, Source.datafield2);</code>
2. トランザクションを使用する
もう 1 つのアプローチは、トランザクションを使用してデータの整合性を確保し、主キーの競合を防ぐことです。
<code class="language-sql">BEGIN TRANSACTION; IF EXISTS (SELECT * FROM MyTable WITH (XLOCK) WHERE KEY = @key) BEGIN UPDATE MyTable SET datafield1 = @datafield1, datafield2 = @datafield2 WHERE KEY = @key; END ELSE BEGIN INSERT INTO MyTable (KEY, datafield1, datafield2) VALUES (@key, @datafield1, @datafield2); END COMMIT TRANSACTION;</code>
3. OUTPUT 句を UPDATE および INSERT と組み合わせて使用します
3 番目のオプションは、OUTPUT 句を使用して UPDATE 操作の影響を受ける行数を取得することです。この情報を使用して、INSERT 操作が必要かどうかを判断できます。
<code class="language-sql">BEGIN TRANSACTION; UPDATE MyTable SET datafield1 = @datafield1, datafield2 = @datafield2 OUTPUT inserted.KEY INTO @AffectedRows WHERE KEY = @key; IF @AffectedRows = 0 BEGIN INSERT INTO MyTable (KEY, datafield1, datafield2) VALUES (@key, @datafield1, @datafield2); END COMMIT TRANSACTION;</code>
以上がSQL Server で Upsert を効率的に実行するにはどうすればよいですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。