【发布时间】:2011-01-15 06:32:39
【问题描述】:
我在 SQL Server 2008 中有一个更新触发器。如果某些列已被修改,我只需要执行触发器操作。因此,我想检查发生了什么变化。
T-SQL 提供了一个“if update(columnName)”结构。但是,如果已经更新了许多行并且其中只有一个行的特定列值发生了更改,“如果 update()”将不得不返回 true。这将使我对比需要的行多得多的行执行触发操作。
所以我认为我只是加入虚拟删除和插入的表(更新之前和之后的行)并自己比较相关列,而不是使用“if update()”。但是,我怎样才能加入这两个表?我不能使用表的主键,因为它可能已被更新修改。我唯一能想到的就是通过 row_number() 加入,即隐式表排序。但这感觉很不对劲,我不知道 SQL Server 是否真的提供了任何保证,即插入的行与删除的行的顺序相同。
【问题讨论】:
-
永远不要更改主键。如果您需要更改主键的值,那么您应该使用代理主键,例如身份。
-
如果“从不更改主键”是铁律,为什么外键约束允许“更新级联/设置 null”?如果主键包含在现实世界中有意义的东西,它可能会在某个时候发生变化。我确实尽量避免它,并且我自己的模式具有不可变的主键,但是我不认为它是绝对的禁忌?在这种特殊情况下,架构设计无论如何都不受我的控制,所以我对此无能为力。
-
外键可能指的是唯一约束,而不仅仅是PK。这使您的论点 aobut CASCADE 无效
-
在一个非常简单的系统中,您可以通过更新 PK 来完成。但是,当您进入具有数百个表的非常大的系统时,就会出现问题。 Jane Doe 结婚并成为 Jane Smith。在大多数表格中,我们保留最后更改的用户信息。您将如何在数百个表中级联这种更改,可能有数百万行受到影响?此外,希望您的主键不会是 html 链接(在电子邮件或书签中)的一部分,该链接会在您的更新后中断,或者更糟糕的是打开错误的数据。您会将 PK 更新级联到您的所有活动日志表吗?
-
我同意。正如已经提到的,我自己的架构设计遵循不变的主键规则。这就引出了另一个问题:你能以某种方式强制执行吗? IE。使主键不可变?我可以想象而不是更新触发器来解决问题。有没有更简单的方法?
标签: sql sql-server tsql sql-server-2008 triggers