複数のテーブルに値を挿入するため、大量の入力および出力パラメーターを持つストアドプロシージャがあります。場合によっては、ストアドプロシージャは単一のテーブルにのみ挿入します(入力パラメーターによって異なります)。これは、説明するための模擬シナリオです。
テーブル/データオブジェクト:
人
Id
Name
Address
名前
Id
FirstName
LastName
アドレス
Id
Country
City
人を挿入するストアドプロシージャがあるとします。アドレスが存在しない場合、データベースのAddress
テーブルに追加しません。
したがって、ストアドプロシージャを呼び出すコードを生成するときに、Address
パラメーターを追加する必要はありません。 SQL Serverではデフォルト値を指定できるため、INPUT
パラメーターの場合は問題ありません。しかし、OUTPUT
パラメータについては、ストアドプロシージャでオプションにして、エラーを受け取らないようにするにはどうすればよいですか...
プロシージャまたは関数「Person_InsertPerson」では、指定されていないパラメータ「@AddressId」が必要です。
入力パラメータと出力パラメータの両方にデフォルトを割り当てることができます。この例では:
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
出力パラメーターとデフォルト値はうまく機能しません!これは、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から始めます。
私見この機能の組み合わせは、コードの匂い(フェー!!)
次のようなOUTPUT
パラメーターにデフォルト値を追加できるように見えます:
@AddressId int = -1 Output
AddressId
は厳密にOUTPUT
変数として意図されているため、可読性の点で貧弱なようです。しかし、それは機能します。より良い解決策があれば教えてください。
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
_値を返します。
フィリップが言ったことに加えて:
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)