在 SSIS 2012 的 OLE DB 源中使用动态 SQL

Posted

技术标签:

【中文标题】在 SSIS 2012 的 OLE DB 源中使用动态 SQL【英文标题】:Using dynamic SQL in an OLE DB source in SSIS 2012 【发布时间】:2013-10-29 18:54:28 【问题描述】:

我有一个存储过程作为 SQL 命令文本,它正在传递一个包含表名的参数。然后,proc 从该表中返回数据。我不能直接将该表称为 OLE DB 源,因为某些业务逻辑需要发生在 proc 中的结果集上。在 SQL 2008 中,这很好用。在升级的 2012 包中,我得到“无法确定元数据,因为 ... 包含动态 SQL。考虑使用 WITH RESULT SETS 子句显式描述结果集。”

问题是我无法在 proc 中定义字段名称,因为作为参数传递的表名称可能是不同的值,并且每次生成的字段都可能不同。有人遇到这个问题或有什么想法吗?我已经使用“dm_exec_describe_first_result_set”、临时表和包含 WITH RESULT SETS 的 CTE 尝试了各种动态 SQL,但它在 SSIS 2012 中不起作用,同样的错误。上下文是许多动态 SQL 方法的问题。

这是我尝试过的最新东西,没有运气:

DECLARE @sql VARCHAR(MAX)
SET @sql = 'SELECT * FROM ' + @dataTableName

DECLARE @listStr VARCHAR(MAX)
SELECT @listStr = COALESCE(@listStr +',','') + [name] + ' ' + system_type_name FROM sys.dm_exec_describe_first_result_set(@sql, NULL, 1)

exec('exec(''SELECT * FROM myDataTable'') WITH RESULT SETS ((' + @listStr + '))')

【问题讨论】:

如果您在 OLEDB 源中尝试 SET FMTONLY OFF; EXEC MyProc 会怎样。这样会更好吗? 试过了,还是不行。 SSIS 需要元数据。 无赖。从 2008 年到 2012 年,一位处理临时表的朋友使用了这个技巧。 您的数据是否来自 SQL Server 2012? 是的。如果我的存储过程调用了一个使用 RETURN TABLE 的函数,我可以让它工作,但我还没有弄清楚如何使函数动态地运行,所以问题可能刚刚转移到一个新的领域。 【参考方案1】:

所以我好心地问,为什么在上帝的绿色地球上,您使用 SSIS 数据流任务来处理这样的动态源数据?

您遇到麻烦的原因是因为您破坏了 SSIS 数据流任务的所有目的:

提取具有已知元数据的已知源,可以在设计时进行静态类型化和缓存 通过简单(理想情况下是异步)转换运行已知流程 获取转换后的数据并将其加载到一个已知的目的地,同时包含已知的元数据

可以使用带回不同数据的参数化数据源。但坦率地说,让他们每次都带回完全不同的元数据而不同集合之间没有一致性,这很荒谬,而且我不完全确定我想知道您如何处理工作 2008 包中的所有列元数据。

这就是为什么它希望您将 WITH RESULTS SET 添加到 SSIS 查询中 - 这样它就可以生成一些元数据。它在运行时不会这样做 - 它不能!它必须有一组已知的列(因为它将它们都别名为编译变量)才能使用。每次运行该数据流任务时,它都需要相同的列 - 完全相同的列,包括名称、类型和约束。

这导致了一个(可怕的,糟糕的)解决方案 - 只需将所有数据粘贴到一个带有 Column1、Column2 ... ColumnN 的临时表中,然后使用与表名参数相同的变量来有条件地分支您的编写代码并对列做任何你想做的事情。

另一个更明智的解决方案是为每个源表创建一个数据流任务,并在优先约束中使用您的参数来选择应该运行的数据流任务。

对于这种为开箱即用 ETL 量身定制的解决方案,您还应高度考虑仅在 C# 或脚本任务中滚动您自己的解决方案,而不是 SSIS 提供的数据流任务。

简而言之,请不要这样做。想想孩子们(包)!

【讨论】:

理论上这很好,但实际上,如果您有 230 个 SSIS 包需要升级到 2012 年,并且在 2008 年设置了数百个 ole DB 源并像这样完美地工作,那么您正在寻找一个快速解决方案。【参考方案2】:

我使用 CozyRoc Dynamic DataFlow Plus 来实现这一点。

使用配置表构建 SQL Select 语句,我有一个 SSIS 包,可将数据从 Oracle 和 Sybase(或任何 OLEDB 源)加载到 MS SQL。一些结果集有数百万行,性能非常好。

无需每次需要新表时都编写新包,而是可以在几分钟内完成配置并在经过预先测试且功能强大的现有包上运行。

如果没有它,我可能会编写数百个包。

【讨论】:

以上是关于在 SSIS 2012 的 OLE DB 源中使用动态 SQL的主要内容,如果未能解决你的问题,请参考以下文章

使用 SSIS 中的参数作为 OLE DB 源执行存储过程

SSIS - 检查 OLE DB 源架构

SSIS - OLE DB 目标 - 表或视图加载与快速加载

SSIS:无法创建OLE DB访问器。验证列元数据是否有效

SSIS - 将 Fact 与查找表匹配两次时重用 Ole DB 源

SSIS - 如何从平面文件插入到具有日期范围的OLE DB?