通过更改跟踪、使用过程和触发器进行增量复制,但输出滞后 1 个执行时间

问题描述 投票:0回答:1

我正在尝试使用更改跟踪演示从数据库 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

问题是什么?怎么解决?

sql-server stored-procedures triggers change-tracking
1个回答
0
投票

您根本无法使用更改跟踪来执行您想要的操作。更改跟踪是异步的,因此它总是稍微落后于已提交的事务运行(并且根本不接收未提交的事务)。

相反,只需使用普通的

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;
    
© www.soinside.com 2019 - 2024. All rights reserved.