如何在 SSIS 中动态映射输入和输出列?

How to Map Input and Output Columns dynamically in SSIS?

我必须通过 SSIS 从 .dbf 文件上传数据到 SQL 服务器。 我的输出列是固定的,但输入列不是固定的,因为文件来自客户端,客户端可能已经按照自己的风格更新了数据。可能还有一些未使用的列,或者输入列名称可能与输出列不同。

我想到的一个想法是将文件输入列映射到 SQL 数据库 table 中的输出列,并仅使用文件 ID 行中存在的那些列。

但我不知道该怎么做。有什么想法吗?

Table 示例

FileID InputColumn OutputColumn Active
1 CustCd CustCode 1
1 CName CustName 1
1 Address CustAdd 1
2 Cust_Code CustCode 1
2 Customer Name CustName 1
2 Location CustAdd 1

如果您创建一个类似的 table,您可以在 2 种方法中使用它在 SSIS 包内动态映射列,或者您必须以编程方式构建整个包。在这个回答中,我将尝试给你一些关于如何做到这一点的见解。

(1) 使用别名构建源代码 SQL 命令

注意:只有当所有 .dbf 文件的列数相同但名称不同时,此方法才有效

在这种方法中,您将根据您创建的文件 ID 和映射 table 生成将用作源的 SQL 命令。您必须知道存储在变量中的文件 ID 和 .dbf 文件路径。例如:

假设Table名称为inputoutputMapping

使用以下命令添加执行 SQL 任务:

DECLARE @strQuery as VARCHAR(4000)

SET @strQuery = 'SELECT '

SELECT @strQuery = @strQuery + '[' + InputColumn + '] as [' + OutputColumn + '],'
FROM inputoutputMapping
WHERE FileID = ?

SET @strQuery = SUBSTRING(@strQuery,1,LEN(@strQuery) - 1) + ' FROM ' + CAST(? as Varchar(500))

SELECT @strQuery

并且在“参数映射”选项卡中 select 包含要映射到参数的文件 ID 的变量 0 和包含 .dbf 文件名的变量(替代 table 名称)到参数 1

将结果集类型设置为 Single Row 并将结果集 0 存储在字符串类型的变量中,例如 @[User::SourceQuery]

ResultSet 值如下:

SELECT [CustCd] as [CustCode],[CNAME] as [CustName],[Address] as [CustAdd] FROM database1

OLEDB Source select Table 访问模式到 SQL 来自变量的命令并使用 @[User::SourceQuery] 变量作为源。


(2) 使用脚本组件作为源

在这种方法中,您必须在数据流任务中使用脚本组件作为源:

首先,如果您不想硬编码,您需要通过变量将 .dbf 文件路径和 SQL 服务器连接传递到脚本组件。

在脚本编辑器中,您必须为在目标 table 中找到的每个列添加一个输出列,并将它们映射到目标

在脚本中,您必须将 .dbf 文件读入数据table:

将数据加载到一个数据table后,还要用您在SQL服务器中创建的映射Table中找到的数据填充另一个数据table。

在数据 table 列循环之后,将 .ColumnName 更改为相关的输出列,例如:

foreach (DataColumn col in myTable.Columns)
    {

    col.ColumnName = MappingTable.AsEnumerable().Where(x => x.FileID = 1 && x.InputColumn = col.ColumnName).Select(y => y.OutputColumn).First(); 

    }

循环遍历数据中的每一行后table并创建一个脚本输出行。

另外注意,在分配输出行时,必须检查列是否存在,可以先将所有列名添加到字符串列表中,然后使用它来检查,例如:

var columnNames = myTable.Columns.Cast<DataColumn>()
                             .Select(x => x.ColumnName)
                             .ToList();  


foreach (DataColumn row in myTable.Rows){

if(columnNames.contains("CustCode"){

    OutputBuffer0.CustCode = row("CustCode");

}else{

    OutputBuffer0.CustCode_IsNull = True

}

//continue checking all other columns

}

如果您需要有关使用脚本组件作为源的更多详细信息,请查看以下链接之一:


(3) 动态构建包

我认为除了您可以选择动态构建包之外,您没有其他方法可以用来实现这个目标,那么您应该选择:


(4) SchemaMapper:C# 模式映射class 库

最近我在 Git-Hub 上开始了一个新项目,这是一个使用 C# 开发的 class 库。您可以使用它将表格数据从 excel、word、powerpoint、text、csv、html、json 和 xml 导入 SQL 服务器 table 使用模式映射方法使用不同的模式定义。查看:

您可以关注此 Wiki 页面以获得分步指南: