【问题标题】:Issue with SQL Trigger old and new valuesSQL 触发器新旧值的问题
【发布时间】:2015-03-13 14:19:41
【问题描述】:

这是我的(正在进行的)触发器。

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_par_id == 父母的 jrid

当父级的 jr_active 列从“Y”更改为“N”时:

  1. jr_active 列中的所有子项都应更新为“N”

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

谁能看出我哪里出错了?

使用 SQL Server 2008

【问题讨论】:

  • 请记住,触发器是基于集合的!在joinreason 中更新多行时,您现在拥有的代码将无法正常运行。
  • 在给定时间不会更新超过一行。
  • 如果插入了多行,那么您的触发器将抛出错误。
  • 从应用程序的角度来看,这可能是正确的,但不要让自己陷入这种心态。多行更新将会发生并且随着这个触发器的发生,您的数据将会被破坏。修复您的触发器,以便它可以从一开始就处理多行。我的一个朋友在一家因触发器无法处理多行而倒闭的公司担任顾问。
  • @NickCarfagno ever 有多长?但这是可能的,对吧?所以你不应该考虑到这一点吗?

标签: sql sql-server database sql-server-2008 triggers


【解决方案1】:

更新后触发的触发器可以访问两个虚拟表: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 更改为N 的父行。

如果你想测试它,我的测试代码可以在这里找到:http://pastebin.com/GzVjX4dT

【讨论】:

  • 非常感谢。你不仅提供了一个可行的解决方案,还解释了它是如何工作的。太棒了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-04-04
  • 2020-11-10
  • 2011-08-06
  • 2012-02-28
  • 2021-04-24
  • 1970-01-01
相关资源
最近更新 更多