SQL Server – Detect Changes in a Single Column with Triggers

sql serversql server 2014

I have an after update trigger that is queuing record ID's into another table for further processing at a later time. It uses inserted to get the ids of the records to process.

I'd now like to exclude certain records being queued to that table if the only change has been to one particular column. If any other columns beyond that one column are changed I still want to queue the record.

How can I identify if only one particular column has been changed?

I've had a look at UPDATE(), but it seems like I'd need to list out all the other 47 columns on the table, which I'd like to avoid.

COLUMNS_UPDATED as used in How to use COLUMNS_UPDATED to check if any of certain columns are updated? seemed promising, but I can't get it to work.
The column I want to exclude has the ColumnID 30. By my figuring that gives me an integer bitmask of 536,870,912 (SELECT POWER(2, 30 - 1)).

The calculator in Windows tells me that is correct to have the 30th bit set.
enter image description here

When I did an UPDATE to just the column I want to exclude COLUMNS_UPDATED() returned 0x000000200040. That to be gives a bit pattern that suggests two completely different columns were updated. Column Id's 7 (2^(7-1)=64) and 22 (2^(22-1)=2,097,152).

enter image description here

I'm not sure it it is worth pursing that approach. It seems like it would be an easy comparison to pickup any changes to other fields.

UPDATE:
I've resorted to using a CHECKSUM comparison other fields between inserted and deleted. I'd prefer not to use this approach as it could cause problems if other fields are added to the table in the future. There is also the chance that a hash collision could occur.

Best Answer

You should be able to create two temp tables (#deleted, #inserted) using SELECT * INTO syntax and then alter the temp tables dropping the column you don't care about. Then use EXCEPT to find if other columns have changed.

set nocount on
IF OBJECT_ID('dbo.TestTable', 'U') IS NOT NULL 
  DROP TABLE dbo.TestTable; 
Create table dbo.TestTable (Id int, Col1 varchar(10), Col2 varchar(10), Col3 varchar(10))

insert into dbo.TestTable (Id, Col1, col2, col3) values(1,'one','one','one')
insert into dbo.TestTable (Id, Col1, col2, col3) values(1,'two','two','two')
go
create TRIGGER dbo.AfterUpdateTrigger ON dbo.TestTable
AFTER UPDATE
AS
BEGIN
    SET NOCOUNT ON;

    SELECT * INTO #deleted FROM deleted
    SELECT * INTO #inserted FROM inserted

    ALTER TABLE #deleted DROP COLUMN col2
    ALTER TABLE #inserted DROP COLUMN col2

    select * from #deleted
    except 
    select * from #inserted

END
GO

update dbo.TestTable set col2 = 'three'
update dbo.TestTable set Col1 = 'three'