web-dev-qa-db-ja.com

SQL Server出力パラメーターの問題

SQL Server 2008 Enterpriseを使用しています。 SQL ServerストアドプロシージャのOUTPUTパラメーターを学習しています。たとえば、ストアドプロシージャsp_add_jobscheduleには、schedule_idというOUTPUTパラメーターがあります。

http://msdn.Microsoft.com/en-us/library/ms366342.aspx

私の混乱は、OUTPUTパラメーターに入力値を提供し、値を返すように見えることです。INPUTパラメーターとOUTPUTパラメーターの両方の動作があるように見えますか? (純粋な出力パラメーターの動作のように見せるために)OUTPUTパラメーターにINPUT値を提供しないことは許可されていますか?

32
George2

混乱はある程度正当化されます-Oracleなどの他のRDBMSには、IN(入力のみ)、OUT(出力のみ)、またはINOUT(両方の方法-「参照渡し」タイプのパラメーター)。

SQL ServerはパラメーターをOUTPUTとラベル付けするため、ここでは少しずさんですが、実際には、これはINPUT/OUTPUTを意味します-基本的には、ストアドプロシージャにチャンスがあることを意味しますそのパラメータでの呼び出しから値を返す。

はい-OUTPUTパラメーターと呼ばれていますが、実際にはINPUT/OUTPUTパラメーターと、それらのININOUT 、OracleのようなOUTは、SQL Server(T-SQL)には存在しません。

60
marc_s

出力パラメーターを使用してストアドプロシージャを作成する方法の簡単な例を示します。

CREATE PROCEDURE test_proc

@intInput int,
@intOutput int OUTPUT

AS
set @intOutput = @intInput + 1 

go

このプロシージャを呼び出して出力パラメータを使用するには、次のようにします。

declare @intResult int
exec test_proc 3 ,@intResult OUT
select @intResult

Ouput変数を最初に宣言する必要があることがわかります。ストアドプロシージャを実行すると、出力値が変数に格納されます。出力変数には任意の値を設定できますが、ストアドプロシージャを実行すると、出力変数にどの値が含まれていても、返されるストアドプロシージャが正確に含まれます。

例えば:

declare @intResult int
exec test_proc 3 ,@intResult OUT
select @intResult

4を返します。

declare @intResult int
set @intResult = 8
exec test_proc 3 ,@intResult OUT
select @intResult

4も返します。

19
Sergey Olontsev

はい、値の受け渡しと取得の両方にOUTPUTパラメーターを使用できます(現時点では、それを行う正当な理由は考えられませんが)。

これを示す簡単な例を次に示します。

-- The stored procedure
CREATE PROCEDURE OutParamExample
    @pNum int OUTPUT
AS
BEGIN
    select @pNum
    set @pNum = @pNum + 5
END
GO

-- use a local variable to retrieve your output param value
declare @TheNumber int
set @TheNumber = 10

print @TheNumber
exec OutParamExample @TheNumber OUTPUT
print @TheNumber

結果は次のようになります。

10

-----------
10

(1 row(s) affected)

15

編集: OK、2番目の段落で「not」を逃し、あなたが尋ねた質問に答えていない可能性があると思います。厳密な出力パラメーター(戻りコードなど)が必要な場合、次のように渡されるローカル変数にvalueを指定する必要はありません。出力パラメータですが、プロシージャ自体のスコープ外で返された値にアクセスできるように、ローカル変数を宣言する必要があります。

例えば:

declare @LocalNumber int
-- I don't have to assign a value to @LocalNumber to pass it as a parameter
exex OutParamExample @LocalNumber OUTPUT  
-- (assume SP has been altered to assign some reasonable value)

-- but I do have to declare it as a local variable so I can get to
-- the return value after the stored procedure has been called
print @LocalNumber
6
Matt

上記で他の人が言ったことにさらに加えて、OUTPUTパラメーターはINPUTとOUTPUTとして機能できます。ただし、渡された値を使用するのはストアドプロシージャに依存します。

ストアドプロシージャがOUTPUTパラメータに渡された値を無視する場合(通常はそうする必要があります)、とにかくINPUT値は無視されます。

Sergeyのコードを使用して、@ intOutputに渡されたユーザー値を使用できます(必要な場合)

create PROCEDURE test_proc

@intInput int,
@intOutput int OUTPUT

AS
set @intOutput = @intOutput + 1 

go

しかし、それはOUTPUTパラメーターの目的に反します。
別のビューを表示するために、c#コンパイラーは、出力パラメーターを使用せずに、割り当てによってoutパラメーターの値を強制的に上書きします。

例えば私はC#でこれを行うことはできません。ここでは、出力パラメーターとしてのみ機能します(つまり、ユーザーがこの関数に渡した値を無視します)

static void dosomething(out int i)
{
    //i = 0;
    i = i + 1;
}
3
shahkalpesh

質問は-理由入力の提供を禁止しますか?これはまったく意味がありません。この簡単な例を考えてみましょう。

CREATE PROCEDURE test (@param AS INT OUTPUT) AS
BEGIN
  SET @param = 100
END
GO

DECLARE @i INT
SET @i = 0

EXECUTE test @i OUTPUT
PRINT @i

DROP PROCEDURE test

これは印刷します

100

参照-変数を最初に入れない場合out値を取得する方法in最初に?

2
Tomalak

プログラミング言語の参照によって渡される出力パラメーターについて考えてみましょう、それは同じです。私が今考えることができる最良の例は、エラーコードを返すことです。いくつかの挿入が必要です... SPからリターンコードを選択した場合、それをコード内にフェッチする必要があります。OUTPUTパラメータを持たない場合は、すでにパラメータ内にあります(つまり、 C#コマンド、PHP init stored procメソッド、または文字列を作成する場合とは異なる何か)

2

元の質問の一部に関する追加の注記:

「OUTPUTパラメーター(..)にINPUT値を提供しないことは許可されていますか?」

SQLServerでは、OUTPUTパラメータのデフォルト値を指定することができます(他の人が実際にINOUTを指摘したように)。明示的な値を指定したり、関数自体にIDを生成させたりできる次の例を考えてください。

CREATE PROCEDURE test (@id uniqueidentifier = NULL OUTPUT) AS
BEGIN
  IF @id IS NULL SET @id = NEWID()
  -- INSERT INTO xyz (...) VALUES (@id, ...)
  PRINT 'Insert with id: ' + CAST (@id as nvarchar(36))
END
GO

DECLARE @insertedId uniqueidentifier
EXECUTE test '00000000-0000-0000-0000-000000000000'
EXECUTE test @insertedId OUTPUT
PRINT @insertedId

DROP PROCEDURE test

これは印刷します

Insert with id: 00000000-0000-0000-0000-000000000000
Insert with id: 67AE3D27-8EAB-4301-B384-30EEA1488440
67AE3D27-8EAB-4301-B384-30EEA1488440
2
blueling

注目に値する他の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を返します

0
Dan