TL;DR :Sie können Wählen Sie aus (Tabellenwert-)Funktionen oder aus jeder Art von Funktion in PostgreSQL aus. Aber nicht von gespeicherten Prozeduren.
Hier ist eine "intuitive", etwas Datenbank-agnostische Erklärung, denn ich glaube, dass SQL und seine vielen Dialekte zu sehr eine organisch gewachsene Sprache / ein organisch gewachsenes Konzept sind, als dass es dafür eine grundlegende, "wissenschaftliche" Erklärung geben könnte.
Prozeduren vs. Funktionen, historisch
Ich sehe nicht wirklich den Sinn darin, aus gespeicherten Prozeduren auszuwählen, aber ich bin durch jahrelange Erfahrung voreingenommen und akzeptiere den Status quo, und ich sehe auf jeden Fall, wie der Unterschied zwischen Prozeduren ist und Funktionen verwirrend sein können und wie man sich wünschen würde, dass sie vielseitiger und leistungsfähiger sind. Insbesondere in SQL Server, Sybase oder MySQL können Prozeduren eine beliebige Anzahl von Ergebnismengen / Aktualisierungszählern zurückgeben, obwohl dies nicht dasselbe ist wie eine Funktion, die einen wohldefinierten Typ zurückgibt.
Stellen Sie sich Prozeduren als zwingende Routinen vor (mit Nebenwirkungen) und von Funktionen als reine Routinen ohne Nebenwirkungen. Ein SELECT
-Anweisung selbst ist auch "rein" ohne Nebenwirkungen (abgesehen von potenziellen Sperreffekten), daher ist es sinnvoll, sich Funktionen als die einzigen Arten von Routinen vorzustellen, die in einem SELECT
verwendet werden können Aussage.
Stellen Sie sich Funktionen als Routinen mit starken Verhaltensbeschränkungen vor, während Prozeduren beliebige Programme ausführen dürfen.
4GL vs. 3GL-Sprachen
Man kann dies auch aus der Perspektive betrachten, dass SQL eine Programmiersprache der vierten Generation (4GL) ist. . Eine 4GL kann nur dann vernünftig arbeiten, wenn sie in ihren Möglichkeiten stark eingeschränkt ist. Allgemeine Tabellenausdrücke haben SQL turing-complete gemacht , ja, aber die deklarative Natur von SQL verhindert immer noch, dass es aus praktischer, alltäglicher Sicht eine Allzwecksprache ist.
Gespeicherte Prozeduren sind eine Möglichkeit, diese Einschränkung zu umgehen. Manchmal möchten Sie vollständig zu sein und praktisch. Gespeicherte Prozeduren greifen also darauf zurück, zwingend erforderlich zu sein, Nebenwirkungen zu haben, transaktional zu sein usw.
Gespeicherte Funktionen sind eine clevere Art, einige einzuführen 3GL / prozedurale Sprachfeatures in die reinere 4GL-Welt um den Preis, Nebenwirkungen in ihnen zu verbieten (es sei denn, Sie möchten die Büchse der Pandora öffnen und haben völlig unvorhersehbare SELECT
Aussagen).
Die Tatsache, dass einige Datenbanken zulassen, dass ihre gespeicherten Prozeduren eine beliebige Anzahl von Ergebnismengen / Cursors zurückgeben, ist eine Eigenschaft ihres willkürlichen Verhaltens, einschließlich Nebenwirkungen. Im Prinzip würde nichts, was ich gesagt habe, dieses spezielle Verhalten auch in gespeicherten Funktionen verhindern, aber es wäre sehr unpraktisch und schwer zu handhaben, wenn sie dies im Kontext von SQL, der 4GL-Sprache, tun dürften.
Also:
- Prozeduren können Prozeduren, beliebige Funktionen und SQL aufrufen
- „Reine“ Funktionen können „reine“ Funktionen und SQL aufrufen
- SQL kann "reine" Funktionen und SQL aufrufen
Aber:
- „Reine“ Funktionen, die Prozeduren aufrufen, werden zu „unreinen“ Funktionen (wie Prozeduren)
Und:
- SQL kann keine Prozeduren aufrufen
- SQL kann keine "unreinen" Funktionen aufrufen
Beispiele für "reine" Tabellenwertfunktionen:
Hier sind einige Beispiele für die Verwendung von "reinen" Tabellenwertfunktionen:
Orakel
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;
/
Und dann:
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
Und dann
SELECT * FROM my_function(1, 2)
PostgreSQL
Lassen Sie mich etwas zu PostgreSQL sagen.
PostgreSQL ist genial und damit eine Ausnahme. Es ist auch seltsam und wahrscheinlich sollten 50 % seiner Funktionen nicht in der Produktion verwendet werden. Es unterstützt nur "Funktionen", keine "Prozeduren", aber diese Funktionen können als alles Mögliche fungieren. Sehen Sie sich Folgendes an:
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;
Nebenwirkungen:
- Eine Tabelle wird erstellt
- Ein Datensatz wird eingefügt
Dennoch:
SELECT * FROM wow();
Erträge
wow
---
1