SSIS – 如何从文件路径位于另一个文本文件中的文本文件中加载数据?

我有一个文本文件,其中包含要加载到数据库中的文件列表。

该列表包含两列:

FilePath,Type c:\f1.txt,A c:\f2.txt,B c:\f3.txt,B 

我想提供此文件作为SSIS的源。 然后我希望它逐行完成。 对于每一行,我希望它读取FilePath列中的文件并检查Type。

如果type是A,那么我希望它忽略位于当前行的FilePath列的文件的前4行,然后将该文件中的其余数据加载到表中。 如果type是B,那么我希望它打开文件并将文件的第一列复制到表1中,将第二列复制到表2中以获取所有行。

如果有人可以请我提供我需要遵循的高级别步骤,我将非常感激。

任何帮助表示赞赏。

这是在SSIS中执行此操作的一种方法。 以下步骤适用于SSIS 2008 R2

  • 创建一个SSIS包并创建三个包变量,即FileNameFilesToReadType 。 FilesToRead变量将保存文件列表及其类型信息。 我们将有一个循环,它将遍历每个记录,并在每次循环时将信息存储在FileNameType变量中。

变量

  • 在控制流选项卡上,放置一个数据流任务,后跟一个ForEach循环容器。 数据流任务将读取包含必须处理的文件列表的文件。 然后循环将遍历每个文件。 您的控制流选项卡最终看起来像这样。 目前,由于没有配置任何内容,因此会出现错误。 我们很快就会谈到这一点。

控制流

  • 在连接管理器部分,您需要四个连接。
  • 首先,您需要一个OLE DB连接才能连接到数据库。 将其命名为SQLServer
  • 第二,平面文件连接管理器读取包含文件和类型列表的文件。 此平面文件连接管理器将包含两个配置的列,即FileNameType Name,将其命名为Files
  • 第三,另一个平面文件连接管理器读取所有类型A的文件。将其命名为Type_A 。 在此平面文件连接管理器中,在Header rows to skip的文本框Header rows to skip输入值4,以便始终跳过前四行。
  • 第四,再一个平面文件连接管理器读取类型B的所有文件。将其命名为Type_B

连接

  • 让我们回到控制流程。 双击第一个数据流任务。 在数据流任务中,放置一个平面文件源,使用连接管理器Files读取所有Files ,然后放置一个Recordset Destination 。 在记录集目标中配置变量FilesToRead 。 您的第一个数据流任务如下所示。

数据流任务

  • 现在,让我们再回到控制流标签。 配置ForEach循环,如下所示。 此循环将遍历存储在变量FilesToRead的记录集。 因为,记录集包含两列,每次循环记录时,变量FileNameType将被赋予当前记录的值。

为每个集合

对于每个变量

  • 在内部,对于每个循环容器,有两个数据流任务,即Type A filesType B files 。 您可以根据需要配置每个数据流任务,以从连接管理器中读取文件。 但是,我们需要根据正在读取的文件禁用任务。
  • 只有在处理A类型文件时,才应启用Type A files数据流任务。
  • 同样,只有在处理B类型文件时才应启用B类文件数据流任务。
  • 要实现此目的,请单击“ Type A files数据流任务,然后按F4以显示属性。 单击Expression属性上的省略号按钮。
  • 在Property Expressions Editor上,选择Disable Property并输入表达式!(@[User::Type] == "A")

表达式A.

  • 同样,单击Type B files数据流任务,然后按F4以显示属性。 单击Expression属性上的省略号按钮。
  • 在Property Expressions Editor上,选择Disable Property并输入表达式!(@[User::Type] == "B")

表达式B.

  • 下面是一个示例Files.txt,其中只包含列表中的A类型文件。 执行包以读取此文件时,您会注意到只有Type A files数据流任务。

样本文件

样本执行

  • 这是另一个示例Files.txt,其中仅包含列表中的B类型文件。 执行包以读取此文件时,您会注意到只有Type B files数据流任务。

样本文件b

样本执行b

  • 如果Files.txt包含A和B类型文件,则循环将根据正在处理的文件类型执行相应的数据流任务。

配置数据流任务键入A文件

  • 我们假设您的A类平面文件有三个列布局,如下所示,以逗号分隔值。 此处的文件数据使用带有所有特殊字符的Notepad ++显示。 CR LF表示行以回车和换行结束。 该文件存储在路径C:\ f1.txt中

输入文件

  • 我们需要数据库中的表来导入数据。 让我们在SQL Server数据库中创建一个名为dbo.Table_A的表,如下所示。

