Función versus procedimiento almacenado en SQL Server
¿Cuándo debo utilizar una función en lugar de un procedimiento almacenado en SQL y viceversa? ¿Cuál es el propósito de cada uno?
Las funciones son valores calculados y no pueden realizar cambios ambientales permanentes SQL Server
(es decir, no se permiten declaraciones INSERT
o ).UPDATE
Una función se puede usar en línea en SQL
declaraciones si devuelve un valor escalar o se puede unir si devuelve un conjunto de resultados.
Un punto que vale la pena destacar de los comentarios, que resumen la respuesta. Gracias a @Sean K Anderson:
Las funciones siguen la definición informática en el sentido de que DEBEN devolver un valor y no pueden alterar los datos que reciben como parámetros (los argumentos). Las funciones no pueden cambiar nada, deben tener al menos un parámetro y deben devolver un valor. Los procesos almacenados no necesitan tener un parámetro, pueden cambiar los objetos de la base de datos y no tienen que devolver un valor.
Aquí hay una tabla que resume las diferencias:
Procedimiento almacenado | Función | |
---|---|---|
Devoluciones | Cero o más valores | Un valor único (que puede ser un escalar o una tabla) |
¿Se puede utilizar la transacción? | Sí | No |
¿Se puede generar salida a parámetros? | Sí | No |
¿Se pueden llamar unos a otros? | Puede llamar a una función | No se puede llamar a un procedimiento almacenado |
¿Utilizable en declaraciones SELECT, WHERE y HAVING? | No | Sí |
¿Admite manejo de excepciones (a través de try/catch)? | Sí | No |
Las funciones y los procedimientos almacenados tienen propósitos separados. Aunque no es la mejor analogía, las funciones pueden verse literalmente como cualquier otra función que usarías en cualquier lenguaje de programación, pero los procesos almacenados se parecen más a programas individuales o a un script por lotes.
Las funciones normalmente tienen una salida y opcionalmente entradas. Luego, la salida se puede utilizar como entrada para otra función (un SQL Server integrado como DATEDIFF, LEN, etc.) o como predicado para una consulta SQL, por ejemplo, SELECT a, b, dbo.MyFunction(c) FROM table
o SELECT a, b, c FROM table WHERE a = dbo.MyFunc(c)
.
Los procesos almacenados se utilizan para vincular consultas SQL en una transacción e interactuar con el mundo exterior. Los marcos como ADO.NET, etc. no pueden llamar a una función directamente, pero pueden llamar directamente a un proceso almacenado.
Sin embargo, las funciones tienen un peligro oculto: pueden usarse incorrectamente y causar problemas de rendimiento bastante desagradables: considere esta consulta:
SELECT * FROM dbo.MyTable WHERE col1 = dbo.MyFunction(col2)
Donde MyFunction se declara como:
CREATE FUNCTION MyFunction (@someValue INTEGER) RETURNS INTEGER
AS
BEGIN
DECLARE @retval INTEGER
SELECT localValue
FROM dbo.localToNationalMapTable
WHERE nationalValue = @someValue
RETURN @retval
END
Lo que sucede aquí es que se llama a la función MyFunction para cada fila de la tabla MyTable. Si MyTable tiene 1000 filas, entonces son otras 1000 consultas ad hoc en la base de datos. De manera similar, si se llama a la función cuando se especifica en la especificación de la columna, entonces se llamará a la función para cada fila devuelta por SELECT.
Por lo tanto, debe tener cuidado al escribir funciones. Si SELECCIONA desde una tabla en una función, debe preguntarse si se puede realizar mejor con un JOIN en el proceso almacenado principal o alguna otra construcción SQL (como CASE... WHEN... ELSE... FIN).