5

我有一个存储过程作为 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 + '))')
4

2 回答 2

3

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

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

  • 提取具有已知元数据的已知源,可以在设计时静态键入和缓存
  • 通过直接(理想情况下是异步)转换来运行已知过程
  • 获取转换后的数据并将其加载到已知的目的地,同时也带有已知的元数据

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

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

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

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

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

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

于 2013-10-29T21:13:59.797 回答
1

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

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

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

如果没有它,我本来可以编写数百个包。

于 2013-12-11T23:23:12.353 回答