我可以使用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
这是一个已解决的问题,可以帮助任何可能遇到类似问题的人。
答案 0 :(得分:2)
可以使用Script,Conditional Split和Merge Join组件的组合来组合详细记录。
脚本组件添加详细记录计数,该记录计数针对遇到的每个DTL001记录递增。这提供了一个详细记录计数列,可用于对输入文件中彼此相邻的DTL001和DTL002记录进行排序和连接。
平面文件连接管理器和源用于将每个输入记录分成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)。
现在,两个平面文件记录的内容都可在单个数据流记录中使用。派生详细信息列组件用于提取任何所需信息,并将结果列发送到目标表。