我在SQL Server 2008中有一个on update触发器。如果某些列已被修改,我只需要执行触发器操作。因此,我想检查一下有什么变化。
T-SQL提供“if update(columnName)”构造。但是,如果已更新许多行,并且只有其中一行具有更改的特定列值,则“如果update()”必须返回true。这将使我执行触发操作的行数远远超过要求。
因此,我没有使用“if update()”,而是想加入虚拟删除和插入的表(更新前后的行),并自己比较相关列。但是,我怎样才能加入这两张桌子?我不能使用表的主键,因为更新可能已经修改了它。我唯一能想到的是通过row_number()加入,即隐式表排序。这感觉非常错误,我不知道SQL Server是否真的提供任何保证,插入的行的顺序与删除的相同。
答案 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美分:))