表

  • 现在,转到SSIS包。 以下是配置名为Type_A的Flat File连接管理器的详细信息。 为连接管理器命名。 您需要在标题行中指定值4以跳过文本框。 你的平面文件连接管理器应该是这样的。

平面文件一般

平面文件列

  • 在“高级”选项卡上,您可以根据需要重命名列名。

平面文件先进

  • 既然已配置连接管理器,我们需要配置数据流任务Type A files来处理相应的文件。 双击数据流任务Type A files 。 在任务中放置一个Flat文件源和OLE DB Destination。

数据流任务

  • 必须配置平面文件源以从平面文件连接管理器中读取文件。

平面文件源连接

平面文件源列

  • 数据流任务没有做任何特殊的事情。 它只是读取类型A的平面文件,并将数据插入到表dbo.Table_A中。 现在,我们需要配置OLE DB Destination以将数据插入数据库。 平面文件连接管理器和表中配置的列名不相同。 因此,必须手动映射它们。

ole db目标连接

ole db目标列

  • 现在,配置了数据流任务。 我们必须使从Files.txt读取的文件路径正确传递。 为此,请单击Type_A平面文件连接管理器,然后按F4以显示属性。 将DelayValidation属性设置为True 。 单击Expressions属性上的Ellipsis按钮。

属性

  • 在Property Expression构建器上,选择ConnectionString属性并将其设置为Expression @[User::FileName]

表达

  • 以下是仅包含Type A文件的Files.txt文件示例。

档

  • 以下是样本类型A文件f01.txt和f02.txt

F01

F02

  • 包执行后,将在Table_A表中找到以下数据

表数据

  • 对于B类文件,必须遵循上述配置步骤。 但是,由于文件处理逻辑不同,数据流任务看起来会略有不同。 数据流任务类型B文件会是这样的。 因为您必须将B类文件中的两列插入到不同的表中。 您必须使用可以创建输入数据克隆的多播转换。 您可以使用每个多播输出传递到不同的转换或目标。

数据流任务类型b

希望能帮助您完成任务。

我建议您为每个不同类型的文件加载创建一个SSIS包。 您可以从其他程序执行这些包,请参见此处: 如何从.NET执行SSIS包?

有了这些信息,您可以编写一个快速程序来执行相关的包:

 var jobs = File.ReadLines("C:\\temp\\order.txt") .Skip(1) .Select(line => line.Split(',')) .Select(tokens => new { File = tokens[0], Category = tokens[1] }); foreach (var job in jobs) { // execute the relevant package for job.Category using job.File } 

我的解决方案看起来像N + 1平面文件连接管理器来处理源文件。 CM A将解决跳过前4行文件格式,B听起来像是一个2列文件等。最后一个CM将用于解析您已经说明的命令文件。

现在您已经定义了所有这些连接管理器,您可以进行处理逻辑。

创建3个变量。 2类型字符串(CurrentPath,CurrentType)。 1是Object类型,我称之为Recordset。

在此处输入图像描述

第一个数据流使用“CM Control”从平面文件源读取所有行。 这是您在示例中提供的数据。

然后,我们将使用该Recordset对象作为ForEach循环容器的源,通常称为碎化。 Bingle术语“Shred recordset ssis”,你必然要写一些描述如何做的文章。 最终结果是,对于源CM控制文件中的每一行,您将这些值分配给CurrentPath,CurrentType变量。

在Loop容器内部,创建一个控制中心点以控制辐射。 我发现脚本任务对此非常有效。 将它拖到canvas上,给它一个强名称,表示它没有用于任何东西,然后创建一个数据流来处理每个处理排列。

神奇来自于使用表达式。 在SSIS的所有东西附近的Dang可以在他们的属性上设置表达式,这是专业人士与poseurs的区别。 在这里,我们将双击连接到给定数据流的行并将约束类型从“约束”更改为“表达式和约束”然后使用的表达式类似于@[User::CurrentType] == "A"这将确保仅在父任务成功且条件为真时才采用路径。

表达魔术的第二位将应用于连接管理器本身。 他们需要使用@[User::CurrentFile]属性的值驱动其ConnectionString属性。 这将允许C:\filea.txt的设计C:\filea.txt但允许来自控制文件的运行时值为\\network\share\ClientFileA.txt除非所有文件具有相同的结构,否则您将最有可能需要在属性中将DelayValidation设置为True。 否则,SSIS将失败PreValidation,因为所有“CM A”到“CM N”将使用该CurrentFile变量,该变量可能是也可能不是该文件布局的有效连接字符串。