Sqlserver
 sql >> Database >  >> RDS >> Sqlserver

Istruzione MERGE di SQL Server 2008:come disabilitare il trigger INSTEAD OF INSERT per consentire l'unione

Query Optimizer esegue un'analisi statica del batch T-SQL e non appena vede l'istruzione MERGE, convaliderà i requisiti. NON prenderà in considerazione le istruzioni DDL che influiscono sui trigger prima dell'istruzione MERGE.

Puoi aggirare questo problema usando GO per suddividere le istruzioni in batch separati, ma se si trova in un singolo SP (nessuna istruzione GO), hai due scelte

  • metti il ​​MERGE in un SP di supporto che il principale chiama; o
  • usa SQL dinamico

SQL dinamico

Creiamo una tabella con un trigger

create table tg1(i int)
;
create trigger tg1_tg on tg1 instead of insert as 
select 1
GO

Quindi prova a MERGE sul tavolo

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
;

Non va bene..

Quindi utilizziamo SQL dinamico

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
;

Procedura di supporto

Creiamo una procedura che esegua il MERGE (un processo di produzione probabilmente avrebbe una variabile table, userebbe una tabella #temp o prenderebbe alcuni parametri)

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

Non andare...

Anche per crearlo, devi disabilitare i trigger, quindi disabilita il trigger e crea di nuovo il proc:questa volta funzionerà.

Infine, puoi eseguire questo batch che funziona

alter table tg1 disable trigger tg1_tg
;
exec tg1_MERGE
;
alter table tg1 enable trigger tg1_tg
;