SSIS 2012 - 条件 headers' 位置

SSIS 2012 - conditional headers' location

我需要使用 SSIS 将几千个 txt 文件暂存到 SQL Server 2012 实例中。

问题是一些 txt 文件的前两行有控制校验和,而另一些则没有。

如果文件有校验和,它的第一行以 "HEADER" 开头——在这种情况下,我必须跳过前两行,然后从第 3 行读取列 headers 并加载数据开始来自第 4 行。

如果文件没有校验和,列名将存在于第 1 行,数据从第 2 行开始。

现在,我的问题是:处理这种情况的侵入性最小的方法是什么?我很懒,所以我正在寻找最小的努力和最大的效果。

我目前的想法:

  1. 使用 C# 脚本组件检测校验和的存在,并构建两个独立的流程,每个流程对应一种文件类型。缺点:两个几乎相同的流程(我不是冗余的忠实拥护者)

  2. 首先使用 PowerShell 在 运行 SSIS 流之前从文件中删除校验和。缺点:需要 re-write 大量文件(性能下降)

  3. 在 Whosebug 上提问。缺点:被 Whosebug 社区视为讽刺。

有什么提示吗?

这是一个方法。

  1. 创建 2 个平面文件连接管理器,并在设计模式下,浏览到每个的示例文件,以便您可以设置列等。
  2. 对于没有校验和行的平面文件连接管理器,将 Header Rows to Skip 保留为 0,对于具有校验和行的平面文件连接管理器,将其设置为 跳过前 2 行 ,如下所示。
  3. 将两个连接管理器的 DelayValidation 属性 设置为 true
  4. 在您的数据流任务中,使用脚本组件检测文件是否有校验和行。
  5. 在脚本组件的输出中,将文件的完整路径作为输出列,并且还有一个指示文件是否具有校验和行的标志。例如:HasCheckSumRows
  6. 将脚本组件的输出连接到条件拆分任务。
  7. 在条件拆分任务中,根据设置为 trueHasCheckSumRows 标志进行拆分,并创建 2 个输出,1 个用于具有校验和行的文件,另一个用于没有校验和行的文件。
  8. 创建 2 个平面文件源,1 个用于校验和行文件,它使用您为这些类型的文件创建的平面文件连接管理器,另一个用于没有校验和行的常规文件。
  9. 将条件拆分的 2 个输出连接到相应的平面文件源,使用输出列中的完整文件路径作为平面文件源的 connectionstring
  10. 最后,使用 Union All 组件将两种类型文件中的行返回到 1 个输入数据流中。所以这不会重复您的工作流程(即不会导致冗余),因为您在 1 个流中拥有所有行。

希望这是有道理的。

我会在评论中写下这个,但你知道我在使用多年后才开始贡献。无论如何,您的选项 1 仅在存在校验和行的情况下拥有冗余数据流可能是最直接的方法,并且看到您的数据集列有限可能是创建和维护最快的方法。对于这种方法,您可以放入一个 Foreach 循环容器,将其设置为枚举文件。添加一个变量来测试校验和是否存在。添加一个 c# 脚本任务来测试校验和并填充变量。然后添加 2 个数据流任务 1 来处理一种格式,第二个处理替代格式。它只会是 4 个组件(文件连接、数据流、源、目标)的重复。然后对于优先约束编辑器(双击绿色箭头)更改为通过表达式中的表达式和约束进行评估,只需根据正在馈送的数据流选择您的变量或 !variable(相反)。这是假设您要在不首先将同一数据流任务中的所有 2000 多个文件与联合等组合的情况下进行暂存。@Shiva 的答案肯定有很多交叉,但我认为不需要有条件地拆分联合如果您要参加演出,则全部 table。

换句话说,如果您真的不希望数据流任务等出现冗余。在 运行 SSIS 包之前不需要执行 powershell 脚本。您可以创建一个 c# 脚本来直接在包中执行此操作。例如,我遇到一个问题,即行尾与我必须导入的数据源不一致。所以我有一个 c# 脚本来规范化在我的数据流任务之前保存文件的行尾。您可以在 ssis 包中将文件动态规范化为一个结构,但正如您指出的那样,它会占用额外的系统资源,但是它会同时将文件加载到 memory/processed.

@xpil,15 种不同的类型不在原始问题中。那时我可能会做两件事中的一件。首先实现您对 #2 的想法,但在 SSIS 脚本中执行。所以我会通过 system.file.io 操作删除不需要的行。然后我会构建所有不同的类型并在脚本中设置一个变量来告诉你它是哪种类型或者通过不同的 dfts 失败。或者我实际上只是编写整个操作的脚本,我可能会或可能不会使用 SSIS,但我只会有一个 system.file.io 来加载文件检测存在和类型,然后简单地使用 SQLBulkCopy 将其放入 table 那么,与其创建 DFT,不如在设置上花费更少的时间。尽管如果文件很大,几百 MB,您可能仍想使用 DFT 路线。这是我编写的 SSIS 脚本任务中的一些片段,它们可能会有所帮助,当然您需要根据自己的目的进行更改。

如果要修复文件和 DFT 路由。

 string contents = File.ReadAllText(_WFRFullPath);
    contents = Regex.Replace(contents, @"\r\n?|\n", crlf);
    File.WriteAllText(_SSISWorkspaceFullPath, contents);

读取文件内容通过正则表达式将文件写回新位置修复。

如果通过脚本路径加载,您只需要将其读入数据table,然后可能按列名或数据类型测试格式。然后加载它。

        SqlConnection sqlConnection = new SqlConnection(sqlConnectionString);
        sqlConnection.Open();

        SqlBulkCopy bulkCopy = new SqlBulkCopy(sqlConnection);
        bulkCopy.DestinationTableName = _stagingTableName;
        foreach (DataColumn col in _jobRecDT.Columns)
        {
            //System.Windows.Forms.MessageBox.Show(col.ColumnName);
            bulkCopy.ColumnMappings.Add(col.ColumnName, col.ColumnName);
        }


        bulkCopy.WriteToServer(_jobRecDT);

        sqlConnection.Close();

请注意,我手头没有它的代码,但如果你有大文件,你实际上可以实现一个流 reader 并将文件分块并批量复制。