2012-02-02 66 views
1

我在SQL Server 2005中有一个触发器,用于跟踪特定字段上的审计更改。我们在单独的表格中跟踪更改。该触发器按照预期的方式对单个记录条目按预期工作,但是现在他们希望通过批量更新来跟踪对列进行的更改。无光标触发批量更新

当前触发:

CREATE TRIGGER [dbo].[trg_LogChanges] 
    ON [dbo].[Test] 
    FOR UPDATE 
AS 

DECLARE @TableName VARCHAR(100) , 
    @UpdatedDate smalldatetime , 
    @UpdatedBy uniqueidentifier 

SELECT @TableName = 'dbo.Test' 

IF(SELECT COUNT(*) FROM INSERTED) = 1 
    BEGIN 
     IF(SELECT LastModifiedDate FROM INSERTED) Is Null 
     SET @UpdatedDate = getdate() 
     ELSE 
     SET @UpdatedDate = (SELECT LastModifiedDate FROM INSERTED) 

     IF(SELECT LastModifiedBy FROM INSERTED) Is Null 
     SET @UpdatedBy = '11111111-1111-1111-1111-111111111111' 
     ELSE 
     SET @UpdatedBy = (SELECT LastModifiedBy FROM INSERTED) 

      IF UPDATE (ActDate) 
     BEGIN 
     INSERT INTO dbo.LogChanges 
     (
      ChangeType 
      , TableName 
      , RecordGuid 
      , FieldName 
      , OldValue 
      , NewValue 
      , UpdatedBy 
      , UpdatedDate 
     ) 
     SELECT 
      'U' 
      , @TableName 
      , d.Guid 
      , 'ActDate' 
      , d.ActDate 
      , i.ActDate 
      , @UpdatedBy 
      , @UpdatedDate 
     FROM INSERTED i 
     INNER JOIN DELETED d 
      on i.Guid = d.Guid 
     WHERE 
      (d.ActDate IS NULL AND i.ActDate IS NOT NULL) 
      OR (d.ActDate IS NOT NULL AND i.ActDate IS NULL) 
      OR (d.ActDate <> i.ActDate) 
     END 
     -- this keeps going for each field that we need to get the Audit Trail on 
    END 
ELSE 
    BEGIN 
     -- now I need to track for multiple records 
     -- I tried changing the WHERE clause above to see if it would work for bulk updates 
     INSERT INTO... 
     SELECT... 
     WHERE 
    (
     (d.ActDate IS NULL AND i.ActDate IS NOT NULL) 
     OR (d.ActDate IS NOT NULL AND i.ActDate IS NULL) 
     OR (d.ActDate <> i.ActDate) 
    ) 
    AND d.ActDate IN (SELECT d.ActDate FROM DELETED d) 
    END 

此代码不能用于多个记录的工作,它抛出一个错误:

Subquery returned more than 1 value. This is not permitted when the subquery 
follows =, !=, <, <= , >, >= or when the subquery is used as an expression. 

我怎样才能改变我的电流触发的批量更新工作。我必须使用光标才能做到这一点吗?如果是这样,那么有人可以提供一些示例代码?

+0

好吧,最后一个'INSERT'上的'SELECT'很重要,请显示所有代码 – Lamak 2012-02-02 15:11:50

+0

Select与单个条目相同。 – Taryn 2012-02-02 15:14:40

回答

2

当有多条记录时,你如何设置@UpdatedDate和@UpdatedBy?我怀疑你正在做这样的事情,这就是你为一个记录做的事情。

IF(SELECT LastModifiedBy FROM INSERTED) Is Null 
    SET @UpdatedBy = '11111111-1111-1111-1111-111111111111' 
ELSE 
SET @UpdatedBy = (SELECT LastModifiedBy FROM INSERTED) 

如果在INSERTED中存在多于一行,则ELSE下的SET将导致错误。

试试这个

INSERT INTO dbo.LogChanges 
(
ChangeType 
, TableName 
, RecordGuid 
, FieldName 
, OldValue 
, NewValue 
, UpdatedBy 
, UpdatedDate 
) 
SELECT 
'U' 
, @TableName 
, d.Guid 
, 'ActDate' 
, d.ActDate 
, i.ActDate 
, ISNULL(LastModifiedBy, '11111111-1111-1111-1111-111111111111') 
, ISNULL(LastModifiedDate, getdate()) 
FROM INSERTED i 
INNER JOIN DELETED d 
    on i.Guid = d.Guid 
WHERE (d.ActDate IS NULL AND i.ActDate IS NOT NULL) 
    OR (d.ActDate IS NOT NULL AND i.ActDate IS NULL) 
    OR (d.ActDate <> i.ActDate) 

这应该任意数量的记录,其中只有一个工作。请注意,我没有检查UPDATE(ActDate)。如果ActDate没有更改,则不会有任何记录返回。

+0

非常感谢。我没有意识到这是我上次修改/最后修改日期的第一个选择语句,它们抛出错误 – Taryn 2012-02-02 15:26:40