我正在尝试使用更改跟踪演示从数据库 A(源)中的表到另一个数据库 B(目标)中的另一个表的增量复制。
我在两个不同的数据库中创建两个同名的表(表名称:
check_exist_Jan_2024
)和一个名为 table_store_ChangeTracking_version
的表来存储更改跟踪信息。
这个想法是
table_store_ChangeTracking_version
存储最后的更改跟踪版本。当数据库 A 中的表被修改(通过插入、删除或更新)时,CHANGE_TRACKING_CURRENT_VERSION()
将增加。我将 CHANGE_TRACKING_CURRENT_VERSION()
与 table_store_ChangeTracking_version
中存储的“最后更改跟踪版本”进行比较,以查找源表中的行 ID 已被修改,然后将这些行复制到目标表。
毕竟我更新了
table_store_ChangeTracking_version = CHANGE_TRACKING_CURRENT_VERSION()
。我使用程序和触发器来自动化此过程。
问题是当我第一次尝试将值插入源表时,目标表中没有任何反应。然后我将另一个值插入到源表中,第一行出现在目标表中。依此类推,当我第三次向源表插入值时,第二行出现在目标表中。
table_store_ChangeTracking_version
中更新更改版本过程也发生了同样的事情。
这是我的 SQL 代码:
-- CREATE PROCEDURE for updating data in table_store_ChangeTracking_version
CREATE PROCEDURE Update_ChangeTracking_Version (@TableName varchar(50))
AS
BEGIN
DECLARE @Current_ChangeTracking_version BIGINT;
SET @Current_ChangeTracking_version = (SELECT CHANGE_TRACKING_CURRENT_VERSION() as CurrentChangeTrackingVersion)
UPDATE table_store_ChangeTracking_version
SET [SYS_CHANGE_VERSION] = @Current_ChangeTracking_version
WHERE [TableName] = @TableName
END
-- CREATE PROCEDURE for Incremental copy data from source to another table
ALTER PROCEDURE Incremental_Copy_check_exist_Jan_2024
AS
BEGIN
DECLARE @Last_ChangeTracking_version BIGINT, @Current_ChangeTracking_version BIGINT;
SET @Current_ChangeTracking_version = (SELECT CHANGE_TRACKING_CURRENT_VERSION() as CurrentChangeTrackingVersion);
SET @Last_ChangeTracking_version = (select max(SYS_CHANGE_VERSION) as last_version
from table_store_ChangeTracking_version
where TableName = 'dbo.check_exist_Jan_2024');
-- Inserted data or updated data
SET IDENTITY_INSERT B.dbo.check_exist_Jan_2024 ON
Insert into B.dbo.check_exist_Jan_2024 (LocationID, Name, CostRate, Availability)
SELECT source_tbl.LocationID, source_tbl.Name, source_tbl.CostRate, source_tbl.Availability
FROM A.dbo.check_exist_Jan_2024 AS source_tbl
RIGHT OUTER JOIN changetable(changes A.dbo.check_exist_Jan_2024, @Last_ChangeTracking_version) AS ct
ON ct.LocationID = source_tbl.LocationID
WHERE ct.SYS_CHANGE_VERSION <= @Current_ChangeTracking_version
AND ct.SYS_CHANGE_OPERATION IN ('I', 'U')
SET IDENTITY_INSERT B.dbo.check_exist_Jan_2024 OFF;
-- Deleted data
DELETE FROM B.dbo.check_exist_Jan_2024
WHERE LocationID IN (SELECT LocationID
FROM changetable(changes A.dbo.check_exist_Jan_2024, @Last_ChangeTracking_version) AS ct
WHERE ct.SYS_CHANGE_OPERATION = 'D');
END;
-- Create trigger when source table has been changed
ALTER TRIGGER Incremental_ChangeTracking_Trigger
ON A.dbo.check_exist_Jan_2024
AFTER INSERT, UPDATE, DELETE
AS
BEGIN
EXECUTE Incremental_Copy_check_exist_Jan_2024;
EXECUTE Update_ChangeTracking_Version
@TableName = 'dbo.check_exist_Jan_2024';
END
问题是什么?怎么解决?
您根本无法使用更改跟踪来执行您想要的操作。更改跟踪是异步的,因此它总是稍微落后于已提交的事务运行(并且根本不接收未提交的事务)。
相反,只需使用普通的INSERT
UPDATE
和
DELETE
即可执行此操作。最简单的是只编写三个单独的触发器。
CREATE OR ALTER TRIGGER check_exist_Jan_2024_INS
ON dbo.check_exist_Jan_2024
AFTER INSERT
AS
SET NOCOUNT ON;
SET IDENTITY_INSERT B.dbo.check_exist_Jan_2024 ON;
INSERT B.dbo.check_exist_Jan_2024 t
(LocationID, Name, CostRate, Availability)
SELECT
i.LocationID,
i.Name,
i.CostRate,
i.Availability
FROM inserted i;
CREATE OR ALTER TRIGGER check_exist_Jan_2024_UPD
ON dbo.check_exist_Jan_2024
AFTER UPDATE
AS
SET NOCOUNT ON;
UPDATE t
SET
Name = i.Name,
CostRate = i.CostRate,
Availability = i.Availability
FROM B.dbo.check_exist_Jan_2024 t
JOIN inserted i ON i.LocationID = t.LocationID
WHERE ( -- use NOT EXISTS (SELECT ... INTERSECT SELECT ...) syntax on older versions
i.Name IS DISTINCT FROM t.Name
OR i.CostRate IS DISTINCT FROM t.CostRate
OR i.Availability IS DISTINCT FROM t.Availability
);
CREATE OR ALTER TRIGGER check_exist_Jan_2024_DEL
ON dbo.check_exist_Jan_2024
AFTER DELETE
AS
SET NOCOUNT ON;
DELETE t
FROM B.dbo.check_exist_Jan_2024 t
JOIN deleted d ON d.LocationID = t.LocationID;