在SSIS数据流中组合多个记录类型

时间:2014-05-29 20:31:40

标签: ssis sql-server-2012

我可以使用Integration Services来提取和转换数据,例如,包含在导入平面文件中的单一类型的固定格式记录中。我也可以在一个文件中处理多种类型的固定格式记录,只要我能够将它们发送到不同的目的地。

但是,如果我需要将输入文件中的两个(或更多)记录与每个到达单个目标的记录相关联,该怎么办?我知道这些记录属于一起的唯一方法是它们在输入文件中彼此相邻。数据流将处理一个接一个的记录。我不能使用SSIS包变量来计算记录,因为包变量只在数据流完成后才更新。

以下是输入文件示例:

HDR00120140501      
DTL001JOAN     0.00 
DTL002     30.00 ABC
DTL001DAVE    11.00 
DTL002     21.85 DEF
DTL001BERT    50.00 
DTL002      0.00 GHI
TRL001              

我需要将DTL001和DTL002细节线的数据组合成单个输出记录。另外,我需要包含HDR001标题行中的信息(在本例中为日期值)。所以目标表看起来像:

CREATE TABLE TestImport (
  ID int IDENTITY(1,1) NOT NULL,
  ImportDate datetime NULL,
  Name char(4) NULL,
  Amount1 decimal(18, 2) NULL,
  Amount2 decimal(18, 2) NULL,
  Desc char(3) NULL )

六个输入明细记录加上标题将在目标表中产生三条记录:

ImportDate Name Amount1 Amount2 Desc
---------- ---- ------- ------- -----
2014-05-01 JOAN 0.00    30.00   ABC
2014-05-01 DAVE 11.00   21.85   DEF
2014-05-01 BERT 50.00   0.00    GHI

这是一个已解决的问题,可以帮助任何可能遇到类似问题的人。

1 个答案:

答案 0 :(得分:2)

可以使用ScriptConditional SplitMerge Join组件的组合来组合详细记录。

脚本组件添加详细记录计数,该记录计数针对遇到的每个DTL001记录递增。这提供了一个详细记录计数列,可用于对输入文件中彼此相邻的DTL001和DTL002记录进行排序和连接。

ssis data flow image

平面文件连接管理器和源用于将每个输入记录分成RecordType,RecordSubType和RecordData列。例如,前三个记录分为以下几部分:

"HDR", "001", "20140501      "
"DTL", "001", "JOAN     0.00 "
"DTL", "002", "     30.00 ABC"

接下来,Derived Header Columns组件添加HeaderRecordCount,DetailRecordCount和ImportDate列。这些最初是未填充的,但它们为脚本组件提供了存储标题和详细信息计数的位置,以及目标表的每一行所需的标题中的任何信息。此脚本还可以处理具有多个部分的文件,其中每个部分都有一个新的HDR001标题记录:

using System;
using System.Data;
using Microsoft.SqlServer.Dts.Pipeline.Wrapper;
using Microsoft.SqlServer.Dts.Runtime.Wrapper;

[Microsoft.SqlServer.Dts.Pipeline.SSISScriptComponentEntryPointAttribute]
public class ScriptMain : UserComponent
{
    static int _HeaderRecordCount = 0;
    static int _DetailRecordCount = 0;
    static DateTime _ImportDate = DateTime.MinValue;
    public override void Input0_ProcessInputRow(Input0Buffer Row)
    {
        if (Row.RecordType == "HDR" && Row.RecordSubType == "001")
        {
            _HeaderRecordCount = _HeaderRecordCount + 1;
            _ImportDate = DateTime.ParseExact(Row.RecordData.Substring(0, 8), "yyyyMMdd", System.Globalization.CultureInfo.InvariantCulture);
        }
        else if (Row.RecordType == "DTL" && Row.RecordSubType == "001")
        {
            _DetailRecordCount = _DetailRecordCount + 1;
        }
        Row.HeaderRecordCount = _HeaderRecordCount;
        Row.DetailRecordCount = _DetailRecordCount;
        Row.ImportDate = _ImportDate;
    }
}

条件性拆分组件然后将DTL001和DTL002记录发送到不同的路径。分割条件是:

RecordType == "DTL" && RecordSubType == "001"
RecordType == "DTL" && RecordSubType == "002"

这些路径每个都在DetailRecordCount列上排序,Merge Join使用该列组合它们。 001路径中的所有记录都传递到Merge Join输出,002路径中的RecordData列也传递到单独的输出列(例如,RecordData002)。

现在,两个平面文件记录的内容都可在单个数据流记录中使用。派生详细信息列组件用于提取任何所需信息,并将结果列发送到目标表。