web-dev-qa-db-ja.com

ストアドプロシージャの戻り値を取得する方法

おそらく答えやすい質問でしょう。私はこの手順を持っています:

CREATE PROCEDURE [dbo].[AccountExists]
    @UserName nvarchar(16)
AS
IF EXISTS (SELECT Id FROM Account WHERE UserName=@UserName)
SELECT 1
ELSE SELECT 0 

このプロシージャを呼び出してこれを行うADO.NETコードがある場合:

return Convert.ToBoolean(sproc.ExecuteScalar());

Trueまたはfalseが返されます。

ストアドプロシージャをSELECTではなくRETURN 1または0に変更すると:

ALTER PROCEDURE [dbo].[AccountExists]
    @UserName nvarchar(16)
AS
IF EXISTS (SELECT Id FROM Account WHERE UserName=@UserName)
RETURN 1
ELSE RETURN 0 

sproc.ExecuteScalar()はnullを返します。代わりにsproc.ExecuteNonQuery()を試すと、-1が返されます。

ADO.NETでRETURNを使用してストアドプロシージャの結果を取得する方法

SELECTではなくAccountExistsを返す必要があるため、別のストアドプロシージャで呼び出すことができます。

--another procedure to insert or update account

DECLARE @exists bit

EXEC @exists = [dbo].[AccountExists] @UserName 

IF @exists=1
--update account
ELSE
 --insert acocunt
33
core

ParameterDirection.ReturnValueを使用してパラメーターを追加します。戻り値は、実行後にパラメーターに存在します。

43
John Saunders

また、ADO.NETから結果(またはその他の出力パラメーター)を取得するには、返されたすべての結果セットを最初にループする(またはNextResultでそれらをスキップする)必要があります

これは、次のように定義されたプロシージャがある場合を意味します。

CREATE PROC Test(@x INT OUT) AS
    SELECT * From TestTable
    SELECT @x = 1

そしてこれを試してください:

SqlCommand cmd = connection.CreateCommand();
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = "Test"
cmd.Parameters.Add("@x", SqlDbType.Int).Direction = ParameterDirection.Output;
cmd.Parameters.Add("@retval", SqlDbType.Int).Direction = ParameterDirection.ReturnValue;

cmd.Execute();
int? x = cmd.Parameters["@x"].Value is DBNull ? null : (int?)cmd.Parameters["@x"].Value;

その場合、xにはnullが含まれます。動作させるには、次のような手順を実行する必要があります。

using (var rdr = cmd.ExecuteReader()) {
    while (rdr.Read())
        MaybeDoSomething;
}
int? x = cmd.Parameters["@x"].Value is DBNull ? null : (int?)cmd.Parameters["@x"].Value;

後者の場合、xには期待どおり1が含まれます。

10
erikkallen

ExecuteScalarは、最初の行の最初の列を返します。結果セットを選択および作成しなくなったため、nullを返していました。参考までに。ジョン・サンダースが正解です。

3
Darren Kopp

セットアップで他のソリューションを試してみましたが、機能しませんでしたが、VB6&ADO 6.xを使用しています。0のprocリターンは成功を示しています。ドン「その規則を持たない利用可能な関数もあることを忘れないでください。MSDNでこれを見つけて、それは私のために働きました:

Debug.Print "starting at ..." & TimeValue(Now)

Dim cn As New ADODB.Connection
Dim cmd As New ADODB.Command
'These are two possible connection strings. You could also have Integrated Security instead of these for SqS for security
'cn.ConnectionString = "Data Source=[yourserver];User ID=[youruser];Password=[yourpw];Initial Catalog=[yourdb];Provider=SQLNCLI10.1;Application Name=[yourapp]"
cn.ConnectionString = "Data Source=[yours];User ID=[youruser];Password=[yourpassword];Initial Catalog=[Yourdb];Provider=sqloledb;Application Name=[yourapp]"
cn.Open

