Jos*_*osh 4 sql sql-server merge triggers sql-server-2008
我试图在存储过程中使用SQL SERVER 2008 MERGE语句来更新/插入表.我在表上有一个INSTEAD OF INSERT触发器,并在尝试创建该过程时收到以下错误消息
MERGE语句的目标"Phone"对MERGE语句中指定的某些操作(但不是全部)具有INSTEAD OF触发器.在MERGE语句中,如果任何操作在目标上启用了INSTEAD OF触发器,则所有操作都必须启用INSTEAD OF触发器.
我绝对不需要INSTEAD OF UPDATE触发器(并且由于在表上启用了CASCADE DELETES而无法创建一个).
因此,在存储过程中,我首先在MERGE之前发出DISABLE TRIGGER命令.但是当我运行存储过程时,我得到了同样的错误,就好像DISABLE TRIGGER命令永远不会运行一样.
查询优化器对T-SQL批处理进行静态解析,一看到MERGE语句,就会验证需求.它不会考虑任何影响MERGE语句之前的触发器的DDL语句.
您可以使用GO来解决这个问题,将语句分成不同的批次,但如果它在一个SP(没有GO语句)中,您有两个选择
让我们创建一个带触发器的表
create table tg1(i int)
;
create trigger tg1_tg on tg1 instead of insert as
select 1
GO
Run Code Online (Sandbox Code Playgroud)
然后尝试在桌面上合并
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
;
Run Code Online (Sandbox Code Playgroud)
不好..
消息5316,级别16,状态1,行1
MERGE语句的目标'tg1'对MERGE语句中指定的某些操作(但不是全部)具有INSTEAD OF触发器.在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
;
Run Code Online (Sandbox Code Playgroud)
让我们创建一个执行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
Run Code Online (Sandbox Code Playgroud)
不行......
消息5316,级别16,状态1,行1
MERGE语句的目标'tg1'对MERGE语句中指定的某些操作(但不是全部)具有INSTEAD OF触发器.在MERGE语句中,如果任何操作在目标上启用了INSTEAD OF触发器,则所有操作都必须启用INSTEAD OF触发器.
即使要创建它,您也需要禁用触发器 - 因此禁用触发器并再次创建proc - 这次将会有效.
最后,您可以运行此批处理
alter table tg1 disable trigger tg1_tg
;
exec tg1_MERGE
;
alter table tg1 enable trigger tg1_tg
;
Run Code Online (Sandbox Code Playgroud)