Las funciones y los procedimientos almacenados tienen propósitos separados. Aunque no es la mejor analogía, las funciones se pueden ver literalmente como cualquier otra función que usaría en cualquier lenguaje de programación, pero los procesos almacenados son más como programas individuales o un script por lotes.
Las funciones normalmente tienen una salida y opcionalmente entradas. La salida se puede usar como entrada para otra función (un servidor SQL incorporado como DATEDIFF, LEN, etc.) o como un 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 a un proceso almacenado directamente.
Sin embargo, las funciones tienen un peligro oculto: pueden ser mal utilizadas 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 esas son otras 1000 consultas ad-hoc en la base de datos. Del mismo modo, si se llama a la función cuando se especifica en la especificación de la columna, se llamará a la función para cada fila devuelta por SELECT.
Por lo tanto, debe tener cuidado al escribir las funciones. Si selecciona SELECT desde una tabla en una función, debe preguntarse si se puede realizar mejor con JOIN en el proceso almacenado primario o en alguna otra construcción SQL (como CASE ... WHEN ... ELSE ... FINAL).