I am struggling to understand how to use Change tracking for a simple task (not so simple it looks like) of tracking individual column changes to the same row?
Consider the following example:
I have a table:
CREATE TABLE [dbo].[Products](
[Id] [int] IDENTITY(1,1) NOT NULL,
[Name] [nvarchar](max) NULL,
[Manufacturer] [nvarchar](max) NULL,
[Country] [nvarchar](max) NULL,
CONSTRAINT [PK_Products] PRIMARY KEY CLUSTERED ([Id] ASC)
Now I insert a row:
insert into Products ([Name],[Manufacturer],[Country])
values ('phone', 'sony', 'japan')
I add change tracking:
ALTER DATABASE [Test]
SET CHANGE_TRACKING = ON
(CHANGE_RETENTION = 90 MINUTES, AUTO_CLEANUP = ON);
ALTER TABLE [dbo].[Products]
ENABLE CHANGE_TRACKING
WITH (TRACK_COLUMNS_UPDATED = ON);
I run 1st update:
update Products set Manufacturer = 'Sega' where Name = 'phone'
I check 2 column updates:
select
CHANGE_TRACKING_IS_COLUMN_IN_MASK(COLUMNPROPERTY(OBJECT_ID('dbo.Products'),'Manufacturer', 'ColumnId'), CT.SYS_CHANGE_COLUMNS) 'Changed?', *
FROM
CHANGETABLE(CHANGES dbo.Products, 0) AS CT
order by sys_change_version;
select
CHANGE_TRACKING_IS_COLUMN_IN_MASK(COLUMNPROPERTY(OBJECT_ID('dbo.Products'),'Country', 'ColumnId'), CT.SYS_CHANGE_COLUMNS) 'Changed?', *
FROM
CHANGETABLE(CHANGES dbo.Products, 0) AS CT
order by sys_change_version;
So far so good, as you can see only the Manufacturer column is reported as changed as expected.
However if I now try to run a 2nd update on the same row for a different column:
update Products set Country = 'USA' where Name = 'phone'
and run the same query above to check columns that have been updated, I get back that BOTH! columns have been updated:

I would expect that the 2nd time I run update the change tracking would only show me the 2nd column as the one that has changed, not both of them!
It gets worse. If I then try and separate the updates by their SYS_CHANGE_VERSION number, that is supposed to track separate updates, I realise that both of these updates have been assigned the same number!:
select * from CHANGETABLE(CHANGES dbo.Products, 0) as changes
Which looks like a bug to me!
I don't want to trigger processing for Manufacturer column when I am updating a Country column on the row.
I scoured the internet but couldn't find any obvious solution to this problem. The obvious solution of cleaning table manually also seems not so straightforward and comes with its own can of worms.
Obviously change tracking has been around for a long time, so it is either I am missing something, or I am very surprised that bug has not been fixed (or even encountered by many people)
Am I missing something obvious here? Or does anyone knows how to make change tracking work for identifying column changes ONE AT A TIME like I imagine they were supposed to work?



Here's a little script demostrating change tracking.
I create a separate procedure to do the change tracking "thing", because it's a repetitive task.
Change tracking relies on the "current version" value, which needs to be advanced all the time. For this reason, one needs to store the value in some table, i've implemented a simple per table tracking by storing it in the
trackingtable.Every time changes occur, you get them by using the previous value you obtain by calling
CHANGE_TRACKING_CURRENT_VERSION, these changes can affect both multiple rows and multiple columns.By using the
CHANGE_TRACKING_IS_COLUMN_IN_MASKyou can obtain which columns were affected by the changes.I don't quite understand why this doesn't work for you, since you:
If you're only interested in changes occuring to specific columns you can do the
CHANGE_TRACKING_IS_COLUMN_IN_MASKthing and it should workThere is no difference here if multiple changes are collapsed into one or not, unless you're really interested in knowing that column X was changed Y number of times - but this is seldom needed.
The collapse changes example is: