Der Abfrageoptimierer führt eine statische Analyse Ihres T-SQL-Stapels durch und validiert die Anforderungen, sobald er die MERGE-Anweisung sieht. Es berücksichtigt KEINE DDL-Anweisungen, die sich auf die Trigger vor der MERGE-Anweisung auswirken.
Sie können dies umgehen, indem Sie GO verwenden, um die Anweisungen in separate Stapel aufzuteilen, aber wenn es sich um einen einzigen SP handelt (keine GO-Anweisungen), haben Sie zwei Möglichkeiten
- Legen Sie das MERGE in einen Support-SP, den der Haupt-SP aufruft; oder
- dynamisches SQL verwenden
Dynamisches SQL
Lassen Sie uns eine Tabelle mit einem Trigger erstellen
create table tg1(i int)
;
create trigger tg1_tg on tg1 instead of insert as
select 1
GO
Versuchen Sie dann, den Tisch zu 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
;
Nicht gut..
Also verwenden wir dynamisches 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
;
Unterstützungsverfahren
Lassen Sie uns eine Prozedur erstellen, die das MERGE durchführt (eine Produktionsprozedur würde wahrscheinlich eine Tabellenvariable haben, eine #temp-Tabelle verwenden oder einige Parameter aufnehmen)
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
Geht nicht...
Selbst um es zu erstellen, müssen Sie die Trigger deaktivieren - also deaktivieren Sie den Trigger und erstellen Sie den Proc erneut - diesmal wird es funktionieren.
Schließlich können Sie diesen Batch ausführen, der funktioniert
alter table tg1 disable trigger tg1_tg
;
exec tg1_MERGE
;
alter table tg1 enable trigger tg1_tg
;