Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Trying to understand some SQL Server change tracking features

I'm working on SQL Server 2016 SP1 with the Change Tracking feature and I have a question for you.

I have a database which has Change Tracking enabled. That database contains a table Table which has "change tracking" activated, but not "track columns updated" option.

For the example, on Table, I only have one column called Id of type is "uniqueidentifier", which is my PK.

On start, my change tracking current version is 0.

I got it with :

SELECT CHANGE_TRACKING_CURRENT_VERSION();

I added a new row to Table:

INSERT INTO dbo.[Table] (Id) 
VALUES ('C99F9E2A-1974-47CE-A406-481076F53BBD');

Now, my change tracking current version is now 1.

With this request, I can see my element in the change tracking system :

SELECT * 
FROM CHANGETABLE (CHANGES dbo.[Table], 0) CT;

The result is :

result 1

Now, I delete my row with this :

DELETE FROM dbo.[Table] 
WHERE Id = 'C99F9E2A-1974-47CE-A406-481076F53BBD';

Change tracking current version is now 2.

I insert it again with the same request than previous.

Change tracking current version is now 3.

With this request, I got this result :

SELECT * 
FROM CHANGETABLE (CHANGES dbo.[Table], 1) CT;

enter image description here

Now is my question, why I got "U" in SYS_CHANGE_OPERATION ?

Why not "I" cause 1 < SYS_CHANGE_CREATION_VERSION which is 3 ?

Thanks for your help !

like image 627
rognar Avatar asked Mar 05 '23 11:03

rognar


1 Answers

Adding some motivation, the intent of the change tracking functions is to enable you to see what has changed since the last time you checked, and enable you to harvest and apply those changes to some other table or external system.

If you look at the changes since just after the delete you will see the operation as an I. But if you look at the change since before the delete, you "skip over" the delete. But change tracking doesn't remember what the non-key values were before the delete. So the row is reported as having been updated.

EG

ALTER DATABASE current  
SET CHANGE_TRACKING = ON  
(CHANGE_RETENTION = 2 DAYS, AUTO_CLEANUP = ON)  
go
drop table if exists ct

create table ct(id uniqueidentifier primary key)

ALTER TABLE ct
ENABLE CHANGE_TRACKING  
WITH (TRACK_COLUMNS_UPDATED = ON) 

declare @beforeInsert bigint = (SELECT CHANGE_TRACKING_CURRENT_VERSION());
INSERT INTO dbo.ct (Id) VALUES ('C99F9E2A-1974-47CE-A406-481076F53BBD');
declare @afterInsert bigint = (SELECT CHANGE_TRACKING_CURRENT_VERSION());
DELETE FROM dbo.ct WHERE Id = 'C99F9E2A-1974-47CE-A406-481076F53BBD';
declare @afterDelete bigint = (SELECT CHANGE_TRACKING_CURRENT_VERSION());
INSERT INTO dbo.ct (Id) VALUES ('C99F9E2A-1974-47CE-A406-481076F53BBD');


SELECT 'from before insert to current',id, sys_change_operation FROM CHANGETABLE (CHANGES dbo.ct, @beforeInsert) CT
union all
SELECT 'from after insert to current',id, sys_change_operation FROM CHANGETABLE (CHANGES dbo.ct, @afterInsert) CT
union all
SELECT 'from after delete to current',id, sys_change_operation FROM CHANGETABLE (CHANGES dbo.ct, @afterDelete) CT

outputs

                              id                                   sys_change_operation
----------------------------- ------------------------------------ --------------------
from before insert to current C99F9E2A-1974-47CE-A406-481076F53BBD I
from after insert to current  C99F9E2A-1974-47CE-A406-481076F53BBD U
from after delete to current  C99F9E2A-1974-47CE-A406-481076F53BBD I
like image 150
David Browne - Microsoft Avatar answered May 03 '23 03:05

David Browne - Microsoft