动态SQL:使用@param和INSERT插入@Table的OPENROWSET

时间:2019-06-25 11:38:17

标签: sql-server tsql sql-server-2012 dynamic-sql openrowset

我正在尝试使用@tableOPENROWSET循环插入@param参数。我改编自This Answer的代码,该代码演示了如何使用Dynamic SQL插入参数。

代码:

DECLARE @BuildTimes TABLE (
    BuildTableName VARCHAR(max) NULL
    ,BuildDate DATE NULL
)

DECLARE @days INT = 0;
DECLARE @startDate DATE = GETDATE();
DECLARE @buildDate DATE = GETDATE();
DECLARE @sql nvarchar(max);

WHILE (@days <=30)
BEGIN
    SET @buildDate = DATEADD(day, -1*@days, @startDate);
    SET @sql='INSERT INTO @BuildTimes
        SELECT * 
        FROM OPENROWSET(
                       ''SQLNCLI'',
                       ''SERVER=localhost;Trusted_Connection=yes;'',
                       ''EXEC [LOG].[BuildTimes] @buildDate = ''''' + CAST(@buildDate AS VARCHAR) +''''''')'

    PRINT @sql
    EXEC(@sql)
    SET @days = @days + 1
END

SELECT * FROM @BuildTimes

错误:

Msg 1087, Level 15, State 2, Line 9
Must declare the table variable "@BuildTimes"

我尝试将OPENROWSET作为不带参数的非动态SQL运行,并且一切正常。我在做什么错了?

3 个答案:

答案 0 :(得分:2)

在动态SQL中无法访问您的变量表@BuildTimes。即使您声明了它并用动态SQL加载了它,您也将无法读取超出动态范围的结果。

一种解决方案是使用临时表而不是变量表:

IF OBJECT_ID('tempdb..#BuildTimes') IS NOT NULL
    DROP TABLE #BuildTimes

CREATE TABLE #BuildTimes (
    BuildTableName VARCHAR(max) NULL
    ,BuildDate DATE NULL
)

DECLARE @days INT = 0;
DECLARE @startDate DATE = GETDATE();
DECLARE @buildDate DATE = GETDATE();
DECLARE @sql nvarchar(max);

WHILE (@days <=30)
BEGIN
    SET @buildDate = DATEADD(day, -1*@days, @startDate);
    SET @sql='INSERT INTO #BuildTimes
        SELECT * 
        FROM OPENROWSET(
                       ''SQLNCLI'',
                       ''SERVER=localhost;Trusted_Connection=yes;'',
                       ''EXEC [LOG].[BuildTimes] @buildDate = ''''' + CAST(@buildDate AS VARCHAR) +''''''')'

    PRINT @sql
    EXEC(@sql)
    SET @days = @days + 1
END

SELECT * FROM #BuildTimes

该表可以在EXEC外部读取,因为它是在外部创建的,并且可以在内部访问,因为它保留在同一会话中。

作为旁注,请避免在希望使用一组已知列的情况下使用*,这样,如果在SELECT的基础表上添加了新列,则INSERT不会破裂。

答案 1 :(得分:1)

为什么要完全使用动态SQL,而不仅仅是使用18.01-0.7

8-0.7

答案 2 :(得分:0)

我发现在这种情况下我根本不需要Dynamic SQL / OPENROWSET。以下代码可产生所需的结果:

DECLARE @BuildTimes TABLE (
    BaseTableName VARCHAR(max) NULL
    ,BuildDate DATE NULL
    ,StartDateTime DATETIME NULL
    ,FinishDateTime DATETIME NULL
    ,TimeTakenMinutes BIGINT NULL
)

DECLARE @days INT = 0;
DECLARE @startDate DATE = GETDATE();
DECLARE @thisBuildDate DATE = GETDATE();

WHILE (@days <=30)
BEGIN
    SET @thisBuildDate = DATEADD(day, -1*@days, @startDate);
    PRINT @thisBuildDate

    INSERT INTO @BuildTimes
    EXEC [LOG].[BuildTimes] @buildDate = @thisBuildDate
    SET @days = @days + 1
END

SELECT * FROM @BuildTimes
GO