如何在 AFTER UPDATE 触发器中仅引用受影响的行

Paw*_*l85 6 trigger sql-server t-sql sql-server-2012 row-modification-time

我有这张桌子:

在此处输入图片说明

我正在尝试创建一个更新触发器,每当对or列执行更新时,该触发器就会更新last_updated_on = GETDATE()last_updated_by = SYSTEM_USER列。step_numberstep_name

我开始创建它

ALTER TRIGGER tr_app_bread_crumbs_afterupdate
ON [dbo].[app_bread_crumbs]
AFTER UPDATE
AS
BEGIN 
    UPDATE [dbo].[app_bread_crumbs]
    SET last_updated_by = SYSTEM_USER,
    last_updated_on = GETDATE()
END
Run Code Online (Sandbox Code Playgroud)

但这将一次更新所有行。我正在尝试弄清楚如何指定仅更新last_updated_onlast_updated_by由正在更新的特定行的触发器。

例如,如果他们更新:

UPDATE [dbo].[app_bread_crumbs]
    SET step_name = 'DAMAGE' WHERE step_number = 1
Run Code Online (Sandbox Code Playgroud)

触发器应该只更新第一行

Han*_*non 10

使用inserted表,这是一个在触发器内可用的特殊表,其中包含将被更新/插入到表中的行。

ALTER TRIGGER tr_app_bread_crumbs_afterupdate
ON [dbo].[app_bread_crumbs]
AFTER UPDATE
AS
BEGIN 
    UPDATE [dbo].[app_bread_crumbs]
    SET last_updated_by = SYSTEM_USER,
    last_updated_on = GETDATE()
    FROM dbo.app_bread_crumbs abc
    WHERE EXISTS (SELECT 1 FROM inserted i WHERE i.id = abc.id);
END
Run Code Online (Sandbox Code Playgroud)

  • ...或连接到 `inserted` 以确保这些值已更改,因为如果提及列,则 `UPDATE()` 返回 true,无论值是否实际更改。 (2认同)

ype*_*eᵀᴹ 6

您需要使用INSERTEDDELETED伪表。一种方法:

ALTER TRIGGER tr_app_bread_crumbs_afterupdate
ON [dbo].[app_bread_crumbs]
AFTER UPDATE
AS
BEGIN
    UPDATE upd
    SET last_updated_by = SYSTEM_USER,
        last_updated_on = GETDATE()
    FROM [dbo].[app_bread_crumbs] AS upd
      JOIN Inserted AS i
        ON i.id = upd.id
      JOIN Deleted AS d
        ON d.id = i.id
    WHERE NOT EXISTS                              -- only when any      
            ( SELECT i.sep_number, i.step_name    -- of the 2 columns
            INTERSECT                             -- changed
              SELECT d.sep_number, d.step_name
            ) ;
END ;
Run Code Online (Sandbox Code Playgroud)