我希望在更改后触发特定列的更新。
(历史记录:某些应用程序会对列进行更新,但我无法找到适合的应用程序。因此,我决定使用触发器来强制退回该值。)
为了简单起见..
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触发器吗?这会导致数据库服务器中出现循环吗?还是会只运行一次? 有没有更好的方法来解决这个问题? (除了查找正在更新此列的应用程序之外:)
谢谢!
答案 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()函数查看列是否已更改。如果列已设置为您想要的值,则无需再次更新。