如何为存储过程(SQL Server)调用的存储过程提供参数值?

时间:2016-06-08 18:41:37

标签: sql-server tsql stored-procedures query-parameters

基于答案here,我已经开始测试SP,我计划最终建立多次调用,具有更多的临时表和不同的值#34;单元"参数。但是@BegDate,@ EndDate和@SortBy参数总是相同的 - 用户提供的那些。

这是我到目前为止所做的:

IF OBJECT_ID ( 'testSP', 'P' ) IS NOT NULL   
    DROP PROCEDURE testSP;  
GO
CREATE PROC [dbo].[testSP]
    @BegDate datetime,
    @EndDate datetime,
    @SortBy varchar(20)
AS
BEGIN
    SELECT * FROM sys.databases
END
GO
sp_configure 'Show Advanced Options', 1
GO
RECONFIGURE
GO
sp_configure 'Ad Hoc Distributed Queries', 1
GO
RECONFIGURE
GO

SELECT * INTO #MyTempTable FROM OPENROWSET('SQLNCLI', 'Server=(local)\SQL2008;Trusted_Connection=yes;',
     'EXEC SP2BCalled @Unit = "FirstUnit"; @BegDate = @BegDate;  @EndDate = @EndDate; @SortBy = @SortBy; ')

SELECT * FROM #MyTempTable

我的问题:这是将params传递给现有存储过程(SP2BCalled)的正确方法:

'EXEC SP2BCalled @Unit = "Abuelos"; @BegDate = @BegDate;  @EndDate = @EndDate; @SortBy = @SortBy; ')

IOW,被调用的SP需要将@BegDate,@ EndDate和@SortBy参数传递给它,所以新的SP会收集那些要传递的参数,但这样做的正确语法是什么?

我应该这样做:

CREATE PROC [dbo].[testSP]
    @BegDateLocal datetime,
    @EndDateLocal datetime,
    @SortByLocal varchar(20)

...然后像这样调用现有的SP:

SELECT * INTO #MyTempTable1 FROM OPENROWSET('SQLNCLI', 'Server=(local)\SQL2008;Trusted_Connection=yes;',
     'EXEC SP2BCalled @Unit = "FirstUnit"; @BegDate = @BegDateLocal;  @EndDate = @EndDateLocal; @SortBy = @SortByLocal; ')

SELECT * INTO #MyTempTable2 FROM OPENROWSET('SQLNCLI', 'Server=(local)\SQL2008;Trusted_Connection=yes;',
     'EXEC SP2BCalled @Unit = "SecondUnit"; @BegDate = @BegDateLocal;  @EndDate = @EndDateLocal; @SortBy = @SortByLocal; ')

SELECT * INTO #MyTempTable3 FROM OPENROWSET('SQLNCLI', 'Server=(local)\SQL2008;Trusted_Connection=yes;',
     'EXEC SP2BCalled @Unit = "ThirdUnit"; @BegDate = @BegDateLocal;  @EndDate = @EndDateLocal; @SortBy = @SortByLocal; ')

......?或者怎么样?

然后我将需要UNION所有临时表(#MyTempTable1,#MyTempTable2和#MinTempTable3)并将其作为最终结果返回。

更新

海因里希斯密特是对的;当我试图运行testSP时,我得到了:

配置选项'显示高级选项'从0更改为1.运行RECONFIGURE语句进行安装。 配置选项' Ad Hoc Distributed Queries'从0更改为1.运行RECONFIGURE语句进行安装。 OLE DB提供程序" SQLNCLI11"对于链接服务器"(null)"返回消息"登录超时已过期"。 OLE DB提供程序" SQLNCLI11"对于链接服务器"(null)"返回消息"建立与SQL Server的连接时发生了与网络相关或特定于实例的错误。找不到服务器或无法访问服务器。检查实例名称是否正确以及SQL Server是否配置为允许远程连接。有关详细信息,请参阅SQL Server联机丛书。"。

4 个答案:

答案 0 :(得分:3)

本地参数是否与要调用的过程的参数同名并不重要。所以你要求这两种方式没有区别。

重要的是你不应该用分号分隔参数。你应该使用逗号。

'EXEC SP2BCalled @Unit = ''FirstUnit'', @BegDate = @BegDateLocal,  @EndDate = @EndDateLocal, @SortBy = @SortByLocal, ')

