Оптимизатор запросов выполняет статический анализ вашего пакета 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
Затем попытайтесь MERGE на столе
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
;
Не хорошо ..
Сообщение 5316, Уровень 16, Состояние 1, Строка 1
У цели 'tg1' оператора MERGE есть триггер INSTEAD OF для некоторых, но не для всех действий, указанных в операторе MERGE. В операторе MERGE, если какое-либо действие имеет включенный триггер INSTEAD OF для цели, тогда все действия должны включать триггеры INSTEAD OF.
Поэтому мы используем динамический 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
Не идти ...
Сообщение 5316, Уровень 16, Состояние 1, Строка 1
У цели 'tg1' оператора MERGE есть триггер INSTEAD OF для некоторых, но не для всех действий, указанных в операторе MERGE. В операторе MERGE, если какое-либо действие имеет включенный триггер INSTEAD OF на цели, тогда все действия должны включать триггеры INSTEAD OF.
Даже для его создания необходимо отключить триггеры - поэтому отключите триггер и создайте процедуру заново - на этот раз все будет работать.
Наконец, вы можете запустить этот пакет, который работает
alter table tg1 disable trigger tg1_tg
;
exec tg1_MERGE
;
alter table tg1 enable trigger tg1_tg
;