I am desperately trying to get an audit solution working with only changed values being sent to the audit table. Here is waht I have so far - can anyone please help with the two lines I've pointed out?
Code:
-- Drop objects if they already exist.
IF OBJECT_ID('TestTrigger_Update') IS NOT NULL DROP TRIGGER TestTrigger_Update
IF OBJECT_ID('TestTable') IS NOT NULL DROP TABLE TestTable
IF OBJECT_ID('TestTableAudit') IS NOT NULL DROP TABLE TestTableAudit;
GO
-- Create a test table.
CREATE TABLE TestTable(TestTableID INT IDENTITY (1, 1), MyCol1 INT, MyCol2 INT, MyCol3 INT, MyCol4 INT);
GO
-- Insert a record.
INSERT INTO TestTable
SELECT 9, 8, 7, 6
GO
-- Create the audit table.
CREATE TABLE TestTableAudit(
TestTableAuditID INT IDENTITY (1, 1),
TableName NVARCHAR(200),
RecordID INT,
ColumnName NVARCHAR(200),
OldValue NVARCHAR(MAX),
NewValue NVARCHAR(MAX))
GO
-- Create the update trigger.
CREATE TRIGGER TestTrigger_Update ON TestTable FOR UPDATE AS
BEGIN
DECLARE @ColumnsUpdated VARBINARY(MAX)
DECLARE @ColumnName NVARCHAR(200)
DECLARE @OldValue NVARCHAR(MAX)
DECLARE @NewValue NVARCHAR(MAX)
SET @ColumnsUpdated = COLUMNS_UPDATED()
-- Loop through the columns that have changed.
DECLARE ChangedColumnCursor CURSOR FAST_FORWARD FOR SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'TestTable' AND sys.fn_IsBitSetInBitmask(@ColumnsUpdated, COLUMNPROPERTY(OBJECT_ID(TABLE_SCHEMA + '.' + TABLE_NAME), COLUMN_NAME, 'ColumnID')) <> 0
OPEN ChangedColumnCursor
FETCH NEXT FROM ChangedColumnCursor INTO @ColumnName
WHILE @@FETCH_STATUS = 0
BEGIN
-- TODO: Set the @OldValue and @NewValue from the Inserted and Deleted respectively.
-- How do I do this... ???
sp_executesql N'SET @Old = SELECT ' + @ColumnName + N' FROM Deleted', N'@Old NVARCHAR(MAX) OUT', @Old = @OldValue OUTPUT
sp_executesql N'SET @New = SELECT ' + @ColumnName + N' FROM Inserted', N'@New NVARCHAR(MAX) OUT', @New = @NewValue OUTPUT
INSERT INTO TestTableAudit (TableName, RecordID, ColumnName, OldValue, NewValue) SELECT
'TestTable',
Inserted.TestTableID,
@ColumnName,
@OldValue,
@NewValue
FROM Inserted FULL OUTER JOIN Deleted ON Inserted.TestTableID = Deleted.TestTableID
FETCH NEXT FROM ChangedColumnCursor INTO @ColumnName
END
CLOSE ChangedColumnCursor
DEALLOCATE ChangedColumnCursor
END
GO
-- Update a couple of columns.
UPDATE TestTable SET MyCol1 = 1234, MyCol3 = 1234
GO
-- Show the results.
SELECT * FROM TestTableAudit
GO