在Sql Server 2008 R2中运行,这是我的UPDATE语句,它在AFTER INSERT触发器中运行:
UPDATE cases.CASEMASTER
SET HOLDLETTERSUNTIL = '1/1/9999'
FROM cases.CASEMASTER C
JOIN INSERTED I
ON I.CASEID = C.ROWID
JOIN events.EVENTLIBRARY L
ON L.ROWID = I.DEFINITIONID
WHERE L.HOLDLETTERS = 1
AND C.HOLDLETTERSUNTIL < GETDATE()
连接都是正确的,并且通过输出窗口,我已经确认where条件评估 - 按顺序 - 为FALSE和TRUE。
然而由于某些原因我无法理解,这个声明实际上正在运行并试图触发UPDATE。由于第一个WHERE条件为FALSE,我不能为我的生活中的数字为什么这是更新case.CASEMASTER中的任何行。但我知道事实是因为它正在触发那张桌子上的触发器。
我是否遗漏了一些愚蠢明显地盯着我的东西,这是绕过我的WHERE条款?
EVENTLIBRARY.HOLDLETTERS是一个INT字段,可以是-1,0或1,指定特定事件在记录案例时是否应该是UNHOLD,NOTCHANGE或HOLD字母。
CASEMASTER.HOLDLETTERUNTIL是DATE字段。
正在插入的表是EVENTMASTER,它定义了针对案例记录的实际事件。
CASEMASTER&gt; EVENTMASTER是1-N
EVENTMASTER&gt; EVENTLIBRARY是N-1
而且,现在我真的很困惑!它正在解雇第二个触发器。但是第二个触发器的INSERTED表中有ZERO行。所以似乎Sql Server只是因为触发事件被运行而触发了一个触发器,即使没有实际更改行?这是新的东西吗?我总是假设如果没有更改行,则AFTER UPDATE触发器不会触发。
答案 0 :(得分:6)
不确定EVENTID
与任何内容有什么关系,因为我根本没有看到查询中提到的EVENTID
。也许你加入了比你想象的更多的行,因为你遗漏了一个连接条件 - 我认为EVENTLIBRARY
中至少有一行HOLDLETTERS = 1
,即使它有不同的EVENTID
比正在更新的当前行,或者与查询中提到的行不同DEFINITIONID
。我不知道实际的查询应该是什么,因为我没有架构和表间关系。
此外:
UPDATE C SET HOLDLETTERSUNTIL = '1/1/9999'
--^-- this...
FROM cases.CASEMASTER C --<-- ...should match this
最后,您假设触发器仅在实际影响1行或更多行时触发,这是假的。即使没有实际影响的行,也会触发每个相关语句的触发器。简单的例子:
USE tempdb;
GO
-- simple, empty table:
CREATE TABLE dbo.flab(i INT);
GO
-- simple table that just prints a message:
CREATE TRIGGER dbo.trFlab
ON dbo.flab FOR UPDATE
AS
BEGIN
SET NOCOUNT ON;
PRINT 'See?';
END
GO
-- this query affects zero rows, both because the WHERE condition is false
-- and also because there are are no rows in the table to begin with!
UPDATE dbo.flab SET i = 1 WHERE 1 = 2;
但结果显示触发器已被触发:
See?
(0 row(s) affected)
通常,您通过以下方式检查触发器中是否实际影响了任何行:
IF EXISTS (SELECT 1 FROM inserted)
和/或
IF EXISTS (SELECT 1 FROM deleted)
在宣布它被解雇之前,你的第二个触发器可能没有做那样的事情。
因此,您应该检查以查看这些行是否已更新,而不是跳到因为在第二个表上触发了触发器而更新行的结论。除非你的连接条件错误(我怀疑那里有些东西是可疑的,因为你在代码中没有提到的评论中提到了一个专栏),我怀疑这不是真的,你认为发生的事情不是什么实际上正在发生。
更新:
所以似乎Sql Server只是因为触发事件被运行而触发了一个触发器,即使没有实际更改行?这是新事物吗?
这绝对是会发生的事情,而且绝对不是新事物。从the SQL Server 2005 documentation for CREATE TRIGGER
, last updated in July of 2006中的第一个音符开始:
无论是否有任何表行受到影响,触发任何有效事件时都会触发这些触发器。这是设计的。