我有一个SSIS例程从一个非常动态的表中读取,并在截断原始源表之前,将它找到的任何行插入不同数据库的表中。SSIS Foreach通过表插入到另一个表中并删除源行
由于源表的动态特性,这种截断不会令人惊讶地导致行不会将其发送到第二个数据库。
删除那些已迁移的行的最佳方法是什么?
源表上有一个标识列,但它不会被迁移。
我无法更改任何表架构。
我有一个SSIS例程从一个非常动态的表中读取,并在截断原始源表之前,将它找到的任何行插入不同数据库的表中。SSIS Foreach通过表插入到另一个表中并删除源行
由于源表的动态特性,这种截断不会令人惊讶地导致行不会将其发送到第二个数据库。
删除那些已迁移的行的最佳方法是什么?
源表上有一个标识列,但它不会被迁移。
我无法更改任何表架构。
一种选择是创建一个表来记录处理过的记录的标识,然后用一个单独的包(或数据流)来删除这些记录。如果您已经在某处记录了处理过的记录,那么您可以在其中添加标识 - 否则,请创建一个新表来存储数据。
第二种选择:如果您尝试避免创建附加表格,则将记录选择和记录处理分为两个阶段。大体上,您可以选择控制流中的所有记录,然后在数据流中逐个处理它们。 具体做法是:
这里有很多这样的例子;例如this one来自古老的杰米汤姆森,或this one其中包括更多的细节。
请注意,您没有谈论数据的规模;如果您有非常多的记录,那么第一个建议可能是更好的选择。请注意,在这两种情况下,您都失去了表截断的优势(因为您正在使用标准delete
调用)。
将其推入对象变量的替代方法是使用RAW文件格式。与分段数据相关的磁盘成本相关,但消耗将比分解数据更加直截了当。 JamieT还写了关于这种方法的文章 – billinkc 2013-03-19 16:41:32
一个可能听起来很愚蠢,但起作用的选项是首先删除并使用OUTPUT子句。
我创建的填充表对我来说是简单的控制流。
IF EXISTS
(
SELECT 1 FROM sys.tables AS T WHERE T.name = 'DeleteFirst'
)
BEGIN
DROP TABLE dbo.DeleteFirst;
END
CREATE TABLE dbo.DeleteFirst
(
[name] sysname
);
INSERT INTO
dbo.DeleteFirst
SELECT
V.name
FROM
master.dbo.spt_values V
WHERE
V.name IS NOT NULL;
在我的OLE DB源,而不是使用SELECT,删除你要进入流水线和输出删除的虚拟表中的数据。Somethinng像
DELETE
DF
OUTPUT
DELETED.*
FROM
dbo.DeleteFirst AS DF;
它的工作原理,它的工作原理!
嗨@billinkc 非常感谢您提供了非常全面的建议,但恐怕只有其中一些我能够理解。 我最终通过重写表格截断的时间来解决这个问题。 再次感谢您的时间和专业知识。 – Patrick 2013-07-29 09:10:29
为了阐明与自身矛盾的Microsoft文档,OUTPUT子句可用,并可从SQL 2005开始工作。我刚刚测试了2005年来验证这一点。 – Mike 2015-02-12 22:55:09
@mike是的,MS开始了一个奇怪的事情,BOL重写。基本上,该产品不支持的版本的功能是写出文档。如果您点击其他版本的下拉菜单,则会看到2005年列出,并在那里指定它可用。尽管2014版本声明“适用于:SQL Server(通过当前版本的SQL Server 2008),Azure SQL数据库”。 – billinkc 2015-02-12 23:13:00
来源是SQL Server,如果是的话,是什么版本(2005/2008/2012)。这两个人是否在同一个实例?我*会发现数据丢失令人惊讶。我不会丢失数据,也不会接受导致这种情况的解决方案。你可以发布你的软件包的外观截图,以便我们了解它的结构,也许我们可以提供有关如何防止这种损失的策略。 – billinkc 2013-03-19 15:58:43
源和目标都是SQL-Server 2008 R2。 对不起,我无法找到附加屏幕截图的方法。 – Patrick 2013-03-19 16:26:03
的处理如下: OLE DB源:数据访问模式为“表或视图” - > 行数 - > 批插入到目的地 - > 单刀片的故障切换到目的地 - > 行计数错误 - > 记录任何错误 TRUNCATE源表。 我希望有帮助。 – Patrick 2013-03-19 16:30:57