Оптимизаторът на заявки прави статичен анализ на вашия T-SQL пакет и веднага щом види израза MERGE, ще потвърди изискванията. НЯМА да вземе предвид никакви DDL изрази, които засягат тригерите преди оператора MERGE.
Можете да заобиколите това, като използвате GO, за да разделите изразите на отделни партиди, но ако е в един SP (без GO изрази), имате два избора
- поставете MERGE в поддържащ SP, който главният извиква; или
- използване на динамичен SQL
Динамичен SQL
Нека създадем таблица с тригер
create table tg1(i int)
;
create trigger tg1_tg on tg1 instead of insert as
select 1
GO
След това опитайте да се СЛИЕТЕ на масата
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
;
Не е добре...
Затова използваме динамичен 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
;
Процедура за поддръжка
Нека създадем процедура, която ще извърши MERGE (производствена процедура вероятно ще има променлива на таблица, ще използва #temp таблица или ще приеме някои параметри)
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
Не върви...
Дори за да го създадете, трябва да деактивирате тригерите - така че деактивирайте тригера и създайте отново процедурата - този път ще работи.
Накрая можете да стартирате тази партида, която работи
alter table tg1 disable trigger tg1_tg
;
exec tg1_MERGE
;
alter table tg1 enable trigger tg1_tg
;