35 votes

Comment obtenir la valeur de retour d'une procédure stockée

Probablement un facile à répondre à la question. J'ai cette procédure:

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

Quand j'ai ADO.NET le code qui appelle cette procédure et fait ceci:

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

True ou false est retourné.

Lorsque je change la procédure stockée renvoie 1 ou 0, au lieu de SÉLECTIONNER:

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

la procédure stockée.ExecuteScalar() renvoie la valeur null. Si j'essaie de la procédure stockée.ExecuteNonQuery() au lieu de cela, -1 est retourné.

Comment puis-je obtenir le résultat d'une procédure stockée avec un RETOUR en ADO.NET?

J'ai besoin de AccountExists de RETOUR, au lieu de SÉLECTIONNER pour que je puisse avoir un autre appel de procédure stockée c':

--another procedure to insert or update account

DECLARE @exists bit

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

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

43voto

John Saunders Points 118808

Ajoutez un paramètre à la commande, en utilisant ParameterDirection.ReturnValue . La valeur de retour sera présente dans le paramètre après l'exécution.

10voto

erikkallen Points 16601

Aussi, pour récupérer le résultat (ou tout autre paramètre de sortie) à partir de ADO.NET vous disposez d'une boucle sur tous les retours d'ensembles de résultats de la première (ou de les ignorer avec NextResult)

Cela signifie que si vous avez une procédure définie comme ceci:

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

Et essayer de faire ceci:

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;

Alors x contient la valeur null. Pour le faire fonctionner, vous devez exécuter la procédure comme:

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

Dans ce dernier cas, x contiendra 1 comme prévu.

3voto

Darren Kopp Points 27704

ExecuteScalar renvoie la première colonne de la première ligne. Puisque vous ne sélectionniez plus et ne créiez pas un jeu de résultats, c'est pourquoi il retournait null. Tout comme FYI. John Saunders a la bonne réponse.

2voto

Pecos Bill Points 469

J'ai essayé les autres solutions avec ma configuration et elles n'ont pas fonctionné mais j'utilise VB6 & ADO 6.x. Je tiens également à souligner qu'un retour de proc de 0 indique une réussite. N'oubliez pas qu'il existe également des fonctions qui n'ont pas cette convention. J'ai trouvé cela sur MSDN et cela a fonctionné pour moi:

 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)
 

Les résultats apparaîtront dans la fenêtre immédiate lors de l'exécution de ceci (Debug.Print)

0voto

Luke Lowrey Points 2032

Si vous prévoyez de l'utiliser comme l'exemple ci-dessous, AccountExists pourrait être mieux en tant que fonction.

Sinon, vous devriez toujours pouvoir obtenir le résultat de la procédure stockée en l'appelant à partir d'une autre en faisant une sélection sur le résultat.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X