正如大多数人所知,只要带有临时表的存储过程被用作OleDbSource,SSIS就很难读取元数据。以前,通过添加SET FMTONLY OFF可以轻松防止这种情况;在EXEC声明之前。这样做的缺点是存储过程在验证期间执行,这可能需要一段时间。从SQL 2012开始,我们可以使用WITH RESULT SETS来指定列及其数据类型。 SSIS会选择这一点,并且在SQL领域一切都很好。
但是,我想生成一个包含BIML的包,它使用这样的存储过程作为源,我无法使其工作。假设我有一个名为'dbo.csp_MyCsp'的存储过程,该过程使用名为'#MyTempTable'的临时表和1列'ColA int'。我正在尝试使用以下(类似的)Biml代码生成OleDbSource:
<OleDbSource ConnectionName="MyConnection" Name="OLE_SRC Test">
<DirectInput>
EXEC dbo.csp_MyCsp
WITH RESULT SETS
(
([Col1] int)
)
</DirectInput>
</OleDbSource>
我收到一条错误消息“无效对象#MyTempTable”。奇怪的是,如果我打开一个包并在我的OleDbSource中粘贴该代码,它的工作没有任何错误。我有一种直觉,认为SSIS和BIML的验证步骤是不同的。
你们有没有人有合适的解决方案?我不能使用FMTONLY OFF,因为存储过程需要一些时间来加载,这会导致生成超时。我正在使用SQL Server / SSIS 2014。
提前致谢!
马文
答案 0 :(得分:1)
我之前遇到过这些问题。我使用了here描述的解决方案。最初的答案不是关于使用BIML生成,而是在Visual Studio 2015中成功地将此解决方案与BIML Express一起使用。
我使用此存储过程作为示例:
CREATE PROCEDURE csp_MyCsp
AS
BEGIN
SET NOCOUNT ON;
IF 1 = 0
BEGIN
SELECT CONVERT(INT, NULL) AS [database_id]
, CONVERT(SYSNAME, NULL) AS [name]
END;
CREATE TABLE #mydatabases (
[database_id] INT,
[name] SYSNAME
);
INSERT INTO #mydatabases
SELECT [database_id], [name]
FROM sys.databases
SELECT [database_id], [name]
FROM #mydatabases
END;
这包含在我的BIML中:
EXEC dbo.csp_MyCsp WITH RESULT SETS (
(
[database_id] INT,
[database_name] SYSNAME
)
)
答案 1 :(得分:0)
我在当前的Biml项目中遇到了类似的类似问题。像你提到的那样,问题似乎是Biml没有考虑存储过程中的临时表生成。
我的解决方案(解决方法?)是首先使它们成为全局临时表,而不仅仅是临时表。然后,我创建了一个新的存储过程,它运行与我的主存储过程相同的代码来处理临时表的创建。在Biml中运行'Generate Packages'之前,我在SSMS中打开一个新的查询窗口,运行该存储过程并保持该窗口打开(只要会话或此案例查询窗口打开,全局临时表就会持续)。
这有点痛苦,但与此同时,它将我的存储过程的执行时间从35分钟缩短到5分钟,我只需要在“生成包”步骤中担心这一点,所以我' d说这是值得的。