2010-07-16 71 views
57

我有一個存儲過程有一堆輸入和輸出參數,因爲它是插入值到多個表。在某些情況下,存儲的proc只能插入一個表(取決於輸入參數)。這是一個模擬的場景來說明。我可以在存儲過程中使用可選的OUTPUT參數嗎?

表/數據對象:

Id 
Name 
Address 

名稱

Id 
FirstName 
LastName 

地址

Id 
Country 
City 

說我有一個插入一個人的存儲過程。如果地址不存在,我不會將其添加到數據庫中的Address表中。

因此,當我生成調用存儲過程的代碼時,我不想打擾添加Address參數。對於INPUT參數,這是可以的,因爲SQL Server允許我提供默認值。但對於OUTPUT參數我該怎麼辦,在存儲過程,使其可選的,所以我沒有收到錯誤...

過程或函數「Person_InsertPerson」預計參數 「@AddressId」,這是不提供。

+0

什麼是你的代碼是什麼樣子?也就是說,你在分支地址是否存在地址。我懷疑我的問題,一旦看到那個分支,就會說:「爲什麼在地址不存在時爲'@ AddressId'傳遞的任何內容都用'NULL'調用sproc,*不使用分支? – ruffin 2017-10-18 17:19:38

回答

90

輸入和輸出參數都可以分配爲默認值。在這個例子中:

CREATE PROCEDURE MyTest 
    @Data1 int 
,@Data2 int = 0 
,@Data3 int = null output 

AS 

PRINT @Data1 
PRINT @Data2 
PRINT isnull(@Data3, -1) 

SET @Data3 = @Data3 + 1 

RETURN 0 

第一放慢參數是必須的,而第二和第三個是可選的 - 如果不是通過調用程序設置,他們將被分配默認值。嘗試使用不同的值和設置來解決SSMS中的以下測試調用例程,以瞭解它們如何一起工作。

DECLARE @Output int 

SET @Output = 3 

EXECUTE MyTest 
    @Data1 = 1 
,@Data2 = 2 
,@Data3 = @Output output 

PRINT '---------' 
PRINT @Output 
+2

謝謝!我想知道爲什麼我不能使用'@var INT OUTPUT = NULL' - 語法很混亂。 – trojjer 2016-04-08 13:40:24

+0

並沒有真正調用默認值(你設置了@output),只有當你不傳遞任何東西時才激活默認值,請參閱我的答案以獲得完整的處理。 – 2016-09-01 17:48:06

1

既然你執行一個存儲過程,而不是一個SQL語句,你有你的SQL命令的命令類型設置爲存儲過程:

cmd.CommandType = CommandType.StoredProcedure; 

here服用。另外,一旦你刪除了這個錯誤,你可以在你的過程中使用SQL的nvl()函數來指定當遇到NULL值時你想要顯示的內容。

對不起,沒有妥善解決這個問題......一定是誤解了你。這裏有一個nvl的例子,我認爲它可能會更好一點?

select NVL(supplier_city, 'n/a') 
from suppliers; 

上面的SQL語句將返回 'N/A',如果supplier_city領域包含空值。否則,它將返回supplier_city值。

+0

