Optymalizator zapytań przeprowadza statyczną analizę wsadu T-SQL i jak tylko zobaczy instrukcję MERGE, sprawdzi poprawność wymagań. NIE uwzględni żadnych instrukcji DDL, które mają wpływ na wyzwalacze przed instrukcją MERGE.
Możesz obejść ten problem za pomocą GO, aby podzielić instrukcje na oddzielne partie, ale jeśli jest to pojedynczy SP (bez instrukcji GO), masz dwie możliwości
- umieść MERGE w podporowym SP, który wywołuje główny; lub
- użyj dynamicznego SQL
Dynamiczny SQL
Stwórzmy tabelę z wyzwalaczem
create table tg1(i int)
;
create trigger tg1_tg on tg1 instead of insert as
select 1
GO
Następnie spróbuj MERGE na stole
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
;
Niedobrze..
Używamy więc dynamicznego 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
;
Procedura wsparcia
Stwórzmy procedurę, która wykona MERGE (proc produkcyjny prawdopodobnie miałby zmienną tabeli, użyj tabeli #temp lub przejął jakieś parametry)
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
Nie idź...
Nawet aby go utworzyć, musisz wyłączyć wyzwalacze - więc wyłącz wyzwalacz i ponownie utwórz proc - tym razem zadziała.
Wreszcie możesz uruchomić tę partię, która działa
alter table tg1 disable trigger tg1_tg
;
exec tg1_MERGE
;
alter table tg1 enable trigger tg1_tg
;