【问题标题】:Triggers: Tracking ID Updates触发器:跟踪 ID 更新
【发布时间】:2013-08-17 22:06:08
【问题描述】:

对于跟踪表更新的触发器,可能会引用两个临时表:删除和插入。有没有办法在它们的主键上使用 INNER JOIN 来交叉引用这两者?

我试图在没有外键的情况下保持引用完整性(不要问),所以我使用了触发器。我希望表 A 中主键的 UPDATE 反映在查找表 B 的“外键”中,并且当 UPDATE 影响表 A 中的多个记录时会发生这种情况。

我见过的所有 UPDATE 触发器示例都取决于连接插入和删除的表以跟踪更改;他们使用更新后的表的 ID 字段(主键)来设置连接。但如果该 ID 字段 (GUID) 是记录(或记录集)中的更改字段,是否有一种好方法可以跟踪这些更改,以便我可以在相应的查找表中强制执行这些更改?

【问题讨论】:

  • 为什么要更新主键?在进行此类更改之前和之后,您还期望如何识别您更改的行?
  • 老实说,我不知道。我正在更新一个应用程序,它的逻辑有点混乱。我正在尝试对这个触发器进行未来证明(阅读:白痴证明),以便在路上没有人会意外地孤立一整套记录。想法?

标签: sql-server tsql triggers sql-update


【解决方案1】:

我自己也遇到过这个问题(或者更确切地说,类似的问题),因此复活了......

我最终的方法是简单地禁止更新 PK 字段,因为它会破坏触发器。幸运的是,我没有支持更新主键列的业务案例(无论如何,这些都是代理 ID),所以我可以侥幸成功。

SQL Server 提供了UPDATE 函数,用于在触发器中检查这种边缘情况:

CREATE TRIGGER your_trigger
ON your_table
INSTEAD OF UPDATE
AS BEGIN

    IF UPDATE(pk1) BEGIN
        ROLLBACK

        DECLARE @proc SYSNAME, @table SYSNAME

        SELECT TOP 1
             @proc = OBJECT_NAME(@@PROCID)
            ,@table = OBJECT_NAME(parent_id)
        FROM sys.triggers 
        WHERE object_id = @@PROCID

        RAISERROR ('Trigger %s prevents UPDATE of table %s due to locked primary key', 16, -1, @proc, @table) WITH NOWAIT
    END
    ELSE UPDATE t SET
         col1 = i.col1
        ,col2 = i.col2
        ,col3 = i.col3
    FROM your_table t
    INNER JOIN inserted i ON t.pk1 = i.pk1

END
GO

(请注意,以上内容未经测试,可能包含有关XACT_STATETRIGGER_NESTLEVEL 的各种问题——只是为了演示原理)

不过,它有点乱,所以我肯定会考虑为此生成代码,以在开发期间处理对表的更改(甚至可能由 CREATE/ALTER 表上的 DDL 触发器完成)。

如果您有一个复合主键,您可以使用IF UPDATE(pk1) OR UPDATE(pk2)... 或使用COLUMNS_UPDATED 函数进行一些按位运算,这将为您提供基于列序号的位掩码(但我不会介绍这里 -- 见 MSDN/BOL)。

另一个(更简单的)选项是DENY UPDATE ON your_table(pk) TO public,但请记住sysadmins(可能还有dbo)的任何成员不会尊重这一点。

【讨论】:

  • 这是我在 StackOverflow 上收到的最完整、经过深思熟虑的答案。非常感谢。老实说,我不相信更新这些表的应用程序会做一些愚蠢的事情,比如为现有记录创建新的 GUID。而且有太多的代码行来审核每个查询。也就是说,应用程序必须能够为新记录创建新的 GUID。因此,这是一种优雅而快速的解决方案,可以按照您想要的方式冒泡。谢谢!
【解决方案2】:

我和@Aaron 在一起,没有主键你就卡住了。如果您有添加触发器的 DDL 权限,您不能在使用时添加自动增量 PK 列吗?如果你愿意,它甚至不需要是 PK。

【讨论】:

    猜你喜欢
    • 2016-04-30
    • 2023-02-07
    • 1970-01-01
    • 2012-11-23
    • 1970-01-01
    • 2017-01-05
    • 2011-02-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多