我有从源表到目标表的数据流。为了简化问题,我会说有两个合并连接的源表和一个目标表。此外,还有一些主键可以帮助我识别每条记录
该程序包每天都在运行,如果从源表中删除一条记录,我怎么知道删除了哪一条,以便我可以在目标表中删除它?
(仅供参考~~我已经检查目标表中是否存在记录,如果存在则更新其他插入,但不知道如何查找已删除的数据)
将源与目标进行比较的问题在于,您必须在每次加载时将每个源行与目标行进行比较,并且随着行数的增加,这会占用越来越多的时间。
因此,处理此问题的最佳方法可能是在源端。两种常见的方法是“软删除”,您可以在其中设置标志列以将行标记为已删除;或在日志表中记录已删除行的 PK 的触发器(或将整行移动到存档日志表)。然后,您的 ETL 过程查看标志或日志/归档表以确定自上次加载以来删除了哪些行。
另一种可能性是源平台提供了一些可用于跟踪已删除行的内置功能,例如SQL Server 中的CDC。但是,如果您完全无法控制源数据库(如果它甚至是数据库),那么除了比较完整的数据集之外可能别无选择。
一种可能的方法:
优点:
您的目标表将始终镜像传入的数据,无需检查删除
缺点:
您将没有任何历史信息(如果需要)
另一种可能的方法:
假设您从源接收所有记录,而不仅仅是导入和更新:
修改包以标记已使用唯一 id 或运行日期时间插入或更新的记录
在包运行之后,处理在上次包运行中未插入或更新记录的目标表。通过消除过程,应删除源文件中未提供的任何记录。
同样,假设发送了所有记录,而不仅仅是导入和更新。但是话又说回来,如果您没有收到所有记录,则实际上无法检测到记录是否已被删除。
我遇到了同样的问题,例如如何将我的旧/存档记录标记为“已删除”,因为它们不再存在于原始数据源中。
基本上,我构建了两个表,其中一个是包含来自原始数据源的所有记录的主表,另一个是我每次运行脚本时保存的用于存储原始数据源的临时表。
主表
ID, NAME, SURNAME, DATE_MODIFIED, ORDERS_COUNT, etc
plus a STATUS column (1 for Active, 0 for Deleted)
TEMP TABLE与原始相同,但没有 STATUS 列
ID, NAME, SURNAME, DATE_MODIFIED, ORDERS_COUNT, etc
关键是如果 MAIN 表的 ID 不再在 Temp 表中,则使用STATUS = 0更新 MAIN TABLE 。即:源记录已被删除。
我是这样做的:
UPDATE m
SET m.Status = 0
FROM tblMAIN AS m
LEFT JOIN tblTEMP AS t
ON t.ID = m.ID
WHERE t.ID IS NULL