TSQL更新触发器:加入已插入和已删除

时间:2010-02-10 13:18:14

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

我在SQL Server 2008中有一个on update触发器。如果某些列已被修改,我只需要执行触发器操作。因此,我想检查一下有什么变化。

T-SQL提供“if update(columnName)”构造。但是,如果已更新许多行,并且只有其中一行具有更改的特定列值,则“如果update()”必须返回true。这将使我执行触发操作的行数远远超过要求。

因此,我没有使用“if update()”,而是想加入虚拟删除和插入的表(更新前后的行),并自己比较相关列。但是,我怎样才能加入这两张桌子?我不能使用表的主键,因为更新可能已经修改了它。我唯一能想到的是通过row_number()加入,即隐式表排序。这感觉非常错误,我不知道SQL Server是否真的提供任何保证,插入的行的顺序与删除的相同。

5 个答案:

答案 0 :(得分:3)

使用您的设计(允许更改主键),构建一致的逻辑似乎非常困难。

说,你有这张桌子:

id   value
1    2
2    1

并发出此操作:

UPDATE  mytable
SET     id = CASE WHEN id = 1 THEN 2 ELSE 1 END,
        value = CASE WHEN value = 1 THEN 2 ELSE 1 END

更新两个记录但是将表保留为:

id   value
2    1
1    2

,从关系的角度来看,类似于根本不改变表格。

主键的重点是它们永远不会改变。

答案 1 :(得分:0)

如果您使用IDENTITY列作为主键,则不会出现更新PK列的问题。

答案 2 :(得分:0)

为防止PK更改,请将其添加到触发器的顶部:

IF (UPDATE(yourPKcol1) OR UPDATE(yourPKcol2))
BEGIN 
    RAISERROR('Primary Key change not permitted!',16,1) 
    ROLLBACK
    RETURN
END

答案 3 :(得分:0)

你最好的选择可能是(正如我在上面的评论中所提到的)创建一个新表,如果可能的话,包括原始数据中的所有数据,但也包括一个不可变的主键(IDENTITY有效,或者你可以使用某些东西)否则,如果你愿意)。然后,您可以公开此新表的视图,该视图模仿原始表的名称和架构。这将为您提供一个固定的ID,您可以使用它来跟踪您想要的更改。

所有这些都假设一个视图在你的特定情况下可以正常工作 - 如果应用程序正在做一些非常奇怪的事情,它可能无法正常工作,但如果它只是抛出标准的CRUD风格的SQL它应该可以正常工作。

答案 4 :(得分:0)

你的折衷是简单和可维护性与性能 如果性能没有优先使用,如果直接更新(YourTriggerActionColumn) 如果性能优先,则执行此操作的方法是使用“if update(PrimaryKeyColumn)”,因此如果主键未更改,则使用inserted-deleted join else如果主键确实已更改,则检查“if update(YourTriggerActionColumn)” 由于PK经常不会改变,因此大多数时候使用插入删除的连接方法可以解决您的性能问题。 不太晚但只是我的2美分:))