4

大多数人都知道,只要将带有临时表的存储过程用作 OleDbSource,SSIS 就很难读取元数据。以前,这可以通过添加 SET FMTONLY OFF 来轻松防止;在执行语句之前。这样做的缺点是存储过程在验证期间被执行,这可能需要一段时间。从 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。

提前致谢!

马文

4

2 回答 2

1

我自己以前也遇到过这些问题。我使用了这里描述的解决方案。最初的答案不是关于使用 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
    )
)
于 2017-02-01T14:05:58.373 回答
0

我在当前的 Biml 项目中遇到了类似的问题。就像您提到的那样,问题似乎是 Biml 没有考虑存储过程中的临时表生成。

我的解决方案(解决方法?)是首先使它们成为全局临时表,而不仅仅是临时表。然后,我创建了一个新的存储过程,它运行与我的主存储过程相同的代码来处理临时表的创建。在 Biml 中运行“生成包”之前,我在 SSMS 中打开了一个新的查询窗口,运行该存储过程并保持该窗口打开(只要会话或本例查询窗口打开,全局临时表就会持续存在)。

这有点痛苦,但同时,它把我的存储过程的执行时间从 35 分钟缩短到了 5 分钟,我只需要在“生成包”步骤中担心这个,所以我会这么说是值得的。

于 2017-01-27T21:52:29.997 回答