Oracle
 sql >> Base de Dados >  >> RDS >> Oracle

Por que a seleção do procedimento armazenado não é suportada em bancos de dados relacionais?


TL;DR :você pode selecione de funções (com valor de tabela) ou de qualquer tipo de função no PostgreSQL. Mas não de procedimentos armazenados.

Aqui está uma explicação "intuitiva", um tanto agnóstica de banco de dados, pois acredito que o SQL e seus muitos dialetos são muito uma linguagem / conceito cultivado organicamente para que haja uma explicação "científica" fundamental para isso.

Procedimentos x Funções, historicamente


Não vejo sentido em selecionar procedimentos armazenados, mas sou influenciado por anos de experiência e aceitação do status quo, e certamente vejo como a distinção entre procedimentos e funções pode ser confuso e como se deseja que eles sejam mais versáteis e poderosos. Especificamente no SQL Server, Sybase ou MySQL, os procedimentos podem retornar um número arbitrário de conjuntos de resultados/contagens de atualização, embora isso não seja o mesmo que uma função que retorna um tipo bem definido.

Pense nos procedimentos como rotinas imperativas (com efeitos colaterais) e de funções como rotinas puras sem efeitos colaterais. Um SELECT declaração em si também é "pura" sem efeitos colaterais (além de possíveis efeitos de bloqueio), então faz sentido pensar em funções como os únicos tipos de rotinas que podem ser usadas em um SELECT declaração.

Na verdade, pense nas funções como rotinas com fortes restrições de comportamento, enquanto os procedimentos podem executar programas arbitrários.

Linguagens 4GL x 3GL


Outra maneira de ver isso é da perspectiva do SQL ser uma linguagem de programação de 4ª geração (4GL) . Um 4GL só pode funcionar razoavelmente se for muito restrito no que pode fazer. Expressões de tabela comuns feitas SQL turing-complete , sim, mas a natureza declarativa do SQL ainda impede que seja uma linguagem de propósito geral do ponto de vista prático do dia a dia.

Os procedimentos armazenados são uma maneira de contornar essa limitação. Às vezes, você quer estar completando e prático. Assim, os procedimentos armazenados se tornam imperativos, tendo efeitos colaterais, sendo transacionais, etc.

As funções armazenadas são uma maneira inteligente de apresentar algumas 3GL / recursos de linguagem procedural para o mundo 4GL mais puro ao preço de proibir efeitos colaterais dentro deles (a menos que você queira abrir a caixa de pandora e ter um SELECT completamente imprevisível declarações).

O fato de alguns bancos de dados permitirem que seus procedimentos armazenados retornem números arbitrários de conjuntos de resultados/cursores é uma característica de permitirem comportamentos arbitrários, incluindo efeitos colaterais. Em princípio, nada do que eu dissesse impediria esse comportamento específico também em funções armazenadas, mas seria muito impraticável e difícil de gerenciar se fosse permitido fazê-lo no contexto do SQL, a linguagem 4GL.

Desta forma:
  • Procedures podem chamar procedures, qualquer função e SQL
  • Funções "puras" podem chamar funções "puras" e SQL
  • SQL pode chamar funções "puras" e SQL

Mas:
  • Funções "puras" que chamam procedimentos tornam-se funções "impuras" (como procedimentos)

E:
  • SQL não pode chamar procedimentos
  • SQL não pode chamar funções "impuras"

Exemplos de funções "puras" com valor de tabela:


Aqui estão alguns exemplos de uso de funções "puras" com valor de tabela:

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;
/

E depois:
SELECT * FROM TABLE (my_function(1, 2))

SQL Server

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

E depois
SELECT * FROM my_function(1, 2)

PostgreSQL


Deixe-me dar uma palavrinha sobre o PostgreSQL.

PostgreSQL é incrível e, portanto, uma exceção. Também é estranho e provavelmente 50% de seus recursos não devem ser usados ​​em produção. Ele suporta apenas "funções", não "procedimentos", mas essas funções podem atuar como qualquer coisa. Confira a seguir:
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;

Efeitos colaterais:
  • Uma tabela é criada
  • Um registro é inserido

Ainda:
SELECT * FROM wow();

Rendimentos
wow
---
1