這並沒有回答這個問題。 我正在使用企業庫的db.GetStoredProcCommand這將爲我做到這一點。我已經用這種方式調用了很多存儲過程,並且它們工作得很好。 例如。代碼調用StoredProc 使用(DbCommand insertPersonCommand = db2ExecuteNonQuery(insertPersonCommand,dbTransaction); – Justin 2010-07-16 17:58:10

+0

對不起隊友。我編輯是一個更相關的一點。 – rownage 2010-07-16 18:05:35

4

看起來像我可以再補充一個默認值到OUTPUT參數如:

@AddressId int = -1 Output 

看起來似乎在自AddressId可讀性方面較差嚴格意爲OUTPUT變量。但它的工作。請讓我知道你是否有更好的解決方案。

+0

這有缺陷,請參閱我的完整治療答案。 – 2016-09-01 17:48:45

1

添加到什麼菲利普說:

我在我的SQL Server數據庫的存儲過程,看起來像下面這樣:

dbo.<storedProcedure> 
(@current_user char(8) = NULL, 
@current_phase char(3) OUTPUT) 

我也從我的.NET調用它代碼如下:

DataTable dt = SqlClient.ExecuteDataTable(<connectionString>, <storedProcedure>); 

我得到一個System.Data.SqlClient.SqlException:過程或函數n期望參數'@current_phase',它沒有被提供。

我也在我的程序中的其他地方使用這個函數,並傳入參數並處理輸出。因此,我不必修改正在進行的當前調用,我只是更改存儲過程以使輸出參數也是可選的。

所以現在看起來如下所示:

dbo.<storedProcedure> 
(@current_user char(8) = NULL, 
@current_phase char(3) = NULL OUTPUT) 
7

輸出參數和默認值不很好地協同工作!這來自SQL 10.50.1617(2008 R2)。 不要被愚弄認爲這個構造神奇地代表了你的價值SET(就像我的同事一樣)!

此「玩具」SP詢問OUTPUT參數值,無論是默認值還是NULL

CREATE PROCEDURE [dbo].[omgwtf] (@Qty INT, @QtyRetrieved INT = 0 OUTPUT) 
AS 
IF @QtyRetrieved = 0 
BEGIN 
    print 'yay its zero' 
END 
IF @QtyRetrieved is null 
BEGIN 
    print 'wtf its NULL' 
END 
RETURN 

如果您在爲OUTPUT未初始化值(即NULL)發送,你真的得到了NULL的SP內部,而不是0。有道理,某些參數已經通過了。

declare @QR int 
exec [dbo].[omgwtf] 1, @QR output 
print '@QR=' + coalesce(convert(varchar, @QR),'NULL') 

輸出爲:

wtf its NULL 
@QR=NULL 

如果我們從主叫方增加一個顯SET我們得到:

declare @QR int 
set @QR = 999 
exec [dbo].[omgwtf] 1, @QR output 
print '@QR=' + coalesce(convert(varchar, @QR),'NULL') 

和(令人驚奇的)輸出:

@QR=999 

再次,有道理,一個參數被傳遞,並且SP沒有采取任何明確的行動給SET一個值。

在SP添加SETOUTPUT參數(就像你應該做的),但是沒有設置從主叫什麼:執行時

ALTER PROCEDURE [dbo].[omgwtf] (@Qty INT, @QtyRetrieved INT = 0 OUTPUT) 
AS 
IF @QtyRetrieved = 0 
BEGIN 
    print 'yay its zero' 
END 
IF @QtyRetrieved is null 
BEGIN 
    print 'wtf its NULL' 
END 
SET @QtyRetrieved = @Qty 
RETURN 

現在:

declare @QR int 
exec [dbo].[omgwtf] 1234, @QR output 
print '@QR=' + coalesce(convert(varchar, @QR),'NULL') 

的輸出是:

wtf its NULL 
@QR=1234 

這是的「標準」行爲SP中的參數處理。

現在的的情節:獲得默認值設置爲「激活」的唯一辦法,就是不能通過在所有OUTPUT參數,恕我直言,沒有什麼意義:因爲它的成立爲OUTPUT參數,這意味着要返回應該收集的「重要」內容。

declare @QR int 
exec [dbo].[omgwtf] 1 
print '@QR=' + coalesce(convert(varchar, @QR),'NULL') 

給出了這樣的輸出:

yay its zero 
@QR=NULL 

但這沒能把握住SP的輸出,即SP開始與可能的目的。

恕我直言,這個功能組合貌合神離構建我會考慮代碼味道(唷!)

+0

使用'OUTPUT'參數進行輸入,優於簡潔(包括重複使用可能調用此和其他sprocs的代碼中的變量)的優點?爲什麼不將這些輸入值作爲「常規」參數傳遞? – ruffin 2017-10-18 17:12:26

+1

@ruffin沒有優勢;可選的OUTPUT參數不能像所有人都期望的那樣工作,這就是爲什麼我建立了這個答案。 – 2017-10-19 11:18:54

+0

+1。我想補充一點,這意味着通過「OUTPUT」參數傳遞值應該被認爲是一個糟糕的主意,原因有兩個:1.意識形態/代碼的氣味,以及2.你的行爲的實際原因在這裏找到。 ¯\\ _(ツ)_ /¯ – ruffin 2017-10-19 13:53:14

相關問題