2

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

该列表包含两列:

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

我想将此文件作为 SSIS 的源提供。然后我希望它一行一行地通过它。对于每一行,我希望它读取 FilePath 列中的文件并检查类型。

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

如果有人能提供我需要遵循的步骤的高级列表,我将不胜感激。

任何帮助表示赞赏。

4

3 回答 3

4

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

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

变量

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

控制流

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

连接

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

数据流任务

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

对于每个集合

对于每个变量

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

表达式 A

  • 同样,点击Type B files数据流任务,按F4调出属性。单击属性上可用的省略号按钮。Expression
  • 在 Property Expressions Editor 上,选择DisableProperty 并输入表达式!(@[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

输入文件

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

桌子

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

平面文件一般

平面文件列

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

高级平面文件

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

数据流任务

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

平面文件源连接

平面文件源列

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

ole db 目标连接

ole db 目标列

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

特性

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

表达

  • 这是一个仅包含 A 类文件的示例 Files.txt 文件。

文件

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

f01

f02

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

表数据

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

数据流任务类型 b

希望这可以帮助您完成任务。

于 2012-04-26T02:59:54.587 回答
1

我建议您为要执行的每种不同类型的文件加载创建一个 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
}
于 2012-04-26T01:15:04.360 回答
1

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

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

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

在此处输入图像描述

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

然后,我们将使用该 Recordset 对象作为 ForEach 循环容器的源,通常称为粉碎。Bingle 术语“Shred 记录集 ssis”,您一定会看到许多描述如何做到这一点的文章。最终结果是,对于该源 CM 控制文件中的每一行,您将这些值分配给 CurrentPath、CurrentType 变量。

在该循环容器内,创建一个控制中心点,以便控制向外辐射。我发现一个脚本任务非常适合这个。将它拖到画布上,给它一个强名称以表明它不用于任何事情,然后创建一个数据流来处理每个处理排列。

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

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

于 2012-04-26T02:28:22.293 回答