web-dev-qa-db-ja.com

ストアドプロシージャにオプションのOUTPUTパラメーターを使用できますか?

複数のテーブルに値を挿入するため、大量の入力および出力パラメーターを持つストアドプロシージャがあります。場合によっては、ストアドプロシージャは単一のテーブルにのみ挿入します(入力パラメーターによって異なります)。これは、説明するための模擬シナリオです。

テーブル/データオブジェクト:

Id
Name
Address

名前

Id
FirstName
LastName

アドレス

Id
Country
City

人を挿入するストアドプロシージャがあるとします。アドレスが存在しない場合、データベースのAddressテーブルに追加しません。

したがって、ストアドプロシージャを呼び出すコードを生成するときに、Addressパラメーターを追加する必要はありません。 SQL Serverではデフォルト値を指定できるため、INPUTパラメーターの場合は問題ありません。しかし、OUTPUTパラメータについては、ストアドプロシージャでオプションにして、エラーを受け取らないようにするにはどうすればよいですか...

プロシージャまたは関数「Person_InsertPerson」では、指定されていないパラメータ「@AddressId」が必要です。

69
Justin

入力パラメータと出力パラメータの両方にデフォルトを割り当てることができます。この例では:

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

最初のパラメーターは必須であり、2番目と3番目はオプションです。呼び出しルーチンによって設定されていない場合、デフォルト値が割り当てられます。さまざまな値と設定を使用して、SSMSの次のテスト呼び出しルーチンを試してみて、すべてがどのように連携するかを確認してください。

DECLARE @Output int

SET @Output = 3

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

PRINT '---------'
PRINT @Output
107
Philip Kelley

出力パラメーターとデフォルト値はうまく機能しません!これは、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

NULLに対して初期化されていない値(つまり、OUTPUT)を送信すると、0ではなく、SP内でNULLを取得しました。理にかなっています、そのパラメーターに何かが渡されました。

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に対して明示的なアクションを実行しませんでした。

SETパラメーターのOUTPUTをSP(想定どおり))に追加しますが、呼び出し元からは何も設定しないでください。

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パラメータを渡さないです。 OUTPUTパラメータとして設定されているため、収集する必要がある「重要な」何かを返すことを意味します。

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

この出力を与えます:

yay its zero
@QR=NULL

しかし、これはSPの出力のキャプチャに失敗します。おそらくその目的はSPから始めます。

私見この機能の組み合わせは、コードの匂い(フェー!!)

13
escape-llc

次のようなOUTPUTパラメーターにデフォルト値を追加できるように見えます:

@AddressId int = -1 Output

AddressIdは厳密にOUTPUT変数として意図されているため、可読性の点で貧弱なようです。しかし、それは機能します。より良い解決策があれば教えてください。

4
Justin

SQLステートメントではなくストアドプロシージャを実行しているため、SQLコマンドのコマンドタイプをストアドプロシージャに設定する必要があります。

_cmd.CommandType = CommandType.StoredProcedure;
_

here から取得。

また、エラーを削除したら、プロシージャでSQLのnvl()関数を使用して、NULL値が検出されたときに表示するものを指定できます。

質問に適切に対処していないことをごめんなさい...あなたが誤解している必要があります。ここにnvlの例がありますが、それはもう少し良く対処できると思いますか?

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

_supplier_city_フィールドにヌル値が含まれている場合、上記のSQLステートメントは「n/a」を返します。それ以外の場合は、_supplier_city_値を返します。

1
rownage

フィリップが言ったことに加えて:

Sqlサーバーデータベースに次のようなストアドプロシージャがありました。

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

そして、次のように私の.netコードからそれを呼び出していました:

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

System.Data.SqlClient.SqlExceptionを取得していました:プロシージャまたは関数はパラメーター '@current_phase'を必要としますが、指定されていません。

また、プログラムのどこかでこの関数を使用し、パラメーターを渡し、出力パラメーターを処理しています。現在の呼び出しを変更する必要がなかったので、ストアドプロシージャを変更して、出力パラメーターもオプションにしました。

そのため、次のようになります。

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