クエリ オプティマイザーは T-SQL バッチの静的解析を行い、MERGE ステートメントを確認するとすぐに要件を検証します。 MERGE ステートメントの前にトリガーに影響を与える DDL ステートメントは考慮されません。
GO を使用してステートメントを個別のバッチに分割することでこれを回避できますが、単一の SP (GO ステートメントなし) にある場合は、2 つの選択肢があります
- メイン SP が呼び出すサポート SP に MERGE を配置します。または
- 動的 SQL を使用する
動的 SQL
トリガー付きのテーブルを作成しましょう
create table tg1(i int)
;
create trigger tg1_tg on tg1 instead of insert as
select 1
GO
次に、テーブルで MERGE を試みます
alter table tg1 disable trigger tg1_tg
;
merge tg1 as target
using (select 1 union all select 3) as source (X) on target.i = source.x
when matched then
delete
when not matched by target then
insert (i) values (x)
output $action, inserted.*, deleted.*
;
alter table tg1 enable trigger tg1_tg
;
良くない..
そこで、動的 SQL を使用します
alter table tg1 disable trigger tg1_tg
;
exec ('
merge tg1 as target
using (select 1 union all select 3) as source (X) on target.i = source.x
when matched then
delete
when not matched by target then
insert (i) values (x)
output $action, inserted.*, deleted.*
;')
alter table tg1 enable trigger tg1_tg
;
サポート手順
MERGE を実行するプロシージャを作成しましょう (プロダクション プロシージャには、おそらくテーブル変数があり、#temp テーブルを使用するか、いくつかのパラメーターを使用します)
create proc tg1_MERGE as
merge tg1 as target
using (select 1 union all select 3) as source (X) on target.i = source.x
when matched then
delete
when not matched by target then
insert (i) values (x)
output $action, inserted.*, deleted.*
;
GO
いけません...
作成する場合でも、トリガーを無効にする必要があります。トリガーを無効にして、proc を再度作成します。今回は機能します。
最後に、動作するこのバッチを実行できます
alter table tg1 disable trigger tg1_tg
;
exec tg1_MERGE
;
alter table tg1 enable trigger tg1_tg
;