触发器:跟踪ID更新

时间:2013-08-15 16:43:15

标签: sql-server tsql triggers sql-update

对于跟踪表的UPDATE的触发器,可以引用两个临时表:已删除和已插入。有没有办法在主键上使用INNER JOIN交叉引用这两个w / o?

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

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

2 个答案:

答案 0 :(得分:0)

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

答案 1 :(得分:0)

我刚才有这个问题(或者更确切地说,类似的问题),我自己,因此复活......

我最终的方法是简单地禁止更新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相关的各种问题 - 它只是用于演示原则) < / p> 但是,它有点乱,所以我肯定会考虑代码生成,以便在开发过程中处理对表的更改(甚至可以通过CREATE / ALTER表上的DDL触发器完成)。

如果你有一个复合主键,你可以使用IF UPDATE(pk1) OR UPDATE(pk2)...或者使用COLUMNS_UPDATED函数进行一些按位工作,它会根据列序数给你一个位掩码(但我不是将在此处介绍 - 请参阅MSDN / BOL)。

另一个(更简单)选项是DENY UPDATE ON your_table(pk) TO public,但请记住,sysadmins(可能dbo)的任何成员都尊重此。< / p>