Sqlserver
 sql >> Datenbank >  >> RDS >> Sqlserver

SQL Server 2008 MERGE-Anweisung – Deaktivieren des INSTEAD OF INSERT-Triggers, um MERGE zuzulassen

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
;