簡體   English   中英

如何為由存儲過程(SQL Server)調用的存儲過程提供參數值?

[英]How can I provide parameter values to a Stored Proc called by a Stored Proc (SQL Server)?

根據此處的答案,我開始嘗試測試SP,最終計划將其構建為多次調用,其中包含更多臨時表和“ Unit”參數的不同值。 盡管@ 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

我的問題:這是將參數傳遞給現有存儲過程(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; ')

...?,或如何?

然后,我將需要合並所有臨時表(#MyTempTable1,#MyTempTable2和#MyTempTable3),並將其作為最終結果返回。

更新

Heinrich Smit是正確的; 當我嘗試運行testSP時,我得到了:

配置選項“顯示高級選項”從0更改為1。運行RECONFIGURE語句進行安裝。 配置選項“臨時分布式查詢”從0更改為1。運行RECONFIGURE語句進行安裝。 鏈接服務器“(null)”的OLE DB訪問接口“ SQLNCLI11”返回消息“登錄超時已過期”。 鏈接服務器“(null)”的OLE DB提供程序“ SQLNCLI11”返回消息“建立與SQL Server的連接時發生了與網絡相關或特定於實例的錯誤。找不到或無法訪問服務器。檢查實例名稱是否正確以及是否將SQL Server配置為允許遠程連接。有關更多信息,請參見SQL Server聯機叢書。

本地參數是否與要調用的過程的參數同名無關緊要。 因此,您詢問這樣做的兩種方式之間沒有區別。

重要的是您不應使用分號分隔參數。 您應該使用逗號。

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

據我所知,您將能夠直接將參數傳遞給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(..

part永遠不會作為存儲過程的一部分運行,因為有多個GO結束了定義。

您也沒有指定要在OPENROWSET使用的數據庫。

是否有使用OPENROWSET而不是使用鏈接服務器[server].[database].[schema].[table]的FQDN的特定原因?

如果您知道要返回的數據集的結構是什么,則可以使用如下所示的內容:

--  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

OPENROWSET僅接受文字字符串。 要使用它,您需要在動態SQL中構建整個命令,然后exec該命令。

內部創建臨時表的exec只存在於范圍exec -它們會消失,當它返回。

您可以使用全局臨時表## MyTempTable1等,但是如果多個用戶同時調用此函數,則他們都將寫入同一全局臨時表。
NEWID技巧制作了一個唯一的全局臨時表來避免這種情況,但是更難管理。

只有在遠程服務器上的SET QUOTED_IDENTIFIER為OFF時,才使用雙引號" 。如果為ON,則雙引號中的任何內容都不會被視為字符串。而是將其視為對象名稱,例如列或表。為避免對此擔心,請使用一對單引號''來表示字符串中的單引號。但是,以這種方式處理嵌套引號確實令人費解。

您只需將遠程服務器配置為一次接受即席分布式查詢,因此您可以預先進行此操作,而不必在每次調用時進行。

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM