sql >> Base de Datos >  >> RDS >> Oracle

¿Por qué la selección del procedimiento almacenado no es compatible con las bases de datos relacionales?

TL;RD :usted puede seleccione de funciones (con valores de tabla), o de cualquier tipo de función en PostgreSQL. Pero no de procedimientos almacenados.

Aquí hay una explicación "intuitiva", algo agnóstica de la base de datos, porque creo que SQL y sus muchos dialectos son un lenguaje / concepto demasiado desarrollado orgánicamente para que haya una explicación "científica" fundamental para esto.

Procedimientos frente a funciones, históricamente

Realmente no veo el punto de seleccionar entre procedimientos almacenados, pero estoy sesgado por años de experiencia y por aceptar el statu quo, y ciertamente veo cómo la distinción entre procedimientos y funciones puede ser confuso y cómo uno desearía que fueran más versátiles y poderosos. Específicamente en SQL Server, Sybase o MySQL, los procedimientos pueden devolver un número arbitrario de conjuntos de resultados/recuentos de actualización, aunque esto no es lo mismo que una función que devuelve un tipo bien definido.

Piense en los procedimientos como rutinas imperativas (con efectos secundarios) y de funciones como puras rutinas sin efectos secundarios. Un SELECT declaración en sí también es "pura" sin efectos secundarios (aparte de los posibles efectos de bloqueo), por lo que tiene sentido pensar en las funciones como los únicos tipos de rutinas que se pueden usar en un SELECT declaración.

De hecho, piense en las funciones como rutinas con fuertes restricciones en el comportamiento, mientras que a los procedimientos se les permite ejecutar programas arbitrarios.

Lenguajes 4GL frente a 3GL

Otra forma de ver esto es desde la perspectiva de que SQL es un lenguaje de programación de cuarta generación (4GL) . Un 4GL solo puede funcionar razonablemente si está fuertemente restringido en lo que puede hacer. Common Table Expressions hizo SQL turing-complete , sí, pero la naturaleza declarativa de SQL aún impide que sea un lenguaje de propósito general desde una perspectiva práctica y cotidiana.

Los procedimientos almacenados son una forma de eludir esta limitación. A veces, quieres estar turing completo y práctico. Entonces, los procedimientos almacenados recurren a ser imperativos, tener efectos secundarios, ser transaccionales, etc.

Las funciones almacenadas son una forma inteligente de introducir algunas 3GL/características de lenguaje procesal en el mundo 4GL más puro al precio de prohibir los efectos secundarios dentro de ellos (a menos que desee abrir la caja de pandora y tener SELECT completamente impredecible declaraciones).

El hecho de que algunas bases de datos permitan que sus procedimientos almacenados devuelvan números arbitrarios de conjuntos de resultados/cursores es un rasgo de que permiten un comportamiento arbitrario, incluidos los efectos secundarios. En principio, nada de lo que dije evitaría este comportamiento particular también en las funciones almacenadas, pero sería muy poco práctico y difícil de manejar si se les permitiera hacerlo dentro del contexto de SQL, el lenguaje 4GL.

Así:

  • Los procedimientos pueden llamar a procedimientos, cualquier función y SQL
  • Las funciones "puras" pueden llamar funciones "puras" y SQL
  • SQL puede llamar funciones "puras" y SQL

Pero:

  • Las funciones "puras" que llaman a los procedimientos se convierten en funciones "impuras" (como los procedimientos)

Y:

  • SQL no puede llamar a procedimientos
  • SQL no puede llamar funciones "impuras"

Ejemplos de funciones con valores de tabla "puras":

Estos son algunos ejemplos del uso de funciones "puras" con valores de tabla:

Oráculo

CREATE TYPE numbers AS TABLE OF number(10);
/

CREATE OR REPLACE FUNCTION my_function (a number, b number)
RETURN numbers
IS
BEGIN
    return numbers(a, b);
END my_function;
/

Y luego:

SELECT * FROM TABLE (my_function(1, 2))

Servidor SQL

CREATE FUNCTION my_function(@v1 INTEGER, @v2 INTEGER)
RETURNS @out_table TABLE (
    column_value INTEGER
)
AS
BEGIN
    INSERT @out_table
    VALUES (@v1), (@v2)
    RETURN
END

Y entonces

SELECT * FROM my_function(1, 2)

PostgreSQL

Déjame tener una palabra sobre PostgreSQL.

PostgreSQL es increíble y, por lo tanto, una excepción. También es raro y probablemente el 50% de sus características no deberían usarse en producción. Solo admite "funciones", no "procedimientos", pero esas funciones pueden actuar como cualquier cosa. Mira lo siguiente:

CREATE OR REPLACE FUNCTION wow ()
RETURNS SETOF INT
AS $$
BEGIN
    CREATE TABLE boom (i INT);

    RETURN QUERY
    INSERT INTO boom VALUES (1)
    RETURNING *;
END;
$$ LANGUAGE plpgsql;

Efectos secundarios:

  • Se crea una tabla
  • Se inserta un registro

Sin embargo:

SELECT * FROM wow();

Rendimientos

wow
---
1