cmd.ActiveConnection = cn
cmd.CommandText = "AccountExists"
cmd.CommandType = adCmdStoredProc
cmd.Parameters.Append cmd.CreateParameter(, adInteger, adParamReturnValue)
cmd.Parameters.Append cmd.CreateParameter("UserName",adVarChar, adParamInput, 16, UserNameInVB)

cmd.Execute
Debug.Print "Returnval: " & cmd.Parameters(0)
cn.Close

Set cmd = Nothing
Set cn = Nothing

Debug.Print "finished at ..." & TimeValue(Now)

これを実行すると、結果がイミディエイトウィンドウに表示されます(Debug.Print)

2
Pecos Bill

VBAを使用して値を取得する方法はいくつかあります。

  1. レコードセット
  2. 影響を受けたレコードの数(挿入/更新/削除の場合のみ-1)
  3. 出力パラメータ
  4. 戻り値

私のコードは4つすべてを示しています。値を返すストアドプロシージャを次に示します。

Create PROCEDURE CheckExpedite
    @InputX  varchar(10),
    @InputY int,
    @HasExpedite int out
AS
BEGIN
    Select @HasExpedite = 9 from <Table>
    where Column2 = @InputX and Column3 = @InputY

    If @HasExpedite = 9
        Return 2
    Else
        Return 3
End

これが、私がExcel VBAで使用しているサブルーチンです。 Microsoft ActiveX Data Objects 2.8 Libraryを参照する必要があります。

Sub CheckValue()

    Dim InputX As String: InputX = "6000"
    Dim InputY As Integer: InputY = 2014

    'open connnection
    Dim ACon As New Connection
    ACon.Open ("Provider=SQLOLEDB;Data Source=<SqlServer>;" & _
        "Initial Catalog=<Table>;Integrated Security=SSPI")

    'set command
    Dim ACmd As New Command
    Set ACmd.ActiveConnection = ACon
    ACmd.CommandText = "CheckExpedite"
    ACmd.CommandType = adCmdStoredProc

    'Return value must be first parameter else you'll get error from too many parameters
    'Procedure or function "Name" has too many arguments specified.
    ACmd.Parameters.Append ACmd.CreateParameter("ReturnValue", adInteger, adParamReturnValue)
    ACmd.Parameters.Append ACmd.CreateParameter("InputX", adVarChar, adParamInput, 10, InputX)
    ACmd.Parameters.Append ACmd.CreateParameter("InputY", adInteger, adParamInput, 6, InputY)
    ACmd.Parameters.Append ACmd.CreateParameter("HasExpedite", adInteger, adParamOutput)

    Dim RS As Recordset
    Dim RecordsAffected As Long

    'execute query that returns value
    Call ACmd.Execute(RecordsAffected:=RecordsAffected, Options:=adExecuteNoRecords)

    'execute query that returns recordset
    'Set RS = ACmd.Execute(RecordsAffected:=RecordsAffected)

    'get records affected, return value and output parameter
    Debug.Print "Records affected: " & RecordsAffected
    Debug.Print "Return value: " & ACmd.Parameters("ReturnValue")
    Debug.Print "Output param: " & ACmd.Parameters("HasExpedite")

    'use record set here
    '...

    'close
    If Not RS Is Nothing Then RS.Close
    ACon.Close

End Sub
1
D_Bester

いくつかのアドバイスがありますが、デフォルトでは、他に指定しない限り、ストアドプロシージャは0を返します。このため、成功を示すには0がよく使用され、戻りエラー条件を指定するには0以外の値が使用されます。 Johnの提案 を使用するか、 output parameter

1
Russ Cam

以下の例のように使用する場合は、AccountExistsを関数として使用することをお勧めします。

それ以外の場合は、結果に対して選択を行うことにより、別のストアドプロシージャからストアドプロシージャを呼び出して、結果を取得できるはずです。

0
Luke Lowrey