更改时强制列更新为特定值

时间:2012-02-21 14:21:56

标签: sql-server triggers

我希望在更改后触发特定列的更新。

(历史记录:某些应用程序会对列进行更新,但我无法找到适合的应用程序。因此,我决定使用触发器来强制退回该值。)

为了简单起见..

UsrTbl:
usrid usr   pwd
1001  admin qwerty
2001  cto   demo
3001  ceo   demo
...

如果某人在usr为admin的pwd上进行更新,我想将其重新更新为特定值。

如果我做了一个触发器,比如:

CREATE TRIGGER the_usr_trg ON usrtbl AFTER UPDATE AS
UPDATE usrtbl SET pwd='qwerty' WHERE usr = 'admin'
GO

上面会解决这个问题吗? 触发器更新列时会发生什么?它会再次触发the_usr_trg触发器吗?这会导致数据库服务器中出现循环吗?还是会只运行一次? 有没有更好的方法来解决这个问题? (除了查找正在更新此列的应用程序之外:)

谢谢!

3 个答案:

答案 0 :(得分:1)

我相信它将取决于数据库上触发器的递归级别。如果RECURSIVE_TRIGGERS设置为OFF,那么它只会运行一次。在您的情况下,请认为如果您创建INSTEAD OF触发器会更好,从而避免桌面上的第一个UPDATE。在你的情况下,它将是这样的:

CREATE TRIGGER the_usr_trg ON usrtbl 
INSTEAD OF UPDATE 
AS
BEGIN

    UPDATE A
    SET pwd= B.pwd
    FROM usrtbl A
    INNER JOIN INSERTED B
        ON A.usr = B.usr
    WHERE usr != 'admin'

END

答案 1 :(得分:1)

默认情况下,触发器不会递归调用自己,除非您使用以下语句告诉它们:

SET RECURSIVE_TRIGGERS ON

您的代码应该可以正常运行。

答案 2 :(得分:0)

根据@ cadrell0的评论,您可以在开发环境中测试它以查看它是否会递归。

更大的问题是,您只是通过重置值来解决问题,而不是找出根本原因 - 查看系统视图sys.trigger_events或实现审计表(这是一种更典型的方式)使用触发器)来查看值的更改时间和原因。

忽略以明文形式存储密码非常糟糕的事实......

为避免触发器中的递归,您可以使用 inserted 表查看建议的更改,或使用trigger update()函数查看列是否已更改。如果列已设置为您想要的值,则无需再次更新。