0

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

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

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

4

2 回答 2

0

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

于 2013-08-16T02:53:00.983 回答
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_STATE或的各种问题TRIGGER_NESTLEVEL- 它只是为了展示原理)

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

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

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

于 2014-03-31T18:14:47.567 回答