启用和禁用触发器的替代方法
Posted
技术标签:
【中文标题】启用和禁用触发器的替代方法【英文标题】:Alternative to enable and disable trigger 【发布时间】:2022-01-20 00:43:39 【问题描述】:对于此示例,是什么? 这是我的触发器,我有一个场景,它不应该被允许直接更新 Table33 中的列 Column33(通过执行查询 UPDATE Table33 SET Column33='123'),但它应该被允许从其他列更新该列正在执行某些计算的触发器。当我在其他触发器中禁用触发器 Triger33,在触发器内部进行更新然后再次启用此触发器时,它会起作用。这个解决方案不好。有没有办法可以给这个触发器设置某种条件,以便它允许不直接的更新,这样我就可以避免在其他触发器中禁用和启用?
create trigger [dbo].[Trigger33]
on [dbo].[Table33]
AFTER UPDATE
as
if UPDATE(Column33)
begin
raiserror('It is not allowed to update Column33 in Table33', 16,1)
rollback
end
【问题讨论】:
添加 "AND @@TRIGGER_NESTLEVEL = 1" 能解决问题吗? 您可能还需要检查值是否实际更改:“AND EXISTS(SELECT * FROM INSERTED I JOIN DELETED D ON D.ID = I.ID WHERE I.Column33 D.第 33 列)”。如果需要考虑空值或区分大小写,则比较可能需要稍微复杂一些。 在另一个触发器中设置CONTEXT_INFO
,并在这个触发器中检查。
或者使用更现代的session_context
允许触发器彼此聊天。
【参考方案1】:
您可以使用nested triggers 服务器配置选项或NESTED_TRIGGERS 数据库配置选项(对于部分包含的数据库)允许触发器代码全局绕过其他触发器。
例如
EXEC sp_configure 'show advanced options', 1;
GO
RECONFIGURE ;
GO
EXEC sp_configure 'nested triggers', 0 ;
GO
RECONFIGURE;
GO
create table t(id int primary key)
create table t2(id int primary key)
go
create trigger te_nope on t2 after insert
as
begin
throw 50001, 'nope', 1;
end
go
create trigger t_ins on t after insert
as
begin
insert into t2(id) select id from inserted
end
go
insert into t2(id) values (1) --fails
--Msg 50001, Level 16, State 1, Procedure te_nope, Line 4 [Batch Start Line 32]
--nope
insert into t(id) values (1) --suceeds
--(1 row affected)
--
--(1 row affected)
其他选项包括将秘密推入在内部触发器中检查的 CONTEXT_INFO,或执行检查以修改嵌套触发器的行为的模拟。
【讨论】:
以上是关于启用和禁用触发器的替代方法的主要内容,如果未能解决你的问题,请参考以下文章