Solución:
Los parámetros de salida en los procedimientos almacenados son útiles para devolver un valor al T-SQL que realiza la llamada, que luego puede usar ese valor para otras cosas.
Digamos que tiene un procedimiento almacenado que devuelve un estado dada la entrada de una ciudad, con el estado como parámetro de salida:
CREATE PROCEDURE [dbo].[GetStateFromCity] (@City NVARCHAR(30), @State NCHAR(2) OUTPUT)
AS
SELECT @State = [State]
FROM [ExampleTable]
WHERE [City] = @City
GO;
Ahora puede usar este parámetro de salida para pasar un valor a otra parte.
Por ejemplo:
DECLARE @State int
EXEC [dbo].[GetStateFromCity] @City = 'Calgary', @State OUTPUT;
-- Do something with this value
SELECT @State;
-- Do something else
EXEC [dbo].[GetInsuranceCompanyByState] @State;
En resumen, si solo desea devolver un valor para una aplicación cliente, probablemente no necesite un parámetro de salida.
Sin embargo, si desea pasar valores en T-SQL entre procedimientos almacenados, pueden ser muy útiles.
Por lo que vale, casi no uso parámetros de salida.
Suponiendo que esta pregunta pertenece a SQL Server: se reduce al contexto y la eficiencia.
Contexto = Código de la aplicación
Al ejecutar el procedimiento almacenado desde el código de la aplicación, no es muy diferente en términos de la cantidad de código. Al devolver un conjunto de resultados, simplemente llame ExecuteReader
y luego SqlDataReader.Read()
para obtener una fila, y luego obtener las columnas de la SqlDataReader
. Pero si solo obtiene un valor único, puede utilizar el método abreviado de ExecuteScalar
que obtiene una fila (incluso si hay más filas) y devuelve el valor en la primera columna (incluso si hay más columnas). Al regresar OUTPUT
parámetros, solo necesita llamar ExecuteNonQuery
, comprobar el .Value
propiedad de cada parámetro y convertir al tipo apropiado.
Entonces, en términos del ejemplo simple de devolver un solo valor, parece “más fácil” devolver un conjunto de resultados y llamar ExecuteScalar
. PERO, devolviendo un conjunto de resultados, ya sea usando ExecuteReader
o ExecuteScalar
, requiere más recursos tanto de SQL Server como de la aplicación cliente. SQL Server necesita configurar y administrar el conjunto de resultados (es decir, requiere memoria y tiempo), y la aplicación necesita crear una instancia SqlDataReader
(sí, incluso cuando se usa ExecuteScalar
) y administrarlo (es decir, requiere memoria y tiempo). Si se le garantiza que solo tendrá una única fila de conjunto de resultados, es mejor (aunque sea solo un poco) usar los parámetros de salida.
Contexto = T-SQL
Al ejecutar el procedimiento almacenado desde T-SQL (y necesita usar los valores devueltos), es al menos más conveniente usar OUTPUT
parámetros. Devolver un conjunto de resultados es utilizable, pero requiere insertar los resultados en una tabla, generalmente una tabla temporal local o una variable de tabla, usando INSERT ... EXEC
. Pero aún debe seleccionar la fila en variables locales. Nuevamente, es más tiempo y recursos llegar al mismo lugar de tener los valores en las variables.
Ahora, cuando devuelve solo un valor (es decir, la misma situación que funciona para ExecuteScalar
), entonces tú puedes algunas veces use una función definida por el usuario (UDF) escalar en su lugar, que tiene la capacidad de colocarse en una consulta, lo que a veces es muy útil (incluso si hay un impacto en el rendimiento al usar UDF escalares en las consultas). Sin embargo, existen muchas restricciones sobre lo que se puede hacer en las UDF, por lo que si necesita crear tablas temporales, o hacer cualquier DML o DDL, etc., entonces usar un procedimiento almacenado es la única opción.
Si bien no forma parte de la pregunta “conjunto de resultados frente al parámetro de SALIDA”, es bueno tener en cuenta que pueden ¡Haz ambos! Si tiene algunos valores que son discretos, así como un conjunto de datos para devolver, el procedimiento almacenado permite devolver ambos, lo que en raras ocasiones es bastante útil.
Otras dos cosas que creo que vale la pena señalar:
1) Puede pasar más de un parámetro como OUTPUT
,
2) No tiene que llamar a los parámetros con OUTPUT
si no quieres los resultados
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
Llamando a esta rutina:
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
Devuelve NULL, NULL, NULL
EXEC ManyOutputs 2, @bVal OUT, @cVal OUT, @dVal OUT
SELECT @bVal AS bVal, @cVal as cVal, @dVal as dVal
Devuelve 13, “El valor de A es 2 y el valor de B es 13”, 0
EXEC ManyOutputs 3, @bVal, @cVal, @dVal
SELECT @bVal AS bVal, @cVal as cVal, @dVal as dVal
Devuelve 13, “El valor de A es 2 y el valor de B es 13”, 0
(lo mismo que la última llamada, porque no obtuvimos nuevos valores usando OUTPUT
, por lo que retuvo los valores antiguos).
EXEC ManyOutputs 5, @bVal OUT, @cVal OUT, @dVal OUT
SELECT @bVal AS bVal, @cVal as cVal, @dVal as dVal
Devuelve 16, “El valor de A es 5 y el valor de B es 16”, 1