SQL Server 2008:更新触发器中的多个列

时间:2013-12-12 00:16:25

标签: sql sql-server

也许我原来的帖子有点乱,所以我得不到多少帮助。我用AuditTest表更新了我的触发器....请看看你是否可以提供帮助。

我对触发器非常陌生,并尝试将审计表放在一起,以跟踪某些列的值更改。

我有很多专栏:Qty, UnitSell, Discount, ProductName等等。以下代码似乎有效,可检测QtyUnitSell值更改,然后INSERT INTO审核表(现在我将其命名为TEST1

如果我继续为其他列重复IF UPDATE(FieldName)语句,我认为它会起作用,但是它过于繁琐,不断重复相同的代码。

这样可以优化这个,所以我不必重复相同的IF UPDATE (Fieldname)语句吗?

alter TRIGGER trigger_Test_AfterUpdate 
ON [dbo].ERP_QuoteDetail 
FOR UPDATE
AS
    declare @QuoteDetailID int; 
    select @QuoteDetailID = i.QuoteDetailID from inserted i;  

    --- Updating QTY if old/new value change
    DECLARE @iQty int; SELECT @iQty = i.Qty from inserted i; 
    DECLARE @dQty int; SELECT @dQty = d.Qty from deleted d; 

    if update(QTY) and exists (select * from deleted d WHERE Qty <> @iQty) 
    BEGIN
        -- Insert into the audit table
        insert into AuditTest (
                [Type]
               ,[TableName]
               ,[PKCol]
               ,[PK]
               ,[FieldName]
               ,[OldValue]
               ,[NewValue]
               ,[UpdateDate]
               ,[DBUsername]
               ,[UserID]
               ) 
        values('u'
                , 'Table_QuoteDetail'
               , 'QuoteDetail'
               , @QuoteDetailID
               , 'QTY'
               , @dQty
               , @iQty
               , GETDATE()
               , '123'
               , '456'             
                );

        PRINT 'AFTER UPDATE Trigger fired.'
    END

--- Updating QTY if old/new value change
DECLARE @iUnitSell int; SELECT @iUnitSell = i.UnitSell from inserted i;
DECLARE @dUnitSell int; SELECT @dUnitSell = d.Qty from deleted d; 
if update(UnitSell) and exists (select * from deleted d
         WHERE UnitSell <> @iUnitSell ) 
    BEGIN

        -- Insert into the audit table
        insert into AuditTest (
                [Type]
               ,[TableName]
               ,[PKCol]
               ,[PK]
               ,[FieldName]
               ,[OldValue]
               ,[NewValue]
               ,[UpdateDate]
               ,[DBUsername]
               ,[UserID]
               ) 
        values('u'
                , 'Table_QuoteDetail'
               , 'QuoteDetail'
               , @QuoteDetailID
               , 'UnitSell'
               , @dUnitSell
               , @iUnitSell
               , GETDATE()
               , '123'
               , '456'             
                );

        PRINT 'AFTER UPDATE Trigger fired.'
    END
GO

2 个答案:

答案 0 :(得分:1)

您可以考虑使用SQL Server的“更改数据捕获”功能进行审核。对于启用了CDC的表,CDC会存储所有插入,更新和删除的行的记录。这将有效地取代您的情况下触发器的需要。

可以找到有关如何启用和配置CDC的详细信息here

答案 1 :(得分:0)

您的根本缺陷是,您似乎希望触发器每行一次 - 这在SQL Server中是 NOT 。相反,触发器会在每个语句时触发,而伪表Deleted可能包含多行

鉴于该表可能包含多行 - 您希望在这里选择哪一行?

select @QuoteDetailID = i.QuoteDetailID from inserted i; 

未定义 - 您可以从Inserted中的任意行获取值。

您需要在知道InsertedDeleted伪表包含多行的情况下重写整个触发器。您需要使用基于集合的操作 - 不要只期望DeletedInserted中的一行!