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

时间:2019-06-11 14:05:47

标签: sql-server sql-server-2008-r2

我有一个表格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'

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

我尝试过的是:

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是表的精确副本,另外还有两列change_made_bychange_made_on

它不符合我的期望。它将updated_by中的任何值插入change_made_by中,而不管查询中updated_by的值如何。因此,我得到了由用户和导入触发的记录活动。

1 个答案:

答案 0 :(得分:2)

为此使用UPDATE()

  

返回一个布尔值,该布尔值指示是否对表或视图的指定列进行了INSERT或UPDATE尝试。 UPDATE()用于Transact-SQL INSERT或UPDATE触发器体内的任何位置,以测试该触发器是否应执行某些操作。

这意味着update函数将为问题中的第一条更新语句返回false,并为第二条更新语句返回true-这正是您所需要的。

此外,请注意,您应始终在插入语句中指定列列表, 并且还要始终在select语句中指定列列表。 (Why?

触发器的修订版可能看起来像这样:

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()函数不会向您发出任何触发触发器的插入或更新语句是否成功的指示,也不会给您指示该列的值是否实际上已更改-仅指示该列是否是触发触发器的insert或update语句的一部分-如您在备注部分的最后一段中所读:

  

如果触发器应用于列,则即使列值保持不变,UPDATED值也将返回true或1。这是设计使然,触发器应实现确定插入/更新/删除操作是否允许的业务逻辑。