【问题标题】:Update one column in a trigger after updating only particular column in the same table in SQL Server 2008在 SQL Server 2008 中仅更新同一表中的特定列后更新触发器中的一列
【发布时间】:2015-05-04 19:19:51
【问题描述】:

我有下面这个结构的表格:

CREATE TABLE [dbo].[Tasks]
(
    [TasksID] [int] IDENTITY(1,1) NOT NULL,
    [CommitteeID] [int] NULL,
    [TransactionDateTime] [datetime2](7) NULL,
    [inspectionStatus] [nvarchar](50) NULL,
    [Latitude] [nvarchar](50) NULL,
    [Longitude] [nvarchar](50) NULL,
    [acceptanceState] [nvarchar](50) NULL,
    [comments] [nvarchar](350) NULL,
    [ScheduledDateTime] [datetime2](7) NULL,
)

我真正想要的是创建一个使用当前日期时间更新[TransactionDateTime] 的触发器,前提是更新了[acceptanceState] 列。

我创建了以下触发器

CREATE TRIGGER [dbo].[TransactionDateUpdate]
ON [dbo].[Tasks]
AFTER UPDATE  
AS BEGIN
   UPDATE dbo.Tasks
   SET TransactionDateTime = GETDATE()
   FROM INSERTED i
   WHERE i.TasksID = Tasks.TasksID 
END

这个触发器的问题是它会更新列[TransactionDateTime],但是如果我对表中的任何列进行了更改,我想要的是仅在列[acceptanceState] 更改时更新[TransactionDateTime] /更新。我能找到任何帮助吗?仅当[acceptanceState]被更改/更新时,如何添加更新[TransactionDateTime]的条件?

我搜索了很多类似的问题,但没有找到完全相同的问题。

【问题讨论】:

  • 您必须将已删除的表添加到您的查询中,并检查插入和删除的值是否不同。
  • 另外我相信 SQL Server 有一个函数“IF UPDATE(ColumnName)”可以让你检查某个列是否被更新了。
  • @TabAlleman:不过,这将如何处理多行更新?
  • @TabAlleman 使用 UPDATE(ColumnName) 的一个问题是,如果该列包含在更新中,它会返回 true。它不考虑实际值。换句话说,即使新旧值相同,它也会返回 true。
  • True,@SeanLange,当列不可能发生变化时,IF UPDATE() 可用于使处理器免于执行查询,但它确实如您所说,如果返回 true该列包含在更新语句中,无论值是否更改。

标签: sql-server sql-server-2008 triggers updates


【解决方案1】:

您只需要在触发器中添加一个 IF UPDATE 检查并加入已删除的表:

CREATE TRIGGER [dbo].[TransactionDateUpdate]
ON [dbo].[Tasks]
AFTER UPDATE  
AS 
BEGIN
   IF UPDATE(acceptanceState)  --add this line
   UPDATE dbo.Tasks
   SET TransactionDateTime = GETDATE()
   FROM INSERTED i
   JOIN DELETED d on i.TasksID = d.TasksID --add this line
   WHERE i.TasksID = Tasks.TasksID 
END

【讨论】:

  • 很高兴听到这个消息!如果您能帮我一个忙并将其标记为已接受的答案,那就太好了!谢谢!
  • 我标记了,不好意思,我是新来的,之前不知道这个标记
  • 别担心! :) 我每天都在这里学到新东西!再次感谢!
  • 仅了解此功能以检查更新了哪一列。对我来说是新的!
【解决方案2】:

最好的方法是比较InsertedDeleted 伪表。在AFTER UPDATE 触发器中,Deleted 伪表包含旧值,而Inserted 包含新值。因此,如果Deleted.acceptanceStateInserted.acceptanceState 不同,则该列已更新。

所以你需要像这样稍微延长你的触发器:

CREATE TRIGGER [dbo].[TransactionDateUpdate]
ON [dbo].[Tasks]
AFTER UPDATE  
AS BEGIN
   UPDATE dbo.Tasks
   SET TransactionDateTime = GETDATE()
   FROM Inserted i
   INNER JOIN Deleted d ON i.TasksID = d.TasksID
   WHERE i.TasksID = Tasks.TasksID 
     AND i.acceptanceState <> d.acceptanceState
END

【讨论】:

  • 比接受的答案更喜欢这个。但是WHERE 子句不应该也包括null 吗? AND (i.acceptanceState &lt;&gt; d.acceptanceState OR d.acceptanceState IS NULL AND i.acceptanceState IS NOT NULL)
猜你喜欢
  • 2011-07-17
  • 1970-01-01
  • 2015-08-18
  • 1970-01-01
  • 2023-03-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多