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

时间:2012-04-25 21:35:28

标签: c# 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中以获取所有行。

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

感谢任何帮助。

3 个答案:

答案 0 :(得分:4)

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

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

Variables

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

control flow

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

connections

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

Data flow task

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

for each collection

for each variable

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

Expression A

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

Expression B

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

sample file a

sample execution a

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

sample file b

sample execution b

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

配置数据流任务类型A文件

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

type a file

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

Table

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

flat file general

flat file columns

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

flat file advanced

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

data flow task

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

flat file source connection

flat file source columns

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

ole db destination connection

ole db destination columns

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

Properties

  • 在“属性表达式”构建器上,选择ConnectionString属性并将其设置为表达式@[User::FileName]

Expression

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

files

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

f01

f02

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

table data

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

data flow task type b

希望能帮助您完成任务。

答案 1 :(得分:1)

我建议您为要执行的每种不同类型的文件加载创建一个SSIS包。您可以从其他程序执行这些程序包,请参阅此处:How to execute an SSIS package from .NET?

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

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
}

答案 2 :(得分:1)

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

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

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

enter image description here

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

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

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

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

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