Digamos que tengo que implementar un fragmento de código T-SQL que debe devolver una tabla como resultado. Puedo implementar una función con valores de tabla o un procedimiento almacenado que devuelve un conjunto de filas. ¿Qué debo usar?
En resumen, lo que quiero saber es:
¿Cuáles son las principales diferencias entre funciones y procedimientos almacenados? ¿Qué consideraciones debo tener en cuenta para utilizar uno u otro?
Respuestas:
Si es probable que desee combinar el resultado de este fragmento de código con otras tablas, entonces, obviamente, una función con valores de tabla le permitirá componer los resultados en una sola declaración SELECT.
Generalmente, hay una jerarquía (Ver <Función de TV <Proceso almacenado). Puede hacer más en cada uno, pero la capacidad de componer las salidas y de que el optimizador se involucre realmente disminuye a medida que aumenta la funcionalidad.
Por lo tanto, use el que mínimamente le permita expresar el resultado deseado.
fuente
Las funciones deben ser deterministas y no se pueden utilizar para realizar cambios en la base de datos, mientras que los procedimientos almacenados le permiten realizar inserciones y actualizaciones, etc.
Debe limitar el uso de funciones, ya que plantean un gran problema de escalabilidad para consultas grandes y complejas. Se convierten en una especie de "caja negra" para el optimizador de consultas y verá enormes diferencias de rendimiento entre el uso de funciones y la simple inserción del código en una consulta.
Pero definitivamente son útiles para devoluciones con valores de tabla en casos muy específicos.
Si necesita analizar una lista delimitada por comas, para simular el paso de una matriz a un procedimiento, una función puede convertir la lista en una tabla para usted. Esta es una práctica común con Sql Server 2005, ya que todavía no podemos pasar tablas a procedimientos almacenados (podemos hacerlo con 2008).
fuente
De los documentos :
fuente
Voy a escribir algunas diferencias interesantes entre los procedimientos almacenados y las funciones.
No podemos usar funciones no deterministas en Funciones, pero podemos usar funciones no deterministas en procedimientos almacenados. Ahora surge la pregunta, ¿qué es la función no determinista? La respuesta es: -
Excepción:-
Podemos usar declaraciones DML (insertar, actualizar, eliminar) dentro de un procedimiento almacenado, pero no podemos usar declaraciones DML en funciones en tablas físicas o tablas permanentes. Si queremos hacer una operación DML en funciones, podemos hacerlo sobre variables de tabla, no sobre tablas permanentes.
No podemos utilizar el manejo de errores dentro de la función, pero podemos hacerlo en procedimientos almacenados.
fuente
El procedimiento puede devolver cero o n valores mientras que la función puede devolver un valor que es obligatorio.
Los procedimientos pueden tener parámetros de entrada / salida mientras que las funciones solo pueden tener parámetros de entrada.
El procedimiento permite tanto la instrucción de selección como la de DML, mientras que la función solo permite la instrucción de selección.
Las funciones se pueden llamar desde el procedimiento, mientras que los procedimientos no se pueden llamar desde la función.
La excepción se puede manejar mediante el bloque try-catch en un procedimiento, mientras que el bloque try-catch no se puede usar en una función.
Podemos optar por la gestión de transacciones en el procedimiento, mientras que no podemos hacerlo en función.
Los procedimientos no se pueden utilizar en una instrucción de selección, mientras que la función se puede incrustar en una instrucción de selección.
UDF (función definida por el usuario) se puede utilizar en las sentencias SQL en cualquier lugar de la sección
WHERE
/HAVING
/SELECT
, mientras que los procedimientos almacenados no se pueden utilizar.Las UDF que devuelven tablas pueden tratarse como otro conjunto de filas. Esto se puede usar en
JOIN
s con otras tablas.Las UDF en línea se pueden considerar como vistas que toman parámetros y se pueden usar en
JOIN
sy otras operaciones de conjuntos de filas.fuente
Si tiene una función, puede usarla como parte de su declaración SQL, por ejemplo
SELECT function_name(field1) FROM table
No funciona de esta manera para los procedimientos almacenados.
fuente
Ejecuté algunas pruebas con un bit de lógica de ejecución prolongada, con el mismo bit de código (una declaración SELECT larga) ejecutándose tanto en una función con valores de tabla como en un procedimiento almacenado, y un EXEC / SELECT directo, y cada uno se realizó de manera idéntica.
En mi opinión, siempre use una función con valores de tabla en lugar de un procedimiento almacenado para devolver un conjunto de resultados, ya que hace que la lógica sea mucho más fácil y legible en las consultas que posteriormente se unen a ellas, y le permite reutilizar la misma lógica. Para evitar un impacto excesivo en el rendimiento, a menudo uso parámetros "opcionales" (es decir, puede pasarles NULL) para permitir que la función devuelva el conjunto de resultados para que sea más rápido, por ejemplo:
CREATE FUNCTION dbo.getSitePermissions(@RegionID int, @optPersonID int, optSiteID int) AS RETURN SELECT DISTINCT SiteID, PersonID FROM dbo.SiteViewPermissions WHERE (@optPersonID IS NULL OR @optPersonID = PersonID) AND (@optSiteID IS NULL OR @optSiteID = SiteID) AND @RegionID = RegionID
De esta manera, puede usar esta función para muchas situaciones diferentes y no sufrir un gran impacto en el rendimiento. Creo que esto es más eficiente que filtrar después:
SELECT * FROM dbo.getSitePermissions(@RegionID) WHERE SiteID = 1
He utilizado esta técnica en varias funciones, a veces con una larga lista de parámetros "opcionales" de este tipo.
fuente
Yo personalmente uso funciones con valores de tabla cuando todo lo que estoy devolviendo es una sola tabla sin efectos. Básicamente, los trato como vistas parametrizadas.
Si necesito que se devuelvan varios conjuntos de registros o si habrá valores actualizados en las tablas, utilizo un procedimiento almacenado.
Mis 2 centavos
fuente
Como se mencionó anteriormente, las funciones son más legibles / componibles / autodocumentadas, pero son menos eficaces en general, y pueden ser mucho menos eficaces si te dejas llevar por ellas en combinaciones como
SELECT * FROM dbo.tvfVeryLargeResultset1(@myVar1) tvf1 INNER JOIN dbo.tvfVeryLargeResultset1(@myVar2) tvf2 ON (tvf1.JoinId = tvf2.JoinId)
A menudo, solo tiene que aceptar la redundancia de código que un tvf podría eliminar (a un costo de rendimiento inaceptable).
Otro punto que aún no he visto mencionado es que no puede usar tablas temporales de cambio de estado de base de datos dentro de un tvf de múltiples declaraciones. El mecanismo más funcionalmente equivalente a una tabla temporal es el no cambio de estado, en la variable de la tabla de memoria, y para conjuntos de datos grandes, una tabla temporal probablemente tendrá más rendimiento que una variable de tabla. (Otras alternativas incluyen tablas dinámicas y expresiones comunes con valores de tabla, pero en cierto nivel de complejidad, estas dejan de ser una buena opción en mi opinión).
fuente
Realizaría una prueba de ambos. Es probable que el enfoque sp o una tabla derivada sea significativamente más rápido que una función y, de ser así, se debería utilizar ese enfoque. En general, evito las funciones porque pueden ser acaparadores de rendimiento.
fuente
Depende :) Si desea utilizar el resultado con valores de tabla en otro procedimiento, es mejor utilizar una función TableValued. Si los resultados son para un cliente, el proceso almacenado suele ser la mejor manera de hacerlo.
fuente
Los procedimientos almacenados son consultas precompiladas que se ejecutan más rápido y se guardan de las inyecciones de SQL. Pueden devolver valores 0 o N. Podemos realizar operaciones DML dentro de los procedimientos almacenados. Podemos usar funciones dentro de los procedimientos y podemos usar funciones en la consulta de selección. Las funciones se utilizan para devolver cualquier valor y las operaciones DML no son posibles en las funciones. las funciones son de dos tipos, escalares y con valores de tabla. La función escalar devuelve un valor único, función con valores de tabla que se utiliza para devolver filas de tablas.
fuente