Query Optimizer gör en statisk analys av din T-SQL-batch, och så snart den ser MERGE-satsen kommer den att validera kraven. Det tar INTE hänsyn till några DDL-satser som påverkar utlösare före MERGE-satsen.
Du kan kringgå detta genom att använda GO för att dela upp satserna i separata partier, men om det är i en enda SP (inga GO-satser) har du två val
- lägg MERGE i en support SP som den huvudsakliga anropar; eller
- använd dynamisk SQL
Dynamisk SQL
Låt oss skapa en tabell med en trigger
create table tg1(i int)
;
create trigger tg1_tg on tg1 instead of insert as
select 1
GO
Försök sedan att SLÅ ihop på bordet
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
;
Inte bra...
Så vi använder dynamisk 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
;
Supportprocedur
Låt oss skapa en procedur som kommer att utföra MERGE (en produktionsproc skulle förmodligen ha en tabellvariabel, använda en #temp-tabell eller ta in några parametrar)
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
No go...
Till och med för att skapa den måste du inaktivera triggers - så inaktivera triggern och skapa processen igen - det kommer att fungera den här gången.
Slutligen kan du köra denna batch som fungerar
alter table tg1 disable trigger tg1_tg
;
exec tg1_MERGE
;
alter table tg1 enable trigger tg1_tg
;