web-dev-qa-db-fra.com

Procédure stockée SQL avec paramètre de sortie

Je sais comment écrire une procédure stockée avec des paramètres de sortie. Mais je ne connais pas la raison pour laquelle je l'utiliserais plutôt qu'en utilisant une simple instruction SELECT. Une procédure stockée normale peut toujours renvoyer une sortie dans une grille (voir les exemples ci-dessous).

Quelqu'un peut-il donner un exemple concret où je peux utiliser un SP avec paramètre de sortie sur avec SP sans paramètre de sortie?

Exemples

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

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

Les paramètres de sortie dans les procédures stockées sont utiles pour renvoyer une valeur au T-SQL appelant, qui peut ensuite utiliser cette valeur pour d'autres choses.

Supposons que vous ayez une procédure stockée qui renvoie un état étant donné l'entrée d'une ville, avec l'état comme paramètre de sortie:

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

Vous pouvez maintenant utiliser ce paramètre de sortie pour passer une valeur ailleurs.

Par exemple:

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

-- Do something with this value
SELECT @State;

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

Pour résumer, si vous souhaitez simplement renvoyer une valeur pour une application cliente, vous n'avez probablement pas besoin d'un paramètre de sortie.

Cependant, si vous souhaitez transmettre des valeurs dans T-SQL entre des procédures stockées, elles peuvent être très utiles.

Pour ce que ça vaut, j'utilise à peine les paramètres de sortie.

4
Randolph West

En supposant que cette question concerne SQL Server: elle se résume au contexte et à l'efficacité.

Contexte = Code d'application

Lors de l'exécution de la procédure stockée à partir du code d'application, la quantité de code n'est pas très différente. Lorsque vous retournez un jeu de résultats, appelez simplement ExecuteReader puis SqlDataReader.Read() pour obtenir la première ligne, puis récupérez les colonnes à partir de SqlDataReader. Mais si vous n'obtenez qu'une seule valeur, vous pouvez utiliser la méthode de raccourci de ExecuteScalar qui obtient une ligne (même s'il y a plus de lignes) et renvoie la valeur dans la première colonne (même s'il y a sont plus de colonnes). Lors du retour des paramètres OUTPUT, il vous suffit d'appeler ExecuteNonQuery, vérifiez le .Value propriété de chaque paramètre, et transtypée dans le type approprié.

Ainsi, en termes d'exemple simple de retour d'une seule valeur, il semble "plus facile" de renvoyer un jeu de résultats et d'appeler ExecuteScalar. MAIS, le renvoi d'un jeu de résultats, que vous utilisiez ExecuteReader ou ExecuteScalar, nécessite plus de ressources de SQL Server et de l'application cliente. SQL Server doit configurer et gérer le jeu de résultats (c'est-à-dire qu'il nécessite de la mémoire et du temps), et l'application doit instancier un SqlDataReader (oui, même en utilisant ExecuteScalar) et le gérer (c'est-à-dire nécessite de la mémoire et du temps). Si vous avez la garantie de n'avoir qu'une seule ligne de jeu de résultats, il vaut mieux (même si ce n'est que légèrement) utiliser les paramètres de sortie.

Contexte = T-SQL

Lors de l'exécution de la procédure stockée à partir de T-SQL (et devant utiliser la ou les valeurs renvoyées), il est au moins plus pratique d'utiliser les paramètres OUTPUT. Le retour d'un jeu de résultats est utilisable, mais nécessite l'insertion des résultats dans une table - généralement une table temporaire locale ou une variable de table - en utilisant INSERT ... EXEC. Mais vous devez ensuite sélectionner la ligne dans des variables locales. Encore une fois, il faut plus de temps et de ressources pour arriver au même endroit où avoir les valeurs dans les variables.

Maintenant, lorsque vous renvoyez une seule valeur (c'est-à-dire la même situation qui fonctionne pour ExecuteScalar), vous pouvez parfois utiliser un scalaire Fonction définie par l'utilisateur (UDF) à la place, qui a la capacité d'être placée dans une requête, ce qui est parfois très utile (même s'il y a un impact sur les performances de l'utilisation d'UDF Scalar dans les requêtes). Cependant, il existe de nombreuses restrictions sur ce qui peut être fait dans les FDU, donc si vous devez créer des tables temporaires, ou faire n'importe quel DML ou DDL, etc., alors l'utilisation d'une procédure stockée est la seule option.


Bien que cela ne fasse pas partie de la question "jeu de résultats vs paramètre OUTPUT", il est bon de garder à l'esprit que vous pouvez faire les deux! Si vous avez des valeurs discrètes ainsi qu'un ensemble de données à renvoyer, la procédure stockée permet de renvoyer les deux, ce qui, en de rares occasions, est très utile.

4
Solomon Rutzky

Je pense que deux autres choses méritent d'être notées:

1) Vous pouvez passer plusieurs paramètres en tant que OUTPUT,

2) Vous n'avez pas besoin d'appeler les paramètres avec OUTPUT si vous ne voulez pas les résultats

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

Appeler cette routine:

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

Renvoie NULL, NULL, NULL

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

Renvoie 13, "La valeur de A est 2 et la valeur de B est 13", 0

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

Renvoie 13, "La valeur de A est 2 et la valeur de B est 13", 0

(identique au dernier appel, car nous n'avons pas obtenu de nouvelles valeurs en utilisant OUTPUT, il a donc conservé les anciennes valeurs.)

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

Renvoie 16, "La valeur de A est 5 et la valeur de B est 16", 1

3
Dan