【问题标题】:SQL Server timestamping triggerSQL Server 时间戳触发器
【发布时间】:2015-10-20 23:48:27
【问题描述】:

我的 SQL 知识非常有限,因为我主要专注于后端 Ruby 开发。然而,由于架构的变化并希望保持良好的设计;我决定在数据库级别而不是后端级别设置时间戳。

现在,我所有的表都有两列:CreatedAtUpdatedAt,两者的默认值都是 GETDATE()

但是,我现在需要为 UpdatedAt 设置时间戳触发器,以便每次更新一行(或多行)时,这些行的 UpdatedAt 列都会获得一个全新的时间戳。

我在编写以下触发器时遇到问题。我收到一个错误:

'=' 附近的语法不正确

我首先在我的 Orders 表上测试我的触发器,然后我计划将该功能移动到所有表。

CREATE TRIGGER dbo.trgTimestampAfterUpdate
ON Dbo.Orders
AFTER UPDATE
AS
BEGIN
    IF EXISTS (SELECT * FROM inserted)
    BEGIN
        SET UpdatedAt = GETDATE()
    END
END

我知道我可以在使用触发器时访问插入和删除的虚拟表。我对这个查询的想法是,我将使用 insert 来区分哪些行已被更新。如果有人可以提供帮助,那就太好了,而且如果您不介意向我解释我的语法或思路有什么问题,我们将不胜感激。

【问题讨论】:

  • 您是否考虑过使用 INSTEAD OF 触发器?
  • UPDATE o SET UpdatedAt = GETDATE() FROM dbo.Orders AS o INNER JOIN inserted AS i ON o.key_column = i.key_column; 您实际上并不需要执行IF EXISTS 检查 - 这只是更新中固有的额外的、不必要的操作。
  • 我没有。我会去调查它@CodeMagician。这是否需要更大的查询?此表中行的大部分更新将通过表单进行,并且可能会同时更新许多不同的列。
  • 这将需要额外的代码,并且有一些维护负担,因为对表的更改通常需要对触发器进行更改。我只喜欢那个解决方案,因为我喜欢避免触发器可能触发触发器并导致问题。我在下面的答案中写了一个安全的解决方案。

标签: sql-server triggers


【解决方案1】:

您不能像那样真正访问插入的表。只有Set UpdatedAt =... 是一个不完整的陈述。隐含地它对您有意义,但即使在您的触发器中,您也必须制作完整的 SQL 语句。

执行此操作的方法是 JOIN 到 INSERTED 表(在下面的示例中,我使用的是半连接)然后您可以使用 INSERTED 表的内容来执行另一个更新。

CREATE TRIGGER [dbo].[trgTimestampAfterUpdate] ON dbo.orders
    FOR UPDATE
AS
BEGIN
    IF NOT(UPDATE(UpdatedAt)) --Avoid triggers firing triggers
    BEGIN

        UPDATE  dbo.orders
        SET     UpdatedAt = GETDATE()
        WHERE   id IN ( SELECT id
                        FROM   inserted )

    END
END

在此代码示例中需要注意两件非常重要的事情。首先更新带有触发器的表将导致触发器再次触发(创建一个循环,该循环将增加,直到您达到系统上嵌套触发器的最大级别。)我进行检查以确保它终止,如果你是只更新updatedat 列。

其次,永远不要假设插入的表中只有一行。下面的代码是一个非常常见的错误

DECLARE @id INT
SELECT @id = id FROM INSERTED 

UPDATE MyTable 
SET UpdatedAT = GETDATE() 
WHERE id = @id
--DON'T DO THIS!

这看起来不错,是一个常见错误,但它只会更新 1 条记录,并且 INSERTED 表中可能有任意数量条记录。

【讨论】:

  • 这个解决方案效果很好,谢谢@CodeMagician。只是为了确保我清楚为什么会这样,基本上我执行了一个不完整的 SQL 语句?访问虚拟 INSERTED 或 DELETED 表的正确方法是通过 where 或内部连接,具体取决于您希望如何使用或访问它们。对吗?
  • 另外,感谢您对避免触发器触发其他触发器的见解。我什至没有关于那个!
  • 没错。乐于助人!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-03-02
  • 2012-01-03
  • 1970-01-01
  • 2017-05-29
  • 1970-01-01
  • 2010-12-11
  • 1970-01-01
相关资源
最近更新 更多