为了解决您的问题,我们必须采用编程方式解决问题。您可以选择两条路线。之所以需要这些方法,是因为您不能为特定的语句禁用触发器,而只能在整个表中禁用它。
选项1:Context_Info()
Samuel Vanga谈MS SQL技巧举了一个很好的例子:
USE AdventureWorks;
GO
-- creating the table in AdventureWorks database
IF OBJECT_ID('dbo.Table1') IS NOT NULL
DROP TABLE dbo.Table1
GO
CREATE TABLE dbo.Table1(ID INT)
GO
-- Creating a trigger
CREATE TRIGGER TR_Test ON dbo.Table1 FOR INSERT,UPDATE,DELETE
AS
DECLARE @Cinfo VARBINARY(128)
SELECT @Cinfo = Context_Info()
IF @Cinfo = 0x55555
RETURN
PRINT 'Trigger Executed'
-- Actual code goes here
-- For simplicity, I did not include any code
GO
现在,当塞缪尔不想让触发器执行时,他们可以使用以下命令:
SET Context_Info 0x55555
INSERT dbo.Table1 VALUES(100)
Context_Info
使用以下系统视图来获取有关当前会话的信息:
sys.dm_exec_requests
sys.dm_exec_sessions
sys.sysprocesses
这里的思想是,您设置的二进制字符串仅在当前会话中公开,因此当触发器在您的会话中执行时,它将看到Context_info
函数的作用域和变量设置,并将跳至触发器的转义部分代替。
选项2:临时表
Itzik Ben-Gan在他的书《 Inside Microsoft SQL Server 2008 T-SQL编程:T-SQL编程》中有一个很好的解决方案,该书也在他的后来的T-SQL Querying中。此context_info
函数上的主要问题是较小的TempDB开销。
为了破坏惊喜但又不破坏书籍的情节(我认为它们值得购买和阅读),您将更改触发器。
您的触发器应执行对临时表的检查。如果临时表存在,则触发器应该知道结束并且不执行操作。
在要执行的更新语句中,首先创建临时表。它会在与触发器相同的事务中看到,并且将导致触发器忽略您的语句。
触发器示例:
CREATE TRIGGER TRIGGERNAME ON TABLENAME for INSERT AS
IF OBJECT_ID('tempdb..#FAKETEMPTABLE') IS NOT NULL RETURN;
GO
当您不希望触发器运行时的开始语句示例:
CREATE TABLE #FAKETEMPTABLE(col1 SMALLINT);
完全将其作为您的示例:
ALTER TRIGGER tiu_benefit ON benefit FOR
...
AS
...
IF OBJECT_ID('tempdb..#FAKETEMPTABLE') IS NOT NULL RETURN;
--... rest of code here
GO
CREATE TABLE #FAKETEMPTABLE(col1 SMALLINT);
UPDATE benefit SET editor = 'srh' where benefit_id = 9876;
GO