我正在以下列方式将数据加载到表中:
DECLARE @srcRc INT;
DECLARE @dstRc INT;
SET @srcRc = ( SELECT COUNT(*) FROM A )
INSERT INTO t
(Col1
,Col2
,Col3
)
SELECT A.Col1
,A.Col2
,B.Col3
FROM A
JOIN B
ON A.Id = B.Id;
SET @dstRc = @@ROWCOUNT
现在我正在比较变量
@srcRc
和 @dstRc
. ROWCOUNT
必须相同。如果不是,则需要删除插入的行。Q1:回滚插入的行的最佳策略是什么?
我有几个想法:
1) 如果行数不匹配,则在事务中运行负载并回滚。
2)将标志列(位)添加到名为
toBeDeleted
的目标表中,运行加载,如果行数不匹配,更新 toBeDeleted
列与 1
值以将其标记为删除的候选对象。然后以批处理模式(while 循环)删除。或者不要删除它们,但在使用 t
时总是从查询中排除删除候选者 table 。3) 在插入行之前,先比较行数。如果不匹配,则不要启动负载。
DECLARE @srcRc INT;
DECLARE @dstRc INT;
SET @srcRc = ( SELECT COUNT(1) FROM A );
SET @dstRc = ( SELECT COUNT(1) FROM A JOIN B ON A.Id = B.Id );
Q2:对于更多的行,比如 10-100 百万,什么是更好的解决方案?
Q3:或者对于类似的情况有没有更好的策略?
最佳答案
好的,假设:
当表 A 和 B 的内容可能已更改时,您需要在稍后的某个日期回滚
T 中可能还有其他行您不想作为回滚的一部分删除。
然后您必须保留您插入的行的列表,因为您无法从 A 和 B 可靠地重新生成该列表,并且您不能从 T 中删除所有内容
你可以通过两种方式做到这一点
显然,第一种策略使用了更多的磁盘空间。因此,您保留数据的时间越长,数据越多,额外的列看起来就越好。
另一种选择是分别生成导入数据的列表,并使您的事务 sql 成为批量插入,并将所有数据硬编码到 sql 中。
这适用于小列表、初始设置数据等。
编辑:
从您的评论看来,您本身并不希望回滚。但最好的方法是在导入过程中应用业务逻辑。
在这种情况下,您的第三个答案是最好的。当您知道源数据不正确时,不要进行导入。
关于sql-server - 删除 vs 回滚策略 - ETL 负载,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41016610/