web-dev-qa-db-ja.com

SQLストアドプロシージャと出力パラメーター

出力パラメーターを使用してストアード・プロシージャーを作成する方法を知っています。しかし、単純なSELECTステートメントを使用するだけでそれを使用する理由がわかりません。通常のストアドプロシージャは、グリッドで出力を返すことができます(以下の例を参照)。

SP出力パラメータなしでSP出力パラメータなしで使用できる実際の例を誰かに教えてもらえますか?

-- Using output parameter
SELECT @var = COUNT(*) FROM table1 WHERE gender = @gender...

-- Without output parameter
SELECT COUNT(*) FROM table WHERE gender = @gender...
6

ストアドプロシージャの出力パラメーターは、呼び出し元のT-SQLに値を返すのに役立ちます。呼び出し元のT-SQLは、その値を他のものに使用できます。

都市の入力を与えられた州を出力パラメーターとするストアドプロシージャがあるとします。

CREATE PROCEDURE [dbo].[GetStateFromCity] (@City NVARCHAR(30), @State NCHAR(2) OUTPUT)
AS
SELECT @State = [State]
FROM [ExampleTable] 
WHERE [City] = @City
GO;

この出力パラメーターを使用して、他の場所に値を渡すことができます。

例えば:

DECLARE @State int
EXEC [dbo].[GetStateFromCity] @City = 'Calgary', @State OUTPUT;

-- Do something with this value
SELECT @State;

-- Do something else
EXEC [dbo].[GetInsuranceCompanyByState] @State;

要約すると、クライアントアプリケーションの値を返すだけの場合は、おそらく出力パラメーターは必要ありません。

ただし、ストアドプロシージャ間でT-SQLの値を渡したい場合は、非常に便利です。

それだけの価値があるので、私は出力パラメーターをほとんど使用しません。

4
Randolph West

この質問がSQL Serverに関連すると仮定すると、それはコンテキストと効率に帰着します。

コンテキスト=アプリコード

アプリのコードからストアドプロシージャを実行する場合、コードの量はそれほど変わりません。結果セットを返すときは、ExecuteReaderを呼び出し、次にSqlDataReader.Read()を呼び出して1つの行を取得し、次にSqlDataReaderから列を取得します。ただし、単一の値を取得しているだけの場合は、ExecuteScalarのショートカットメソッドを使用して、行が1つでも(行がまだある場合でも)取得し、最初の列に値を返します(行がある場合でも)より多くの列です)。 OUTPUTパラメータを返すときは、ExecuteNonQueryを呼び出して、各パラメータの.Valueプロパティを確認し、適切な型にキャストするだけです。

したがって、単一の値を返す単純な例の観点から見ると、結果セットを返し、ExecuteScalarを呼び出すのが「最も簡単」のようです。しかし、ExecuteReaderまたはExecuteScalarを使用しているかどうかにかかわらず、結果セットを返すには、SQL Serverとクライアントアプリの両方のリソースがさらに必要です。 SQL Serverは結果セットをセットアップして管理する必要があります(つまり、メモリと時間を必要とします)。アプリはSqlDataReaderをインスタンス化し(ExecuteScalarを使用している場合でも)、それを管理する必要があります(つまりメモリと時間が必要です)。結果セットの行が1つしかないことが保証されている場合は、出力パラメーターを使用することをお勧めします(わずかであっても)。

コンテキスト= T-SQL

T-SQLからストアドプロシージャを実行する場合(および戻り値を使用する必要がある場合)、OUTPUTパラメータを使用する方が便利です。結果セットを返すことは使用可能ですが、INSERT ... EXECを使用して、結果をテーブル(通常はローカル一時テーブルまたはテーブル変数)に挿入する必要があります。ただし、その場合も行を選択してローカル変数に入れる必要があります。繰り返しになりますが、変数に値を配置する同じ場所にたどり着くには、より多くの時間とリソースが必要です。

これで、単一の値のみを返す場合(つまり、ExecuteScalarで機能する同じ状況)、timesを使用してスカラーを使用できます代わりにユーザー定義関数(UDF)。これは、クエリに配置できるため、(クエリでスカラーUDFを使用することでパフォーマンスが低下した場合でも)非常に便利です。ただし、UDFで実行できることには多くの制限があるため、一時テーブルを作成したり、DMLやDDLなどを実行したりする必要がある場合は、ストアドプロシージャを使用するしか選択肢がありません。


「結果セットとOUTPUTパラメータ」の質問の一部ではありませんが、あなたが両方できることを覚えておいてください。控えめな値と返すデータのセットがある場合、ストアドプロシージャは両方を返すことを許可しますが、まれに非常に役立ちます。

4
Solomon Rutzky

注目に値する他の2つのこと:

1)OUTPUTとして複数のパラメーターを渡すことができます。

2)結果が必要ない場合は、OUTPUTを使用してパラメーターを呼び出す必要はありません。

CREATE PROCEDURE ManyOutputs @a int, @b int output, @c varchar(100) output, @d bit output
AS
BEGIN
    SET @b = @a + 11
    SET @c = 'The Value of A is ' + CAST(@a AS varchar(5)) + ', and the value of B is ' + CAST(@b AS varchar(5))
    IF (@a % 2 = 1)
        SET @d = 1
    ELSE
        SET @d = 0
END
GO

このルーチンを呼び出す:

DECLARE @bVal int
DECLARE @cVal varchar(100)
DECLARE @dVal bit

EXEC ManyOutputs 1, @bVal, @cVal, @dVal
SELECT @bVal AS bVal, @cVal as cVal, @dVal as dVal

NULL、NULL、NULLを返します

EXEC ManyOutputs 2, @bVal OUT, @cVal OUT, @dVal OUT
SELECT @bVal AS bVal, @cVal as cVal, @dVal as dVal

13、「Aの値は2、Bの値は13」、0を返します

EXEC ManyOutputs 3, @bVal, @cVal, @dVal
SELECT @bVal AS bVal, @cVal as cVal, @dVal as dVal

13、「Aの値は2、Bの値は13」、0を返します

(前回の呼び出しと同じです。OUTPUTを使用して新しい値を取得しなかったため、古い値が保持されていました。)

EXEC ManyOutputs 5, @bVal OUT, @cVal OUT, @dVal OUT
SELECT @bVal AS bVal, @cVal as cVal, @dVal as dVal

16、「Aの値は5、Bの値は16」、1を返します

3
Dan