sql >> Databáze >  >> RDS >> Oracle

Proč není v relačních databázích podporován výběr z uložené procedury?

TL;DR :můžete vyberte z (tabulkových) funkcí nebo z jakéhokoli druhu funkcí v PostgreSQL. Ale ne z uložených procedur.

Zde je "intuitivní", poněkud databázově agnostické vysvětlení, protože věřím, že SQL a jeho mnoho dialektů je příliš organicky vypěstovaný jazyk/koncept, než aby pro to existovalo základní, "vědecké" vysvětlení.

Postupy vs. funkce, historicky

Opravdu nevidím smysl ve vybírání z uložených procedur, ale jsem zaujatý mnohaletými zkušenostmi a přijímáním status quo a rozhodně chápu, jak rozdíl mezi procedurami a funkce může být matoucí a jak by si člověk přál, aby byly všestrannější a výkonnější. Konkrétně v SQL Server, Sybase nebo MySQL mohou procedury vracet libovolný počet sad výsledků / počtů aktualizací, i když to není totéž jako funkce, která vrací dobře definovaný typ.

Představte si postupy jako imperativní rutiny (s vedlejšími účinky) a funkcí jako čisté rutiny bez vedlejších účinků. A SELECT samotné prohlášení je také "čisté" bez vedlejších účinků (kromě potenciálních zamykacích efektů), takže má smysl uvažovat o funkcích jako o jediném typu rutin, které lze použít v SELECT prohlášení.

Ve skutečnosti si představte funkce jako rutiny se silnými omezeními chování, zatímco procedury mohou spouštět libovolné programy.

Jazyky 4GL vs. 3GL

Jiný způsob, jak se na to podívat, je z pohledu SQL jako 4. generace programovacího jazyka (4GL) . 4GL může rozumně fungovat pouze tehdy, je-li silně omezena v tom, co může dělat. Běžné tabulkové výrazy učinily SQL turing-complete , ano, ale deklarativní povaha SQL stále brání tomu, aby se z praktického a každodenního hlediska stal jazykem pro všeobecné použití.

Uložené procedury představují způsob, jak toto omezení obejít. Někdy chcete být kompletní a praktický. Uložené procedury se tedy uchylují k tomu, že jsou imperativní, mají vedlejší účinky, jsou transakční atd.

Uložené funkce představují chytrý způsob, jak některé představit 3GL / procedurální jazyk přináší do čistějšího světa 4GL za cenu zákazu vedlejších účinků uvnitř nich (pokud nechcete otevřít pandořinu skříňku a nemáte zcela nepředvídatelné SELECT prohlášení).

Skutečnost, že některé databáze umožňují, aby jejich uložené procedury vracely libovolný počet sad výsledků / kurzorů, je znakem toho, že umožňují libovolné chování, včetně vedlejších účinků. V zásadě nic z toho, co jsem řekl, nezabrání tomuto konkrétnímu chování také v uložených funkcích, ale bylo by velmi nepraktické a těžko ovladatelné, kdyby jim to bylo povoleno v kontextu SQL, jazyka 4GL.

Tedy:

  • Procedury mohou volat procedury, libovolnou funkci a SQL
  • „Čisté“ funkce mohou volat „čisté“ funkce a SQL
  • SQL může volat "čisté" funkce a SQL

Ale:

  • „Čisté“ funkce volající procedury se stávají „nečistými“ funkcemi (jako procedury)

A:

  • SQL nemůže volat procedury
  • SQL nemůže volat "nečisté" funkce

Příklady "čistých" funkcí s tabulkovou hodnotou:

Zde je několik příkladů použití „čistých“ funkcí s tabulkovou hodnotou:

Oracle

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

A pak:

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

A pak

SELECT * FROM my_function(1, 2)

PostgreSQL

Dovolte mi promluvit o PostgreSQL.

PostgreSQL je úžasný a tedy výjimka. Je to také zvláštní a pravděpodobně 50% jeho funkcí by nemělo být použito ve výrobě. Podporuje pouze "funkce", nikoli "procedury", ale tyto funkce mohou fungovat jako cokoliv. Podívejte se na následující:

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;

Vedlejší účinky:

  • Je vytvořena tabulka
  • Je vložen záznam

Přesto:

SELECT * FROM wow();

Výtěžky

wow
---
1


  1. rozdělení řádků v Redshift

  2. Mám v PHP/MySQL otevřít více databázových připojení nebo sdílet 1?

  3. SQL:jak používat UNION a objednávat podle konkrétního výběru?

  4. php mysql_connect Varování zakázat