我正在实施SSIS包,目前正在尝试执行以下操作。
我创建了一个执行SQL任务来解决第1步和使用oledb源和oledb目标的数据流来解决第二点问题。到目前为止它一直在成功运行,但不适用于我使用临时表的存储过程。
当我编辑oledb源并单击预览按钮时,我收到错误,没有返回列
我知道SSIS在执行依赖于临时表的存储过程时生成列存在问题。我已经将存储过程转换为使用临时表变量,并且当我进行预览时,它现在能够在SSIS中返回列。唯一的缺点是存储过程需要更长的时间来执行。它使用1小时15分钟,而使用临时表则需要15分钟。
我确实看到了在执行存储过程之前使用SET FMTONLY的建议,作为更改为临时表变量的替代解决方案,但这似乎不起作用,因为我收到语法或权限被拒绝错误。
有人可以告诉我一个解决我的问题的方法,但不会影响性能。
答案 0 :(得分:1)
听起来你已经阅读过在SSIS中使用Temp表的所有方法,包括IF 1=0...
技巧?如果你还没有看过那个,请谷歌吧。
您说使用表变量会导致存储过程比使用Temp Table花费大约5倍的时间。最可能的原因是您正在索引临时表而不是表变量。如果你不知道表变量可以被索引,他们可以。你可以尝试一下。
最后,您没有提到的解决方案是,您可以使用在完成使用后被截断的真实表替换临时表。
答案 1 :(得分:0)
简短评论:
尝试EXEC WITH RESULT SETS并为具有临时表的proc指定自己的元数据;或者使用脚本组件作为源并自己指定输出列。
长评:
从技术上讲,它是您在SSIS中使用的驱动程序/数据库,用于决定使用临时表时的行为。
使用SSIS的管道组件时,元数据是一个重要因素。通过元数据,我指的是管道组件使用的列的名称,它们的数据类型等。在设计数据流时,某人/某事应该将这些元数据提供给需要它的组件。
在大多数情况下,SSIS会自动检索元数据。未连接到外部数据源的组件(如条件拆分等)从其连接的其他组件获取其元数据。对于连接到外部数据源的管道组件(如Oledb源,oledb目标,查找等),SSIS提供了一种在没有人为参与的情况下获取此元数据的机制。此机制涉及驱动程序连接到数据库并检索输出的元数据。如果驱动程序/数据库能够返回元数据,则使用该元数据。如果驱动程序/数据库无法运行,那么您将收到所看到的错误。我的其余评论是基于您在问题中使用SQL Server数据库的假设。
在SSIS中使用SQL Server数据库时,通常我们使用Microsoft提供的本机客户端驱动程序。当试图获取元数据时,这些驱动程序尝试获取元数据而不实际执行SQL语句(实际执行可能有副作用;而且,可能需要超过几秒/分钟/小时;并且您不需要副作用和在程序包设计时间长的等待时间。)因此,为了获取元数据,驱动程序依赖于sql命令中使用的实际对象的元数据。如果该命令使用物理表或视图,则SQL Server已具有可用的元数据并可将其提供给驱动程序。如果它是临时表,则SQL Server在创建临时表之前不具有元数据。如果使用FMT ONLY选项,您可以以这种方式使用它来创建临时表,但避免任何繁重的处理/副作用,从而能够检索元数据而不会受到惩罚。 2012年之后,这些本机客户端驱动程序依赖于一些较新的功能来检索元数据而不是2012之前的驱动程序。在2012年及之后,驱动程序使用sp_describe_first_result_set proc来检索元数据。因此,是否可以获取元数据取决于sp_describe_first_result_set proc的能力。
因此,虽然SSIS可以自动获取元数据(因为驱动程序/数据库),但在某些情况下它不会自动获取元数据(同样是因为驱动程序/数据库)。在涉及第二种情况的情况下,某些其他进程(通常是人)可以帮助驱动程序推断元数据或直接向组件提供元数据。
为了帮助驱动程序,在SQL Server 2012及更高版本的情况下,您可以使用WITH RESULTSETS子句指定输出元数据。当此子句存在时,驱动程序将使用它并且不会尝试从系统对象查询元数据;从而避免你本来会得到的错误。如果您使用的是SQL Server 2008附带的驱动程序,则只能使用FMT。此选项位于驱动程序/数据库级别。
另一个选项可能是使用脚本组件作为源,在输出列中,您可以指定列/元数据。在这种情况下,SSIS不会尝试从数据源检索元数据,但会依赖于您在脚本组件的“输出”部分中提供的定义。
如您所见,这两个选项都涉及指定元数据的人(或其他一些进程),而不是SSIS尝试以自动方式检索元数据。如果使用SQL Server,我更喜欢第一个选项,如果使用像MySql这样的数据库,我更喜欢第二个选项。