更新后,在SQL Server中触发并更新到一行

Mar*_*ark 2 sql sql-server sql-server-2008

这是保持对数据库行的更改的简单跟踪的最佳方法:

ALTER TRIGGER [dbo].[trg_121s] 
ON  [dbo].[121s]
  AFTER UPDATE
AS 
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;

-- Insert statements for trigger here

update dbo.[121s]
set modified=getdate()
where id in 
(select distinct ID from Inserted)

END
Run Code Online (Sandbox Code Playgroud)

因此,对[121s]中某行的任何更新都将导致修改的列被更新.

它有效,但我不确定它是否是实现这一目标的最佳方式.

我对这条线路感到困惑:

(select distinct ID from Inserted)
Run Code Online (Sandbox Code Playgroud)

...以及它如何知道它获得正确的行ID.

感谢您的任何确认/澄清,

标记

Aar*_*and 19

inserted是一个伪表,它肯定包含受该UPDATE语句影响的所有正确的行(我认为DISTINCT没有必要,如果ID是主键 - 虽然很难说这个表的名称是什么121s).在应用修改日期/时间之前,您是否可以考虑验证所有这些值是否实际更改了值.除此之外,我可能会这样做:

ALTER TRIGGER [dbo].[trg_121s] 
ON [dbo].[121s]
AFTER UPDATE
AS 
BEGIN
  SET NOCOUNT ON;

  UPDATE t SET modified = CURRENT_TIMESTAMP
   FROM dbo.[121s] AS t
   WHERE EXISTS (SELECT 1 FROM inserted WHERE ID = t.ID);
END
GO
Run Code Online (Sandbox Code Playgroud)

如果你想要100%万无一失的保证他们都使用相同的时间戳更新(虽然我不知道在这个用例中我是否见过多个值):

ALTER TRIGGER [dbo].[trg_121s] 
ON [dbo].[121s]
AFTER UPDATE
AS 
BEGIN
  SET NOCOUNT ON;

  DECLARE @ts DATETIME;
  SET @ts = CURRENT_TIMESTAMP;

  UPDATE t SET modified = @ts
   FROM dbo.[121s] AS t
   WHERE EXISTS (SELECT 1 FROM inserted WHERE ID = t.ID);
END
GO
Run Code Online (Sandbox Code Playgroud)

如果您想确保仅在列foo更改值时才会发生更新,您可以说:

  UPDATE t SET modified = @ts
   FROM dbo.[121s] AS t
   INNER JOIN inserted AS i
   ON t.ID = i.ID
   AND t.foo <> i.foo;
Run Code Online (Sandbox Code Playgroud)

如果可以foo为空则变得更加复杂,但这是一般模式.