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
;