2

我有一个 SSIS 例程,它从一个非常动态的表中读取数据,并将它找到的任何行插入到不同数据库中的表中,然后截断原始源表。

由于源表的动态特性,这种截断会导致行无法进入第二个数据库,这并不奇怪。

仅删除已迁移的那些行的最佳方法是什么?

源表上有一个标识列,但未迁移。

我无法更改任何一个表架构。

4

2 回答 2

4

一个可能听起来很愚蠢但有效的选项是先删除并使用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,而是删除要沿管道传输的数据并输出 DELETED 虚拟表。类似的东西

DELETE
    DF
OUTPUT
    DELETED.*
FROM
    dbo.DeleteFirst AS DF;

结果

它有效,有效!

于 2013-03-19T18:57:35.310 回答
1

一种选择是创建一个表来记录已处理记录的身份,然后创建一个单独的包(或数据流)来删除这些记录。如果您已经在某处记录已处理的记录,那么您可以在那里添加身份 - 否则,创建一个新表来存储数据。

第二种选择:如果您试图避免创建额外的表,则将记录选择和记录处理分为两个阶段。从广义上讲,您将选择控制流中的所有记录,然后在数据流中逐个处理它们。具体来说:

  1. 创建一个 Object 类型的变量来存储您的记录列表,并创建另一个与您的身份类型匹配的变量(大概是 int)来存储“当前记录身份”。
  2. 在控制流中,添加一个执行 SQL 任务,该任务使用查询来构建要处理的标识值列表,然后将它们存储到记录列表变量中。
  3. 添加一个 Foreach 循环容器来处理该列表;foreach 任务会将当前记录标识符加载到您在上面定义的第二个变量中。
  4. 在 foreach 任务中,添加一个数据流来复制该单条记录,然后将其从源中删除。

网上有很多这样的例子;例如,这个来自可敬的杰米汤姆森,或者这个包含更多细节。

请注意,您没有谈论数据的规模;如果您有大量记录,第一个建议可能是更好的选择。请注意,在这两种情况下,您都会失去表截断的优势(因为您使用的是标准delete调用)。

于 2013-03-19T16:11:58.747 回答