试图了解一些 SQL 服务器更改跟踪功能
Trying to understand some SQL Server change tracking features
我正在开发具有更改跟踪功能的 SQL Server 2016 SP1,我有一个问题要问你。
我有一个启用了更改跟踪的数据库。该数据库包含一个 table Table
,它激活了 "change tracking",但没有 "track columns updated" 选项。
例如,在Table
上,我只有一个名为Id
的列,类型是"uniqueidentifier",这是我的PK。
开始时,我的更改跟踪当前版本为 0。
我得到它:
SELECT CHANGE_TRACKING_CURRENT_VERSION();
我在 Table
中添加了一个新行:
INSERT INTO dbo.[Table] (Id)
VALUES ('C99F9E2A-1974-47CE-A406-481076F53BBD');
现在,我的更改跟踪当前版本是 1。
通过这个请求,我可以在更改跟踪系统中看到我的元素:
SELECT *
FROM CHANGETABLE (CHANGES dbo.[Table], 0) CT;
结果是:
现在,我用这个删除我的行:
DELETE FROM dbo.[Table]
WHERE Id = 'C99F9E2A-1974-47CE-A406-481076F53BBD';
更改跟踪当前版本现在是 2。
我按照与之前相同的要求再次插入。
更改跟踪当前版本现在是 3。
根据这个请求,我得到了这个结果:
SELECT *
FROM CHANGETABLE (CHANGES dbo.[Table], 1) CT;
现在是我的问题,为什么我在 SYS_CHANGE_OPERATION 中得到 "U"?
为什么不 "I" 因为 1 < SYS_CHANGE_CREATION_VERSION 是 3 ?
感谢您的帮助!
If you delete a row and then insert a row that has the old primary key, the change is seen as an update to all columns in the row.
据推测,id
是所讨论的 table 的主键。
此外,不要使用 id
作为列的名称,使用 TableID
... 所以如果 table 名称是 Users
,那么主键(如果使用代理键)应该是 UserID
。使用 id
作为主键列的名称会造成相当大的混乱,并使您的代码容易出错。查看 this 答案以了解详细信息。
添加一些动力,更改跟踪功能的目的是让您看到自上次检查以来发生的更改,和 使您能够收获和应用那些更改为其他 table 或外部系统。
如果您在删除 之后查看自 以来的变化,您会看到该操作是 I
。但是,如果您查看删除之前的变化,您 "skip over" 删除了。但是更改跟踪不记得删除之前的非键值是什么。因此,该行被报告为已更新。
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
产出
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
我正在开发具有更改跟踪功能的 SQL Server 2016 SP1,我有一个问题要问你。
我有一个启用了更改跟踪的数据库。该数据库包含一个 table Table
,它激活了 "change tracking",但没有 "track columns updated" 选项。
例如,在Table
上,我只有一个名为Id
的列,类型是"uniqueidentifier",这是我的PK。
开始时,我的更改跟踪当前版本为 0。
我得到它:
SELECT CHANGE_TRACKING_CURRENT_VERSION();
我在 Table
中添加了一个新行:
INSERT INTO dbo.[Table] (Id)
VALUES ('C99F9E2A-1974-47CE-A406-481076F53BBD');
现在,我的更改跟踪当前版本是 1。
通过这个请求,我可以在更改跟踪系统中看到我的元素:
SELECT *
FROM CHANGETABLE (CHANGES dbo.[Table], 0) CT;
结果是:
现在,我用这个删除我的行:
DELETE FROM dbo.[Table]
WHERE Id = 'C99F9E2A-1974-47CE-A406-481076F53BBD';
更改跟踪当前版本现在是 2。
我按照与之前相同的要求再次插入。
更改跟踪当前版本现在是 3。
根据这个请求,我得到了这个结果:
SELECT *
FROM CHANGETABLE (CHANGES dbo.[Table], 1) CT;
现在是我的问题,为什么我在 SYS_CHANGE_OPERATION 中得到 "U"?
为什么不 "I" 因为 1 < SYS_CHANGE_CREATION_VERSION 是 3 ?
感谢您的帮助!
If you delete a row and then insert a row that has the old primary key, the change is seen as an update to all columns in the row.
据推测,id
是所讨论的 table 的主键。
此外,不要使用 id
作为列的名称,使用 TableID
... 所以如果 table 名称是 Users
,那么主键(如果使用代理键)应该是 UserID
。使用 id
作为主键列的名称会造成相当大的混乱,并使您的代码容易出错。查看 this 答案以了解详细信息。
添加一些动力,更改跟踪功能的目的是让您看到自上次检查以来发生的更改,和 使您能够收获和应用那些更改为其他 table 或外部系统。
如果您在删除 之后查看自 以来的变化,您会看到该操作是 I
。但是,如果您查看删除之前的变化,您 "skip over" 删除了。但是更改跟踪不记得删除之前的非键值是什么。因此,该行被报告为已更新。
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
产出
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