我们编写了许多SSIS包,使用平面文件源从CSV文件导入数据。
现在看来,在将这些软件包部署到生产环境之后,这些文件的提供者可能会提供文件列顺序发生变化的文件(请勿询问!)。目前,如果发生这种情况,我们的包将失败。
例如,在每行的开头插入一个附加列。在这种情况下,平面文件源继续使用现有的列顺序,这显然会对转换产生不利影响!
EG。使用一个简单的示例,原始文件具有以下内容:
OurReference,Client,Amount
235,MFI,20000.00
236,MS,30000.00
平面文件源的输出是:
OurReference Client Amount
235 ClientA 20000.00
236 ClientB 30000.00
随后,传送的文件更改为:
OurReference,ClientReference,Client,Amount
235,A244,ClientA,20000.00
236,B222,ClientB,30000.00
当针对此文件运行现有的未更改的包时,平面文件源的输出为:
OurReference Client Amount
235 A244 ClientA,20000.00
236 B222 ClientB,30000.00
理想情况下,我们希望使用能够解决此问题的数据源 - 即根据列名而不是列顺序生成输出。
欢迎任何建议!
答案 0 :(得分:1)
最佳方法是在SSIS包导入CSV数据之前运行检查。这可能必须是外部脚本/应用程序,因为我不认为您可以在MS Business Intelligence Studio中操作数据。
答案 1 :(得分:1)
不是我知道的。
提前检查问题的可能性是设置两个不同的连接管理器,一个具有单个平行。这个可以读取第一行并判断它是否正常并中止。
如果你想做这项工作,你可以更进一步,让那个扁平的单字段行成为唯一的连接管理器,并使用流中的脚本组件来解析行并分配给你需要的列后来在流程中。
据我所知,没有办法在运行时动态地向流添加列 - 因此需要将所需的所有列添加到脚本任务输出中。是否可以找到它们并从每一行解析它取决于您。不能使用任何“新”(即未预料到的)列。缺少您的列可能会默认或抛出异常。
最后一种可能性是在运行之前使用SSIS对象模型修改包以更改连接管理器 - 甚至可以使用基于输入文件检查的对象模型动态编写整个包。我在C#中使用模板完成了相当多的包生成,然后根据从描述大型机文件的主文件中获取的元数据添加了信息。
答案 2 :(得分:0)
这是一个粗略的方法。我会在最后写下限制。 创建一个平面文件源。将整行放在一列中。 不要检查第一个数据行中的列名称。 创建脚本组件 代码:
public override void Input0_ProcessInputRow(Input0Buffer Row)
{
string sRow = Row.Column0;
string sManipulated = string.Empty;
string temp = string.Empty;
string[] columns = sRow.Split(',');
foreach (string column in columns)
{
sManipulated = string.Format("{0}{1}", sManipulated, column.PadRight(15, ' '));
}
/* Note: For sake of demonstration I am padding to 15 chars.*/
Row.Column0 = sManipulated;
}
创建一个平面文件目的地 将Column0映射到Column0
限制:我随意将每个字段填充为15个字符。需要考虑的要点: 1.我们需要每个相同大小的领域吗? 2.如果是,那个大小是多少?
处理这种情况的一般方法是创建一个表来存储文件名,字段和字段大小。 使用文件名动态创建源和目标连接管理器。 使用字段名称和相应的字段大小来确定填充。不确定,如果你需要这么大的灵活性。如果您有任何疑问,请回复。