SSIS 2012 - 条件标头的位置

时间:2016-06-09 08:49:56

标签: sql-server ssis ssis-2012

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

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

如果文件有校验和,则其第一行以“HEADER”开头 - 在这种情况下,我必须跳过前两行,然后从第3行读取列标题并从第4行开始加载数据。

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

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

到目前为止我的想法:

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

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

  3. 在StackOverflow上询问。缺点:StackOverflow社区可以看作具有讽刺意味。

  4. 任何提示?

2 个答案:

答案 0 :(得分:2)

这是一种方法。

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

答案 1 :(得分:0)

我会在评论中写下这个,但是你知道我在使用多年后很难做出贡献。无论如何,只有拥有Checksum行条件的冗余数据流的选项1可能是最直接的方法,并且看到您的数据集列有限可能是创建和维护最快的。对于这种方法,您可以放入Foreach循环容器,将其设置为枚举文件。添加一个变量来测试校验和是否存在。添加c#脚本任务以测试校验和并填充变量。然后添加2个数据流任务1来处理一种格式,第二种添加另一种格式。它只是4个组件的重复(FileConnection,Dataflow,source,destination)。然后对于优先约束编辑器(双击绿色箭头)更改为通过表达式中的表达式和约束进行评估,只需选择您的变量或!变量(相反),具体取决于正在馈送的数据流。这假设你没有首先将同一数据流任务中的所有2000多个文件与工会等组合在一起。在@Shiva答案中肯定会有很多交叉,但我不认为需要进行条件拆分如果你要去一个临时表,那就结合了。

enter image description here

如果您真的不想要数据流任务的冗余等,请注意另一个注意事项。在运行SSIS包之前,无需执行powershell脚本。您可以创建一个c#脚本以在包中正确执行。例如,我遇到的问题是,我必须导入的数据源的行结尾不一致。所以我有一个c#脚本来规范化在我的数据流任务之前保存文件的行结尾。您可以在ssis包中将文件规范化为一个结构,但是当您指出文件已经被加载到内存/处理时,它将需要额外的系统资源。

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

如果要去修复文件和DFT路线。

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

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

如果通过脚本路由加载,那么您只需要将其读取为数据表,然后可能通过列名称或数据类型将其读取为测试格式。然后加载它。

        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();

注意我手头没有代码,但是如果你有大文件,你可以实际实现一个流阅读器并将文件大块化并批量复制。