TL;DR :du kan vælg fra (tabel-værdi) funktioner, eller fra enhver form for funktion i PostgreSQL. Men ikke fra lagrede procedurer.
Her er en "intuitiv", noget databaseagnostisk forklaring, for jeg mener, at SQL og dets mange dialekter er for meget et organisk dyrket sprog/begreb til, at der kan være en grundlæggende, "videnskabelig" forklaring på dette.
Procedurer vs. funktioner, historisk
Jeg kan ikke rigtig se meningen med at vælge fra lagrede procedurer, men jeg er forudindtaget af mange års erfaring og accepterer status quo, og jeg kan bestemt se, hvordan skelnen mellem procedurer og funktioner kan være forvirrende, og hvordan man ville ønske, at de var mere alsidige og kraftfulde. Specifikt i SQL Server, Sybase eller MySQL kan procedurer returnere et vilkårligt antal resultatsæt/opdateringsantal, selvom dette ikke er det samme som en funktion, der returnerer en veldefineret type.
Tænk på procedurer som imperative rutiner (med bivirkninger) og fungerer som rene rutiner uden bivirkninger. En SELECT
selve erklæringen er også "ren" uden bivirkninger (bortset fra potentielle låseeffekter), så det giver mening at tænke på funktioner som de eneste typer rutiner, der kan bruges i en SELECT
erklæring.
Tænk faktisk på funktioner som værende rutiner med stærke begrænsninger på adfærd, hvorimod procedurer tillades at udføre vilkårlige programmer.
4GL vs. 3GL sprog
En anden måde at se dette på er fra perspektivet, at SQL er et 4. generations programmeringssprog (4GL) . En 4GL kan kun fungere rimeligt, hvis den er stærkt begrænset i, hvad den kan. Almindelige tabeludtryk gjort SQL turing-komplet , ja, men den deklarative karakter af SQL forhindrer stadig, at det er et sprog til generelle formål fra et praktisk, dagligdags perspektiv.
Lagrede procedurer er en måde at omgå denne begrænsning på. Nogle gange vil du at være turing komplet og praktisk. Så lagrede procedurer tyer til at være tvingende, have bivirkninger, være transaktionelle osv.
Lagrede funktioner er en smart måde at introducere nogle på 3GL / proceduremæssige sprogfunktioner ind i den renere 4GL-verden til prisen for at forbyde bivirkninger inde i dem (medmindre du vil åbne pandoras æske og have fuldstændig uforudsigelig SELECT
udsagn).
Det faktum, at nogle databaser tillader, at deres lagrede procedurer returnerer vilkårlige antal resultatsæt/markører, er et træk ved, at de tillader vilkårlig adfærd, inklusive bivirkninger. I princippet ville intet, jeg sagde, forhindre denne særlige adfærd også i lagrede funktioner, men det ville være meget upraktisk og svært at administrere, hvis de fik lov til at gøre det inden for konteksten af SQL, 4GL-sproget.
Således:
- Procedurer kan kalde procedurer, enhver funktion og SQL
- "Rene" funktioner kan kalde "rene" funktioner og SQL
- SQL kan kalde "rene" funktioner og SQL
Men:
- "Rene" funktioner kalder procedurer bliver "urene" funktioner (som procedurer)
Og:
- SQL kan ikke kalde procedurer
- SQL kan ikke kalde "urene" funktioner
Eksempler på "rene" tabelværdierede funktioner:
Her er nogle eksempler på brug af tabelværdier, "rene" funktioner:
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;
/
Og så:
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
Og så
SELECT * FROM my_function(1, 2)
PostgreSQL
Lad mig få et ord om PostgreSQL.
PostgreSQL er fantastisk og dermed en undtagelse. Det er også mærkeligt, og sandsynligvis bør 50% af dets funktioner ikke bruges i produktionen. Det understøtter kun "funktioner", ikke "procedurer", men disse funktioner kan fungere som hvad som helst. Tjek følgende:
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;
Bivirkninger:
- Der oprettes en tabel
- En post er indsat
Alligevel:
SELECT * FROM wow();
Udbytte
wow
---
1