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

13
我需要通过SSIS从.dbf文件上传数据到SQL Server中。 我的输出列是固定的,但输入列并不固定,因为这些文件来自客户端,客户端可能通过自己的样式更新了数据。可能还有一些未使用的列,或者输入列名与输出列名不同。
我脑海中的一个想法是将文件的输入列映射到SQL数据库表中的输出列,并仅使用该行中存在的列。
但我不知道如何做到这一点。有什么想法吗?
表格示例: 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

1
你想从那张表中得到什么输出?看起来你的需求需要手工劳动,或者可能使用人工智能... - Pham X. Bach
1
SSIS工作在静态元数据上,如果您的源(甚至目标)是动态的,那么您大多数情况下都会遇到麻烦。您可以使用自定义脚本任务组件(使用C#或Visual Basic)来正确解析您的动态输入并生成与目标匹配的标准、众所周知的输出。https://learn.microsoft.com/en-us/sql/integration-services/extending-packages-scripting-data-flow-script-component-types/creating-a-source-with-the-script-component?view=sql-server-2017 - EzLo
1
请检查我的答案更新(第4部分),您可能会发现它很有趣。 - Hadi
@Hadi,你无能为力 - 这就是问题所在。这需要一个智能系统来分析和确定需要进行哪些更改,不仅涉及数据模型,还包括系统的逻辑架构,包括:SSIS计算、存储过程、报表、视图等。我认为,对数据模型的更改应该是一项困难而艰苦的工作,以便对更改进行全面分析,从而完全理解其影响。在我看来,任何低于此水平的做法都是不负责任的。我不知道有哪个程序集可以完成这种工作。 - J Weezy
1
@JWeezy 我完全同意。 - Hadi
显示剩余9条评论
1个回答

12

如果您创建了类似的表格,则可以使用两种方法在SSIS包内动态映射列,或者您必须以编程方式构建整个包。在这个答案中,我将试图为您提供如何执行此操作的一些见解。

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

注意:此方法仅在所有.dbf文件具有相同列计数但名称不同的情况下才起作用

在此方法中,您将生成将用作源的SQL命令,该命令基于您创建的FileID和Mapping表。 您必须知道FileID和.dbf文件路径存储在变量中。 例如:

假设表名为inputoutputMapping

添加一个Execute 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
在参数映射选项卡中,选择包含要映射到参数0的FileID的变量和包含.dbf文件名(替代表名)的变量作为参数1
将结果集类型设置为Single Row,并将ResultSet 0存储在字符串类型的变量中,例如@[User::SourceQuery]
ResultSet值如下:
SELECT [CustCd] as [CustCode],[CNAME] as [CustName],[Address] as [CustAdd] FROM database1
OLEDB Source中选择从变量选择SQL命令的表访问模式,并使用@[User::SourceQuery]变量作为源。

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

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

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

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

在脚本内部,您必须将.dbf文件读入数据表:

在将数据加载到数据表后,还要使用MappingTable中找到的数据填充另一个数据表。

之后循环遍历数据表列并将.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(); 

    }
在循环遍历数据表的每一行并创建脚本输出行后。此外,请注意,在分配输出行时,必须检查列是否存在,您可以首先将所有列名称添加到字符串列表中,然后使用它进行检查,例如:
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#模式映射类库

最近我在Git-Hub上启动了一个新项目,这是使用C#开发的类库。您可以使用它将来自Excel,Word,PowerPoint,文本,CSV,HTML,JSON和XML的表格数据根据模式映射方法导入到具有不同模式定义的SQL Server表中。请查看:

您可以按照此Wiki页面进行逐步指南:


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接