おそらく答えやすい質問でしょう。私はこの手順を持っています:
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
ParameterDirection.ReturnValue
を使用してパラメーターを追加します。戻り値は、実行後にパラメーターに存在します。
また、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が含まれます。
ExecuteScalarは、最初の行の最初の列を返します。結果セットを選択および作成しなくなったため、nullを返していました。参考までに。ジョン・サンダースが正解です。
セットアップで他のソリューションを試してみましたが、機能しませんでしたが、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)
VBAを使用して値を取得する方法はいくつかあります。
私のコードは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
いくつかのアドバイスがありますが、デフォルトでは、他に指定しない限り、ストアドプロシージャは0を返します。このため、成功を示すには0がよく使用され、戻りエラー条件を指定するには0以外の値が使用されます。 Johnの提案 を使用するか、 output parameter
以下の例のように使用する場合は、AccountExistsを関数として使用することをお勧めします。
それ以外の場合は、結果に対して選択を行うことにより、別のストアドプロシージャからストアドプロシージャを呼び出して、結果を取得できるはずです。