eid*_*lon 2 t-sql sql-server join sql-server-2008-r2 sql-update
在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()
Run Code Online (Sandbox Code Playgroud)
连接都是正确的,并且通过输出窗口,我已经确认where条件评估 - 按顺序 - 为FALSE和TRUE.
但由于某些原因我无法理解,这个声明实际上正在运行并试图触发UPDATE.由于第一个WHERE条件为FALSE,我不能为我的生活中的数字,为什么这是更新case.CASEMASTER中的任何行.但我知道事实是因为它正在触发该桌子上的触发器.
我错过了一些愚蠢地盯着我看的东西,那是绕过我的WHERE条款吗?
EVENTLIBRARY.HOLDLETTERS是一个INT字段,可以是-1,0或1,指定特定事件在针对案例记录时是否应该是UNHOLD,NOTCHANGE或HOLD字母.
CASEMASTER.HOLDLETTERUNTIL是DATE字段.
插入的表是EVENTMASTER,它定义了针对案例记录的实际事件.
CASEMASTER> EVENTMASTER是1-N
EVENTMASTER> EVENTLIBRARY是N-1
而且,现在我真的很困惑!它正在解雇第二个触发器.但是第二个触发器的INSERTED表中有ZERO行.所以似乎Sql Server只是因为触发事件被运行而触发了一个触发器,即使没有实际更改行?这是新的东西吗?我总是假设如果没有更改行,则AFTER UPDATE触发器不会触发.
不知道是什么EVENTID与任何东西有关,因为我根本没有EVENTID在查询中看到提到.也许你要加入更多的行比你想象的,因为你已经离开了加盟条件-我相信至少有一排EVENTLIBRARY用HOLDLETTERS = 1,即使它有不同的EVENTID比当前行(S)被更新,或不同的DEFINITIONID比您查询中提到的那个.我不知道实际的查询应该是什么,因为我没有架构和表间关系.
也:
UPDATE C SET HOLDLETTERSUNTIL = '1/1/9999'
--^-- this...
FROM cases.CASEMASTER C --<-- ...should match this
Run Code Online (Sandbox Code Playgroud)
最后,您假设触发器仅在实际影响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;
Run Code Online (Sandbox Code Playgroud)
但结果显示触发器被触发:
See?
(0 row(s) affected)
Run Code Online (Sandbox Code Playgroud)
通常,您通过以下方式检查触发器中是否实际影响了任何行:
IF EXISTS (SELECT 1 FROM inserted)
Run Code Online (Sandbox Code Playgroud)
和/或
IF EXISTS (SELECT 1 FROM deleted)
Run Code Online (Sandbox Code Playgroud)
在宣布它被解雇之前,你的第二个触发器可能没有做那样的事情.
因此,您应该检查以查看这些行是否已更新,而不是跳到因为在第二个表上触发了触发器而更新行的结论.除非你的连接条件错误(我怀疑那里有些东西是可疑的,因为你在代码中没有提到的评论中提到了一个列),我怀疑这不是真的,你认为发生的事情不是什么实际上发生了.
更新:
所以似乎Sql Server只是因为触发事件被运行而触发了一个触发器,即使没有实际更改行?这是新的东西吗?
这绝对是发生的事情,绝对不是新的.从SQL Server 2005文档CREATE TRIGGER中的第一个注释开始,最后一次更新于2006年7月:
无论是否有任何表行受到影响,触发任何有效事件时都会触发这些触发器.这是设计的.