【问题标题】:SQL Server 2008 Update TriggerSQL Server 2008 更新触发器
【发布时间】:2014-03-26 15:32:20
【问题描述】:

我需要在表上创建一个更新触发器,如果​​存在某些插入的值,它也会更新表。这可能吗?我已经尝试过,当插入的值存在并触发触发器时,触发器会进行更新并再次触发自身。最终 - 僵局。有没有办法安全地做到这一点?

代码:

CREATE TRIGGER dbo.trg_updateaddress on dbo.Customers
    AFTER UPDATE
AS
BEGIN
    SET NOCOUNT ON;

    DECLARE @original_source varchar(50)
    SELECT  @original_source = address_source FROM deleted

    IF EXISTS (SELECT * FROM inserted i
               INNER JOIN deleted d
                    ON i.cust_id = d.cust_id
               WHERE i.address_source IS NOT NULL 
               AND   (i.[address] <> d.[address]
               OR    i.address2 <> d.address2
               OR    i.city <> d.city
               OR    i.[state] <> d.[state]
               OR    i.zip <> d.zip
               OR    i.country <> d.country
               OR    i.phone <> d.phone
               OR    i.cell <> d.cell
               OR    i.email <> d.email))
    BEGIN
         UPDATE customers
         SET    address_changed = GETDATE()
    END
    ELSE
    BEGIN
        UPDATE customers
        SET    address_source = @original_source
    END
END

【问题讨论】:

  • 你能显示你的触发代码吗?
  • 您是否想要触发器递归触发,还是没有必要?
  • 即使这样有效,它也会用新的GETDATE() 更新Customers 的所有行。
  • 但是你有BEGIN UPDATE customers SET address_changed = GETDATE() END,没有WHERE
  • 我认为INSTEAD OF 触发器在这里会更有用。

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


【解决方案1】:

您可以做的一件事是禁用数据库中的触发器递归:

USE [master]
GO
ALTER DATABASE [yourDbName] SET RECURSIVE_TRIGGERS OFF WITH NO_WAIT
GO

这将防止数据库中的所有触发器直接触发自己,同时仍然允许它们触发其他触发器。

我通常还是推荐这个设置,因为递归触发器通常不是你想要的,而且是一种非常特殊的行为。

【讨论】:

  • 这在我的环境中会很可怕,因为这个数据库中有很多触发器,这有可能破坏其他触发器代码。
【解决方案2】:

您可以使用 NESTED_LEVEL 防止触发器自行触发

把它放在 SET NOCOUNT ON 之后;

IF trigger_nestlevel() < 2

这将防止触发器在它自己的更新时触发。

注意:第一次更新时 trigger_nestlevel 从 1 开始计数,因此如果您希望触发器仅触发一次则将其设置为 2,如果您希望它触发两次则将其设置为 3。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-01-31
    • 1970-01-01
    • 2014-01-19
    • 2011-06-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多