使用OpenRowSet

时间:2018-02-21 10:06:59

标签: sql-server tsql dynamic-sql openrowset

尝试执行包含OpenRowSet

的动态SQL时出现以下错误
  

返回链接服务器“(null)”的OLE DB提供程序“SQLNCLI10”   消息“延期准备无法完成。” Msg 8180,等级   16,国家1,第83行声明无法准备。消息137,   等级15,状态2,行84必须声明标量变量“@ P1”。

这是一个示例proc

    IF OBJECT_ID('dbo.usp_SomeProc') IS NULL
      EXEC ('CREATE PROCEDURE dbo.usp_SomeProc AS RETURN 0;');
    GO
    --DROP PROC dbo.usp_SomeProc
    ALTER PROCEDURE dbo.usp_SomeProc
        --Input Parameters
         @Param1    NVARCHAR(50)
        ,@Param2    INT
        ,@Param3    NVARCHAR(11)
    AS
    BEGIN
        SET NOCOUNT ON;

        SELECT Param1 = @Param1, Param2 = @Param2, Param3 = @Param3

        SET NOCOUNT OFF;

        RETURN 0;

    END;

    GO

这里用动态SQL执行proc - 这个工作

DECLARE @P1 NVARCHAR(50)='Some-Nonsense-Text'
, @P2 INT=98765, @P3 NVARCHAR(11)='Meaningless'
, @SQL NVARCHAR(MAX)
SET @SQL = 'EXEC dbo.usp_SomeProc    @Param1=@P1
                                    ,@Param2=@P2
                                    ,@Param3=@P3'
--PRINT @SQL
EXEC sys.sp_executesql @SQL, N'@P1 NVARCHAR(50), @P2 INT, @P3 NVARCHAR(11)', @P1, @P2, @P3 ; 
GO

执行不使用动态SQL的OpenRowSet语句

DECLARE @P1 NVARCHAR(50)='Some-Nonsense-Text', @P2 INT=98765, @P3 NVARCHAR(11)='Meaningless'
SELECT * 
INTO dbo.SomeProcTest
FROM OPENROWSET (   'SQLNCLI','Server=<server>\<instance?;Trusted_Connection=yes;'
,'EXEC xStuff.dbo.usp_SomeProc
 @Param1=''Some-Nonsense-Text''
,@Param2=98765
,@Param3=''Meaningless'''
                        )
SELECT * FROM dbo.SomeProcTest
DROP TABLE dbo.SomeProcTest
GO

使用动态SQL和OPENROWSET执行Proc失败并出现上述错误

DECLARE @ServerInstance NVARCHAR(200) = CAST(SERVERPROPERTY('MachineName') AS NVARCHAR(90))
    +'\' +CAST(SERVERPROPERTY('InstanceName') AS NVARCHAR(90)) ;
DECLARE @OpenRowSet NVARCHAR(MAX) ;
DECLARE @P1 NVARCHAR(50)='Some-Nonsense-Text', @P2 INT=98765, @P3 NVARCHAR(11)='Meaningless', @SQL NVARCHAR(MAX)


SET @SQL = 'EXEC xStuff.dbo.usp_SomeProc
                         @Param1=@P1
                        ,@Param2=@P2
                        ,@Param3=@P3'
--PRINT @SQL
SET @OpenRowSet = 
'
SELECT * 
INTO xStuff.dbo.SomeProcTest 
FROM OPENROWSET (   ''SQLNCLI''
                    ,''Server='+@ServerInstance +';Trusted_Connection=yes;''
                    ,'''+ @SQL +'''
                )' ;
--PRINT @OpenRowSet
EXEC sys.sp_executesql @OpenRowSet, N'@P1 NVARCHAR(50), @P2 INT, @P3 NVARCHAR(11)', @P1, @P2, @P3 ; 
SELECT * FROM xStuff.dbo.SomeProcTest
DROP TABLE xStuff.dbo.SomeProcTest
GO

我哪里错了?

1 个答案:

答案 0 :(得分:0)

使用此answer中的示例,我能够修改我的查询以使其正常工作

似乎你无法将变量传递给OPENROWSET,你需要像这样修改初始Query以使其工作

--Execute Proc with dynamic SQL and OPENROWSET
DECLARE @ServerInstance NVARCHAR(200) = CAST(SERVERPROPERTY('MachineName') AS NVARCHAR(90))
    +'\' +CAST(SERVERPROPERTY('InstanceName') AS NVARCHAR(90)) ;
DECLARE @OpenRowSet NVARCHAR(MAX) ;
DECLARE @P1 NVARCHAR(50)='Some-Nonsense-Text', @P2 INT=98765, @P3 NVARCHAR(11)='Meaningless', @SQL NVARCHAR(MAX)

SET @SQL = 'EXEC xStuff.dbo.usp_SomeProc
                         @Param1=''''' +@P1+ '''''
                        ,@Param2=' +CAST(@P2 AS NVARCHAR(20))+ '
                        ,@Param3=''''' +@P3+ ''''''
--PRINT @SQL

SET @OpenRowSet = 
'
SELECT * 
INTO xStuff.dbo.SomeProcTest 
FROM OPENROWSET (   ''SQLNCLI''
                    ,''Server='+@ServerInstance +';Trusted_Connection=yes;''
                    ,'''+ @SQL +'''
                )' ;
--PRINT @OpenRowSet
EXEC sys.sp_executesql @OpenRowSet ;--
SELECT * FROM xStuff.dbo.SomeProcTest
DROP TABLE xStuff.dbo.SomeProcTest
GO