SQL 2008 变化跟踪和检测更新数据
SQL 2008 Change tracking and detecting Updated data
我计划在 SSIS 项目中实现它。由于我没有企业版的SQLserver 2008,只好借助其他方法
另一种方法是使用触发器,但我尽量避免使用很多触发器。
使用更改跟踪,我很难检测到正确的操作。该操作被标记为 "I",而它应该是 "U"。我做错了什么?
这是一个小示例代码。 pKey = 2 应该是 "U"
use master;
go
create database CT_Example;
go
use CT_Example;
go
alter database CT_Example
set change_tracking = on
(change_retention = 2 days, auto_cleanup = on);
go
create table Employee
(
pKey int not null,
Name nvarchar(50) NULL,
CT bigint null,
constraint pk_pKey
primary key (pKey)
);
go
alter table Employee
enable change_tracking
with (track_columns_updated = off);
go
create table Staging
(
pKey int not null,
Name nvarchar(50) NULL,
CT bigint null,
);
go
insert into Employee (pKey,Name)
values
(1,'Jhon'),
(2,'Phill'),
(3,'Jones'),
(4,'Tom');
go
update e set
Name = 'Harry'
from
Employee as e
where
pKey = 2;
go
update a set
a.CT = CHANGE_TRACKING_CURRENT_VERSION()
from
Employee as a;
update e set
Name = 'Gabriel'
from
Employee as e
where
pKey = 2;
insert into Employee (pKey,Name)
values
(5,'Sing'),
(6,'Emily'),
(7,'Jane'),
(8,'Sami');
go
Delete
from
Employee
where
pKey = 3;
declare @last_synchronization_version integer;
SET @last_synchronization_version = (select ct from Staging);
select
*
from
Employee as a
right outer join changetable (changes Employee, @last_synchronization_version) as c
on a.pKey = c.pKey;
go
use master;
go
drop database CT_Example;
go
你的问题出在这里:
declare @last_synchronization_version integer;
SET @last_synchronization_version = (select ct from Staging);
并且暂存 table 是空的,也是 @last_synchronization_version = NULL
。它也应该声明为 bigint
.
尝试运行这个:
select
*
from
Employee as a
right outer join changetable (changes Employee, 3) as c
on a.pKey = c.pKey;
go
您将看到 pKey=2 的行作为 U。
或者您可以这样请求 "What was the last change operation for row pKey=2?":
SELECT @last_synchronization_version = sys_change_version - 1
FROM changetable (VERSION Employee,([pKey]), (2)) y
SELECT sys_change_operation
FROM changetable (changes Employee, @last_synchronization_version) x
WHERE x.pKey=2
可以看到不需要每一行都存储最后一个版本变化,它是由SQL服务器提供的。
As per documentation changetable (changes Employee, null)
应执行以下操作:
If the value is NULL, all tracked changes are returned.
但也许不是最新版本的更改,而是每行所有可用更改的第一个版本。
您可以试试这个脚本,看看更改跟踪是如何工作的:
use master;
go
create database CT_Example;
go
use CT_Example;
go
alter database CT_Example
set change_tracking = on
(change_retention = 2 days, auto_cleanup = on);
go
create table Employee
(
pKey int not null,
Name nvarchar(50) NULL,
CT bigint null,
constraint pk_pKey
primary key (pKey)
);
go
alter table Employee
enable change_tracking
with (track_columns_updated = off);
go
declare @last_synchronization_version bigint;
insert into Employee (pKey,Name)
values
(1,'Jhon'),
(2,'Phill'),
(3,'Jones'),
(4,'Tom');
SELECT CHANGE_TRACKING_CURRENT_VERSION()
SET @last_synchronization_version = CHANGE_TRACKING_CURRENT_VERSION()-1
SELECT * FROM changetable (changes Employee, @last_synchronization_version) x
update e set
Name = 'Harry'
from
Employee as e
where
pKey = 2;
SELECT CHANGE_TRACKING_CURRENT_VERSION()
SET @last_synchronization_version = CHANGE_TRACKING_CURRENT_VERSION()-1
SELECT * FROM changetable (changes Employee, @last_synchronization_version) x
update e set
Name = 'Gabriel'
from
Employee as e
where
pKey = 2;
SELECT CHANGE_TRACKING_CURRENT_VERSION()
SET @last_synchronization_version = CHANGE_TRACKING_CURRENT_VERSION()-1
SELECT * FROM changetable (changes Employee, @last_synchronization_version) x
insert into Employee (pKey,Name)
values
(5,'Sing'),
(6,'Emily'),
(7,'Jane'),
(8,'Sami');
SELECT CHANGE_TRACKING_CURRENT_VERSION()
SET @last_synchronization_version = CHANGE_TRACKING_CURRENT_VERSION()-1
SELECT * FROM changetable (changes Employee, @last_synchronization_version) x
Delete
from
Employee
where
pKey = 3;
SELECT CHANGE_TRACKING_CURRENT_VERSION()
SET @last_synchronization_version = CHANGE_TRACKING_CURRENT_VERSION()-1
SELECT * FROM changetable (changes Employee, @last_synchronization_version) x
SET @last_synchronization_version = @last_synchronization_version-1
SELECT @last_synchronization_version
SELECT * FROM changetable (changes Employee, @last_synchronization_version) x
SET @last_synchronization_version = @last_synchronization_version-1
SELECT @last_synchronization_version
SELECT * FROM changetable (changes Employee, @last_synchronization_version) x
SET @last_synchronization_version = @last_synchronization_version-1
SELECT @last_synchronization_version
SELECT * FROM changetable (changes Employee, @last_synchronization_version) x
SET @last_synchronization_version = @last_synchronization_version-1
SELECT @last_synchronization_version
SELECT * FROM changetable (changes Employee, @last_synchronization_version) x
use master;
go
drop database CT_Example;
go
我计划在 SSIS 项目中实现它。由于我没有企业版的SQLserver 2008,只好借助其他方法
另一种方法是使用触发器,但我尽量避免使用很多触发器。
使用更改跟踪,我很难检测到正确的操作。该操作被标记为 "I",而它应该是 "U"。我做错了什么?
这是一个小示例代码。 pKey = 2 应该是 "U"
use master;
go
create database CT_Example;
go
use CT_Example;
go
alter database CT_Example
set change_tracking = on
(change_retention = 2 days, auto_cleanup = on);
go
create table Employee
(
pKey int not null,
Name nvarchar(50) NULL,
CT bigint null,
constraint pk_pKey
primary key (pKey)
);
go
alter table Employee
enable change_tracking
with (track_columns_updated = off);
go
create table Staging
(
pKey int not null,
Name nvarchar(50) NULL,
CT bigint null,
);
go
insert into Employee (pKey,Name)
values
(1,'Jhon'),
(2,'Phill'),
(3,'Jones'),
(4,'Tom');
go
update e set
Name = 'Harry'
from
Employee as e
where
pKey = 2;
go
update a set
a.CT = CHANGE_TRACKING_CURRENT_VERSION()
from
Employee as a;
update e set
Name = 'Gabriel'
from
Employee as e
where
pKey = 2;
insert into Employee (pKey,Name)
values
(5,'Sing'),
(6,'Emily'),
(7,'Jane'),
(8,'Sami');
go
Delete
from
Employee
where
pKey = 3;
declare @last_synchronization_version integer;
SET @last_synchronization_version = (select ct from Staging);
select
*
from
Employee as a
right outer join changetable (changes Employee, @last_synchronization_version) as c
on a.pKey = c.pKey;
go
use master;
go
drop database CT_Example;
go
你的问题出在这里:
declare @last_synchronization_version integer;
SET @last_synchronization_version = (select ct from Staging);
并且暂存 table 是空的,也是 @last_synchronization_version = NULL
。它也应该声明为 bigint
.
尝试运行这个:
select
*
from
Employee as a
right outer join changetable (changes Employee, 3) as c
on a.pKey = c.pKey;
go
您将看到 pKey=2 的行作为 U。
或者您可以这样请求 "What was the last change operation for row pKey=2?":
SELECT @last_synchronization_version = sys_change_version - 1
FROM changetable (VERSION Employee,([pKey]), (2)) y
SELECT sys_change_operation
FROM changetable (changes Employee, @last_synchronization_version) x
WHERE x.pKey=2
可以看到不需要每一行都存储最后一个版本变化,它是由SQL服务器提供的。
As per documentation changetable (changes Employee, null)
应执行以下操作:
If the value is NULL, all tracked changes are returned.
但也许不是最新版本的更改,而是每行所有可用更改的第一个版本。
您可以试试这个脚本,看看更改跟踪是如何工作的:
use master;
go
create database CT_Example;
go
use CT_Example;
go
alter database CT_Example
set change_tracking = on
(change_retention = 2 days, auto_cleanup = on);
go
create table Employee
(
pKey int not null,
Name nvarchar(50) NULL,
CT bigint null,
constraint pk_pKey
primary key (pKey)
);
go
alter table Employee
enable change_tracking
with (track_columns_updated = off);
go
declare @last_synchronization_version bigint;
insert into Employee (pKey,Name)
values
(1,'Jhon'),
(2,'Phill'),
(3,'Jones'),
(4,'Tom');
SELECT CHANGE_TRACKING_CURRENT_VERSION()
SET @last_synchronization_version = CHANGE_TRACKING_CURRENT_VERSION()-1
SELECT * FROM changetable (changes Employee, @last_synchronization_version) x
update e set
Name = 'Harry'
from
Employee as e
where
pKey = 2;
SELECT CHANGE_TRACKING_CURRENT_VERSION()
SET @last_synchronization_version = CHANGE_TRACKING_CURRENT_VERSION()-1
SELECT * FROM changetable (changes Employee, @last_synchronization_version) x
update e set
Name = 'Gabriel'
from
Employee as e
where
pKey = 2;
SELECT CHANGE_TRACKING_CURRENT_VERSION()
SET @last_synchronization_version = CHANGE_TRACKING_CURRENT_VERSION()-1
SELECT * FROM changetable (changes Employee, @last_synchronization_version) x
insert into Employee (pKey,Name)
values
(5,'Sing'),
(6,'Emily'),
(7,'Jane'),
(8,'Sami');
SELECT CHANGE_TRACKING_CURRENT_VERSION()
SET @last_synchronization_version = CHANGE_TRACKING_CURRENT_VERSION()-1
SELECT * FROM changetable (changes Employee, @last_synchronization_version) x
Delete
from
Employee
where
pKey = 3;
SELECT CHANGE_TRACKING_CURRENT_VERSION()
SET @last_synchronization_version = CHANGE_TRACKING_CURRENT_VERSION()-1
SELECT * FROM changetable (changes Employee, @last_synchronization_version) x
SET @last_synchronization_version = @last_synchronization_version-1
SELECT @last_synchronization_version
SELECT * FROM changetable (changes Employee, @last_synchronization_version) x
SET @last_synchronization_version = @last_synchronization_version-1
SELECT @last_synchronization_version
SELECT * FROM changetable (changes Employee, @last_synchronization_version) x
SET @last_synchronization_version = @last_synchronization_version-1
SELECT @last_synchronization_version
SELECT * FROM changetable (changes Employee, @last_synchronization_version) x
SET @last_synchronization_version = @last_synchronization_version-1
SELECT @last_synchronization_version
SELECT * FROM changetable (changes Employee, @last_synchronization_version) x
use master;
go
drop database CT_Example;
go