SSIS 使用派生列动态添加源中不存在的列
SSIS Use Derived Column to Dynamically Add Column(s) that do not Exists in Source
我正在尝试将 tables 从两个源系统拉到一个合并的目标服务器中。我们有多个业务部门驻留在不同的源系统上,并且大部分具有相同的 table 结构,但是其中一个源系统已升级到较新的版本并且具有其他源没有的一些列。
我现在将数据流任务设置为 运行 在 for each 循环中,该循环查找并循环遍历我的每个源。我需要根据源系统更改查询以包含缺少的列。我希望我可以通过使用派生列添加列来动态地执行此操作,如果有问题的列不存在,如果它确实存在,我希望包忽略派生列并继续.
我也尝试过将我的查询写到变量中,但我不太明白如何让 DFT 根据源连接选择特定的查询变量。
编辑:Table 下面的比较示例:
--Updated Source
SELECT [ProductID]
,[ProductNumber]
,[ReorderPoint]
,[ListPrice]
,[SizeUnitMeasureCode]
,[WeightUnitMeasureCode]
,[Class]
,[Style]
,[ProductSubcategoryID]
,[ProductModelID]
,[ModifiedDate]
FROM [Sales].[Product];
--Outdated Source
SELECT [ProductID]
,[ProductNumber]
,[ReorderPoint]
,[ListPrice]
,[SizeUnitMeasureCode]
,[WeightUnitMeasureCode]
,[Class]
,[Style]
,NULL AS [ProductSubcategoryID]
,NULL AS [ProductModelID]
,[ModifiedDate]
FROM [Sales].[Product];
我希望能够提取所有列,包括过时源中缺少的列。用 NULL AS 标注的列是有问题的缺失列。
在 SSIS 中以半动态方式执行此操作的唯一方法是在数据流源查询中使用表达式,在连接到缺少某些列的系统时将列名称替换为文字空值。或者给您数据流中的脚本源并替换代码中缺失的列。
我不喜欢这个解决方案,但它可能有效。正如我提到的,您可以构建一个动态语句,然后从中构建查询。这很丑陋,但是,就像我说的,SSIS 期望一致的定义,所以如果你不能给它,那么你必须跳过一些障碍。
这也是未经测试的,但希望能给你灵感。
DECLARE @ColumnList table (OrdinalPosition int IDENTITY(1,1),
ColumnName sysname,
ColumnDatatype sysname);
--The following datatypes are completely guessed
INSERT INTO @ColumnList
VALUES(N'ProductID',N'int'),
(N'ProductNumber',N'int'),
(N'ReorderPoint',N'int'),
(N'ListPrice',N'decimal'),
(N'SizeUnitMeasureCode',N'decimal'); --You get the idea
DECLARE @SQL nvarchar(MAX),
@CRLF nchar(2) = NCHAR(13) + NCHAR(10);
DECLARE @Delimiter nvarchar(20) = N',' + @CRLF + N' ';
SELECT @SQL = N'SELECT ' +
STRING_AGG(ISNULL(QUOTENAME(c.[name]),N'CONVERT(' + QUOTENAME(CL.ColumnDatatype) + N',NULL') + N') AS ' + QUOTENAME(CL.ColumnName),@Delimiter) WITHIN GROUP (ORDER BY CL.OrdinalPosition) + @CRLF +
N'FROM Sales.Product;'
FROM @ColumnList CL
LEFT JOIN sys.columns c
JOIN sys.tables t ON c.object_id = t.object_id
AND t.[name] = N'Product'
JOIN sys.schemas s ON t.schema_id = s.schema_id
AND s.[name] = N'dbo'
ON CL.ColumnName = c.[name];
--PRINT @SQL; --Your best friend
EXEC sys.sp_executesql @SQL;
您应该能够使用它作为 SSIS 源的定义并且它应该创建一个包含您想要的所有列的数据集,即使 table 没有。
我正在尝试将 tables 从两个源系统拉到一个合并的目标服务器中。我们有多个业务部门驻留在不同的源系统上,并且大部分具有相同的 table 结构,但是其中一个源系统已升级到较新的版本并且具有其他源没有的一些列。
我现在将数据流任务设置为 运行 在 for each 循环中,该循环查找并循环遍历我的每个源。我需要根据源系统更改查询以包含缺少的列。我希望我可以通过使用派生列添加列来动态地执行此操作,如果有问题的列不存在,如果它确实存在,我希望包忽略派生列并继续.
我也尝试过将我的查询写到变量中,但我不太明白如何让 DFT 根据源连接选择特定的查询变量。
编辑:Table 下面的比较示例:
--Updated Source
SELECT [ProductID]
,[ProductNumber]
,[ReorderPoint]
,[ListPrice]
,[SizeUnitMeasureCode]
,[WeightUnitMeasureCode]
,[Class]
,[Style]
,[ProductSubcategoryID]
,[ProductModelID]
,[ModifiedDate]
FROM [Sales].[Product];
--Outdated Source
SELECT [ProductID]
,[ProductNumber]
,[ReorderPoint]
,[ListPrice]
,[SizeUnitMeasureCode]
,[WeightUnitMeasureCode]
,[Class]
,[Style]
,NULL AS [ProductSubcategoryID]
,NULL AS [ProductModelID]
,[ModifiedDate]
FROM [Sales].[Product];
我希望能够提取所有列,包括过时源中缺少的列。用 NULL AS 标注的列是有问题的缺失列。
在 SSIS 中以半动态方式执行此操作的唯一方法是在数据流源查询中使用表达式,在连接到缺少某些列的系统时将列名称替换为文字空值。或者给您数据流中的脚本源并替换代码中缺失的列。
我不喜欢这个解决方案,但它可能有效。正如我提到的,您可以构建一个动态语句,然后从中构建查询。这很丑陋,但是,就像我说的,SSIS 期望一致的定义,所以如果你不能给它,那么你必须跳过一些障碍。
这也是未经测试的,但希望能给你灵感。
DECLARE @ColumnList table (OrdinalPosition int IDENTITY(1,1),
ColumnName sysname,
ColumnDatatype sysname);
--The following datatypes are completely guessed
INSERT INTO @ColumnList
VALUES(N'ProductID',N'int'),
(N'ProductNumber',N'int'),
(N'ReorderPoint',N'int'),
(N'ListPrice',N'decimal'),
(N'SizeUnitMeasureCode',N'decimal'); --You get the idea
DECLARE @SQL nvarchar(MAX),
@CRLF nchar(2) = NCHAR(13) + NCHAR(10);
DECLARE @Delimiter nvarchar(20) = N',' + @CRLF + N' ';
SELECT @SQL = N'SELECT ' +
STRING_AGG(ISNULL(QUOTENAME(c.[name]),N'CONVERT(' + QUOTENAME(CL.ColumnDatatype) + N',NULL') + N') AS ' + QUOTENAME(CL.ColumnName),@Delimiter) WITHIN GROUP (ORDER BY CL.OrdinalPosition) + @CRLF +
N'FROM Sales.Product;'
FROM @ColumnList CL
LEFT JOIN sys.columns c
JOIN sys.tables t ON c.object_id = t.object_id
AND t.[name] = N'Product'
JOIN sys.schemas s ON t.schema_id = s.schema_id
AND s.[name] = N'dbo'
ON CL.ColumnName = c.[name];
--PRINT @SQL; --Your best friend
EXEC sys.sp_executesql @SQL;
您应该能够使用它作为 SSIS 源的定义并且它应该创建一个包含您想要的所有列的数据集,即使 table 没有。