【发布时间】:2012-07-24 14:11:31
【问题描述】:
我有从源表到目标表的数据流。为了简化问题,我会说有两个合并连接的源表和一个目标表。此外,还有主键可以帮助我识别每条记录
程序包每天都在运行,如果从源表中删除一条记录,我怎么知道删除了哪条记录,以便我可以在目标表中删除它?
(仅供参考~~我已经检查目标表中是否存在记录,如果存在则更新其他插入,但不知道如何查找已删除的数据)
【问题讨论】:
我有从源表到目标表的数据流。为了简化问题,我会说有两个合并连接的源表和一个目标表。此外,还有主键可以帮助我识别每条记录
程序包每天都在运行,如果从源表中删除一条记录,我怎么知道删除了哪条记录,以便我可以在目标表中删除它?
(仅供参考~~我已经检查目标表中是否存在记录,如果存在则更新其他插入,但不知道如何查找已删除的数据)
【问题讨论】:
另一种可能的方法:
假设您从源接收所有记录,而不仅仅是导入和更新:
修改包以标记已使用唯一 id 或运行日期时间插入或更新的记录
在运行包后,处理在上次运行包时未插入或更新记录的目标表。通过消除过程,应删除源文件中未提供的任何记录。
再次假设所有记录都已发送,而不仅仅是导入和更新。但是话又说回来,如果您没有收到所有记录,则实际上无法检测到记录是否已被删除。
【讨论】:
将源与目标进行比较的问题在于,您必须在每次加载时将每个源行与目标行进行比较,并且随着行数的增加会占用越来越多的时间。
因此,处理此问题的最佳方法可能是在源端。两个common approaches 是“软删除”,您可以在其中设置一个标志列来将该行标记为已删除;或在日志表中记录已删除行的 PK 的触发器(或将整行移动到存档日志表)。然后,您的 ETL 流程会查看标志或日志/归档表,以确定自上次加载以来删除了哪些行。
另一种可能性是源平台提供了一些可用于跟踪已删除行的内置功能,例如CDC 在 SQL Server 中。但是,如果您完全无法控制源数据库(即使它是一个数据库),那么除了比较完整的数据集之外,可能别无选择。
【讨论】:
一种可能的方法:
优点:
您的目标表将始终镜像传入的数据,无需检查删除
缺点:
您不会有任何历史信息(如果需要)
【讨论】:
我遇到了同样的问题,例如如何将我的旧/存档记录标记为“已删除”,因为它们不再存在于原始数据源中。
基本上,我构建了两个表,其中一个是主表,其中包含来自原始数据源的所有记录,另一个是我每次运行脚本时保存的用于存储原始数据源的临时表。
主表
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
【讨论】: