SQL - 仅当用户进行更新时触发插入

SQL - trigger insert only when a user made an update

我有一个 table、customers_accounts,用于跟踪帐户中客户的一些基本信息。当客户的文件被打开时,我从外部系统同步信息,以便我们的用户获得最新的信息。

UPDATE 
    customers_accounts
SET
    first_name = 'bob',
    last_name = 'burger'
WHERE 
    account_number = '12345'

当用户更新帐户时,我执行相同的查询,但我更新了一个列,指示最后一个进行更改的用户

UPDATE 
    customers_accounts
SET
    first_name = 'bob',
    last_name = 'burger',
    updated_by = 'H Jon Benjamin',
    updated_on = GETDATE()
WHERE 
    account_number = '12345'

这是我要解决的问题。我想跟踪历史记录 table 中的更改,但只记录用户所做的更改,而不是来自外部系统的更改。所以我的计划是创建一个触发器,如果​​用户列在插入时不为空,则插入一行(因为 updated_by 在上面的第一次更新中隐式为空)

我试过的是这样的:

ALTER trigger [dbo].[Accounts_Customers_LogUpdate] 
ON [dbo].[Accounts_Customers]
AFTER UPDATE
AS
    DECLARE @Now AS DATETIME = GETDATE()
    DECLARE @User AS NVARCHAR(150)

    SELECT @User = (SELECT [updated_by] FROM INSERTED)

    IF (@User IS NOT NULL)
    BEGIN
        SET NOCOUNT ON

        INSERT INTO [dbo].[Accounts_Customers-History]
            SELECT *, @User, @Now
            FROM inserted
    END

Accounts_Customers-History 是 table 的精确副本,带有两个额外的列,change_made_bychange_made_on

它的表现与我预期的不同。它会将 updated_by 中的任何值插入到 change_made_by 中,而不管查询中 updated_by 的值如何。所以我正在记录 activity 由用户和导入触发。

为此使用 UPDATE()

Returns a Boolean value that indicates whether an INSERT or UPDATE attempt was made on a specified column of a table or view. UPDATE() is used anywhere inside the body of a Transact-SQL INSERT or UPDATE trigger to test whether the trigger should execute certain actions.

这意味着 update 函数将 return false 用于问题中的第一个更新语句,而 true 用于第二个更新语句 - 这正是你需要什么。

另外,请注意您应该始终在插入语句中指定列列表, 并且始终在 select 语句中指定列列表。 ()

您的触发器的修订版本可能如下所示:

ALTER TRIGGER [dbo].[Accounts_Customers_LogUpdate] 
ON [dbo].[Accounts_Customers]
AFTER UPDATE

AS

DECLARE @Now as DateTime = GetDate()
IF UPDATE(updated_by)
BEGIN

    -- Always specify the columns list in an insert statement!
    insert into [dbo].[Accounts_Customers-History] (<Columns list>)
    -- Always specify the columns list in a select statement!
    select <columns list>,  @Now
    from inserted

END

请注意,如果触发触发器的插入或更新语句成功,UPDATE() 函数不会向您提供任何指示,也不会向您提供列值是否实际更改的指示- 它仅指示该列是否是触发触发器的插入或更新语句的一部分 - 正如您在备注部分的最后一段中所读:

If a trigger applies to a column, the UPDATED value will return as true or 1, even if the column value remains unchanged. This is by-design, and the trigger should implement business logic that determines if the insert/update/delete operation is permissible or not.