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