Funciones frente a procedimientos almacenados

88

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?

Auron
fuente
1
Esta parece ser la respuesta perfecta: stackoverflow.com/a/1179778/365188
Ozair Kafray

Respuestas:

51

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.

Damien_The_Unbeliever
fuente
50

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).

Eric Z Barba
fuente
1
Pero PUEDE enviar XML a un procedimiento almacenado: stackoverflow.com/questions/144550/…
cllpse
2
Incorrecto, la mayoría de las funciones del servidor SQL no son deterministas, como getdate en el servidor MS-SQL. Solo las funciones ODBC son funciones canónicas (= mucho más rápidas + indexables) ... Pero tienes mucha razón, debes limitar el uso de funciones en las consultas tanto como sea posible por razones de rendimiento.
Stefan Steiger
45

De los documentos :

Si un procedimiento almacenado cumple con los siguientes criterios, es un buen candidato para ser reescrito como una función con valores de tabla:

  • La lógica se puede expresar en una sola instrucción SELECT, pero es un procedimiento almacenado, en lugar de una vista, solo debido a la necesidad de parámetros.

  • El procedimiento almacenado no realiza operaciones de actualización, excepto para las variables de tabla.

  • No hay necesidad de instrucciones EXECUTE dinámicas.

  • El procedimiento almacenado devuelve un conjunto de resultados.

  • El propósito principal del procedimiento almacenado es generar resultados intermedios que se cargarán en una tabla temporal, que luego se consulta en una instrucción SELECT.

Christoffer Lette
fuente
12

Voy a escribir algunas diferencias interesantes entre los procedimientos almacenados y las funciones.

  • Podemos utilizar funciones en consultas seleccionadas, pero no podemos utilizar procedimientos almacenados en consultas seleccionadas.
  • 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: -

    Una función no determinista es aquella función que devuelve diferentes salidas para los mismos valores de entrada en diferentes momentos, como getdate (). Siempre devuelve un valor diferente cada vez que se ejecuta.

    Excepción:-

    Las versiones anteriores de sql server anteriores a sql 2000 no permiten usar la función getdate () en funciones definidas por el usuario, pero la versión 2005 y posteriores nos permite usar la función getdate () dentro de una función definida por el usuario.

    Newid () es otro ejemplo de función no determinista, pero no se puede usar en funciones definidas por el usuario, pero podemos usarlo en un procedimiento almacenado.

  • 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.

Neeraj Kumar Yadav
fuente
¿Cómo es que las operaciones DML son compatibles con las funciones de MySQL?
Joey Pinto
@JoeyPinto. Porque myNONsql no es una queja de SQL. Claro, tiene extras, pero no lo básico.
PerformanceDBA
8
  1. El procedimiento puede devolver cero o n valores mientras que la función puede devolver un valor que es obligatorio.

  2. Los procedimientos pueden tener parámetros de entrada / salida mientras que las funciones solo pueden tener parámetros de entrada.

  3. 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.

  4. Las funciones se pueden llamar desde el procedimiento, mientras que los procedimientos no se pueden llamar desde la función.

  5. 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.

  6. Podemos optar por la gestión de transacciones en el procedimiento, mientras que no podemos hacerlo en función.

  7. 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.

  8. 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.

  9. Las UDF que devuelven tablas pueden tratarse como otro conjunto de filas. Esto se puede usar en JOINs con otras tablas.

  10. Las UDF en línea se pueden considerar como vistas que toman parámetros y se pueden usar en JOINsy otras operaciones de conjuntos de filas.

nathan1138
fuente
6

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.

Ilya Kochetov
fuente
1
Creo que estaba hablando de funciones que devuelven valores de tabla.
wcm
1
Bueno, estoy hablando en general. Pero para mi caso específico, ahora estoy entre un procedimiento almacenado o una función con valores de tabla.
Auron
5

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.

Paul Grimshaw
fuente
4

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

wcm
fuente
4

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).

6eorge Jetson
fuente
1

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.

HLGEM
fuente
1

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.

edosoft
fuente
-1

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.

Harish Madaan
fuente
Esta es una pregunta muy antigua con una gran cantidad de respuestas, muchas de ellas (incluida la respuesta aceptada) son altamente votadas. Antes de agregar otra respuesta a un hilo de este tipo, debe preguntarse: "¿Qué les falta a todas esas respuestas existentes que me obliga a escribir otra?"
APC