2015-03-13 78 views
0

这是我的(进行中)触发器。SQL问题触发旧值和新值

ALTER TRIGGER [dbo].[trgInsertUpdate] 
ON [dbo].[joinreason] 
AFTER INSERT, UPDATE 
AS 
BEGIN 
    DECLARE @jr_active AS char(1), @jrid AS int; 
    SELECT @jr_active = (SELECT jr_active FROM INSERTED) 
    SELECT @jrid = (SELECT jrid FROM INSERTED) 

    IF UPDATE(jr_active) 
    BEGIN 
     IF (jr_active = 'N') 
     BEGIN 
      UPDATE joinreason 
      SET jr_active = 'N' where jr_par_jrid = jrid; 
     END 
    END 
END 

jr_active列是'Y'或'N'。 业务需求是:

当记录没有jr_par_id时,它被认为是父项。

当记录有jr_par_id时,它被认为是孩子。

  1. ==父

当父母的jr_active列从 'Y' 改为 'N' 的jrid孩子的jr_par_id:

  1. 所有的孩子都应该更新在jr_active列中为'N'

我无法理解如何引用旧值(更新后更改的值)和新值(即将要更新的值)。

任何人都可以看到我要去哪里错了吗?

使用SQL Server 2008

+1

请记住,触发设置为基础的:如果你想测试我的测试代码可以在这里找到

!当'joinreason'中更新多行时,您现在的代码将无法正常运行。 – NickyvV 2015-03-13 14:26:27

+0

在给定的时间内不会更新一行。 – Curly5115 2015-03-13 14:27:49

+0

如果插入了多行,那么触发器将抛出错误。 – 2015-03-13 14:29:37

回答

2

触发更新后,大火有机会获得两个虚拟表:的其中包含了旧版本(更新之前)inserted其中包含更改的行的新的更新版本,deleted改变了行。要让触发器检测一行是否发生了变化,您需要连接两个虚拟表并比较感兴趣的值。

我相信这触发是你想要什么:

CREATE TRIGGER [dbo].[trgInsertUpdate] 
ON [dbo].[joinreason] 
AFTER INSERT, UPDATE 
AS 
BEGIN 
    IF UPDATE(jr_active) 
    BEGIN 
     UPDATE joinreason 
     SET jr_active = 'N' 
     FROM joinreason j 
     JOIN inserted i ON i.jrid = j.jr_par_jrid 
     JOIN deleted d ON i.jrid = d.jrid 
     WHERE d.jr_active = 'Y' AND i.jr_active = 'N' 
    END 
END 

inserted虚表的连接限制了更新,以儿童和加入与deleted筛选出有其jr_activeY变为父行Nhttp://pastebin.com/GzVjX4dT

+1

非常感谢。您不仅提供了工作解决方案,而且还介绍了它的工作原理。真棒。 – Curly5115 2015-03-13 15:33:43