答案 1 :(得分:1)

据我所知,你赢了'能够直接将参数传递给OPENROWSET调用。您需要创建一个动态SQL字符串并执行它,例如

DECLARE @SQL VARCHAR(MAX)
SET @SQL = 'SELECT * FROM OPENROWSET(''SQLNCLI'', ''DRIVER={SQL Server}; Server=127.0.0.1;'',''EXEC [Test].[dbo].[Test] @var1 = ' + @var1 + ''')'
EXEC(@SQL)

另外,根据提供的代码,

SELECT * INTO #MyTempTable FROM OPENROWSET(..

部分永远不会作为存储过程的一部分运行,因为有多个GO结束了定义。

您也没有指定要在OPENROWSET中使用的数据库。

是否有使用OPENROWSET的具体原因,而不是使用链接服务器的FQDN,[server].[database].[schema].[table]

答案 2 :(得分:1)

如果您知道返回的数据集的结构是什么,那么您可以使用以下内容:

--  Making assumptions about the data set
CREATE TABLE #MyTempTable1
 (
   Col1    int            not null
  ,Col2    datetime       not null
  ,ColEtc  nvarchar(max)  not null
 )

INSERT #MyTempTable1 (Col1, Col2, ColEtc)
 EXECUTE SP2BCalled
   @Unit    = 'Abuelos'
  ,@BegDate = @BegDate
  ,@EndDate = @EndDate
  ,@SortBy  = @SortBy

答案 3 :(得分:1)

OPENROWSET只接受文字字符串。要使用它,您需要在动态SQL中构建整个命令,然后exec该命令。

exec内创建的临时表仅存在于exec的范围内 - 它们在返回时会消失。

您可以使用全局临时表## MyTempTable1等,但如果多个用户同时调用它,它们将全部写入相同的全局临时表。
NEWID技巧使得一个独特的全局临时表可以避免这种情况,但是更难以管理。

使用双引号"仅在远程服务器上SET QUOTED_IDENTIFIER为OFF时有效。如果它为ON,则双引号中的任何内容都不会被视为字符串。 相反,它被视为对象名称,如列或表。 为避免担心这一点,请使用一对单引号''来表示字符串中的单引号。但是,以这种方式处理嵌套引号确实令人难以置信。

您只需要将远程服务器配置为接受ad-hoc分布式查询一次,这样您就可以预先执行,而不是每次调用。

stackoverflow是持有远程存储过程的数据库的名称。只需替换正确的名称即可。

Declare @Unit varchar(max) = 'FirstUnit', @BegDateLocal datetime = '01-jun-2016', @EndDateLocal datetime = '30-jun-2016', @SortBy varchar(max) = 'X'
Declare @sql nvarchar(max)
Declare @exec nvarchar(max) = 'EXEC stackoverflow.dbo.SP2BCalled @Unit = ''''FirstUnit'''', @BegDate = ''''' + convert(varchar(max), @BegDateLocal, 120) + ''''''
     + ', @EndDate = ''''' + convert(varchar(max), @EndDateLocal, 120) + ''''''
     + ', @SortBy = ''''' + @SortBy + ''''''
Declare @GlobalTemp varchar(max) = '##MyTempTable1'
Declare @GlobalTempNEWID varchar(max) = '[##' + cast(newid() as char(36)) + ']'
Declare @DropCheck varchar(max) = 'IF object_id(''tempdb..' + @GlobalTemp + ''') is not null drop table ' + @GlobalTemp
Set @sql = @DropCheck + '; SELECT * INTO ' + @GlobalTemp 
            + 'FROM OPENROWSET(
               ''SQLNCLI'',
               ''Server=(local)\SQL2008;Trusted_Connection=yes;'',' 
               + '''' + @exec + ''')'

Print @sql
exec (@sql)
SELECT * FROM ##MyTempTable1