I have a trigger in SQL Server 2005 that is used to track audit changes on specific fields. We track the changes in a separate table. This trigger works as expected for the single record entries which is how it was intended but now they want to track changes made to the column via a bulk update.
Current trigger:
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
This code doesn’t work for multiple records it throws an error:
Subquery returned more than 1 value. This is not permitted when the subquery
follows =, !=, <, <= , >, >= or when the subquery is used as an expression.
How can I alter my current trigger to work for a bulk update. Do I have to use a cursor to do it? If so, then can someone offer some sample code?
How are you setting @UpdatedDate and @UpdatedBy when there is more than one record? I suspect you are doing something like this, which is what you are doing for one record.
The SET under ELSE will cause the error if there is more than one row in INSERTED.
Try this instead
This should work for any number of records, including just one. Note that I am not checking
UPDATE(ActDate). No records will be returned if ActDate did not change.