I need to create a trigger that will add a record to a queue table whenever a record is modified in the main table. The record added to the queue table must contain every field that was modified for that record.
I have this code so far but I don’t think it will work for multiple rows updated:
ALTER TRIGGER [dbo].[tr_EmpHistory]
ON [dbo].[employeeData]
FOR UPDATE
AS
BEGIN
DECLARE @FieldsUpdated xml,
@FieldsUpdated1 varchar(100)
SELECT @Fieldsupdated1 = ' '
SELECT
@FieldsUpdated1 = @FieldsUpdated1 + ' emp_bankaccountnumber'
FROM inserted as a,
deleted as b
WHERE a.emp_id = b.emp_id
AND a.emp_bankAccountNumber <> b.emp_bankAccountNumber
SELECT
@FieldsUpdated1 = @FieldsUpdated1 + 'emp_salary '
FROM inserted as a,
deleted as b
WHERE a.emp_id = b.emp_id
AND a.emp_salary <> b.emp_salary
SELECT
@FieldsUpdated1 = @FieldsUpdated1 + 'emp_SSN '
FROM inserted as a,
deleted as b
WHERE a.emp_id = b.emp_id
AND a.emp_SSN <> b.emp_SSN
SELECT
@FieldsUpdated1 = @FieldsUpdated1 + 'emp_lname '
FROM inserted as a,
deleted as b
WHERE a.emp_id = b.emp_id
AND a.emp_lname <> b.emp_lname
SELECT
@FieldsUpdated1 = @FieldsUpdated1 + 'emp_fname '
FROM inserted as a,
deleted as b
WHERE a.emp_id = b.emp_id
AND a.emp_fname <> b.emp_fname
SELECT
@FieldsUpdated1 = @FieldsUpdated1 + 'emp_manager '
FROM inserted as a,
deleted as b
WHERE a.emp_id = b.emp_id
AND a.emp_manager <> b.emp_manager
SELECT @Fieldsupdated = (
SELECT COLUMN_NAME AS Name
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'employeeData'
AND CHARINDEX(COLUMN_NAME,(ltrim(rtrim(@fieldsupdated1)))) > 0
FOR XML AUTO, ROOT('Fields') )
INSERT INTO auditEmployeeData(
audit_emp_id,
audit_emp_bankAccountNumber,
audit_emp_salary,
audit_emp_SSN,
audit_emp_lname,
audit_emp_fname,
audit_emp_manager,
ColumnsUpdated )
SELECT emp_id,
emp_bankAccountNumber,
emp_salary,
emp_SSN,
emp_lname,
emp_fname,
emp_manager,
@FieldsUpdated
FROM INSERTED
END
GO
If I am understanding this correctly, if one record had last name updated and another record got the first name updated at the same time then both records would be logged as having both first and last named changed. Is that correct? If so, how could I make it work correctly without using a cursor?
The only way I can think to solve the problem is to use a cursor but I know that is not a good idea. Any help would be appreciated.
Thanks!
You can use
CASEto build a value row-by-row showing the changed columns:Some additional fiddling about can eliminate the extra delimiter.