In vielen Programmiersprachen gibt es kaum Unterschiede zwischen Funktionen und Prozeduren. In SQL gibt es sie aber. In PostgreSQL sind Funktionen und Prozeduren nicht einfach zwei Wege, Code auszuführen. Es sind unterschiedliche Denkweisen.
Eine Funktion in SQL darf keine Daten in der Datenbank ändern. Sie arbeitet nur mit den übergebenen Daten und gibt darauf basierend ein Ergebnis zurück. Sie ist dafür gedacht, innerhalb von SELECT-Statements verwendet zu werden.
Eine Prozedur in SQL ist dafür da, die Datenbank zu verändern. Sie kann mit Transaktionen arbeiten (im Gegensatz zu Funktionen), etwas in die DB schreiben. Und sie kann nicht innerhalb von SELECT-Statements verwendet werden.
Hier ein kurzer Vergleich:
| Eigenschaft | Funktion (FUNCTION) | Prozedur (PROCEDURE) |
|---|---|---|
| Gibt Daten zurück | ✅ Ja (RETURNS ...) |
❌ Nein (kann nur Aktionen ausführen) |
| Wird aufgerufen mit | SELECT, PERFORM |
CALL |
| Kann in Abfragen verwendet werden | ✅ Ja | ❌ Nein |
Kann in DO verwendet werden |
✅ Ja | ❌ Nein |
Unterstützt COMMIT, ROLLBACK |
❌ Nein | ✅ Ja |
| Seit wann in PostgreSQL | Von Anfang an | Seit Version 11 |
Unterschiede in SQL
Im normalen SQL ist eine Funktion wie ein Ausdruck: Sie berechnet und gibt einen Wert zurück. Eine Prozedur ist eine Anweisung: Sie macht etwas, nimmt aber nicht an Ausdrücken teil.
Funktion in SQL
SELECT calculate_discount(200);
- Kann in
WHERE,ORDER BY,INSERT,UPDATEusw. verwendet werden. - Muss rein sein: darf den Zustand der DB nicht ändern (wenn IMMUTABLE/STABLE).
Prozedur in SQL
CALL process_order(123);
- Gibt kein Ergebnis zurück.
- Kann
COMMIT,ROLLBACKmachen,RAISEaufrufen, Schleifen starten.
Unterschiede in PL/pgSQL
Funktionen in PostgreSQL kann man sich als Gruppe von Berechnungen vorstellen. Sie sind sehr flexibel: Man kann Parameter übergeben, Bedingungen, Schleifen, Cursor, Subqueries nutzen, Zeilen, Skalare, Tabellen zurückgeben.
Funktionen in PL/pgSQL
CREATE FUNCTION square(x INT) RETURNS INT AS $$
BEGIN
RETURN x * x;
END;
$$ LANGUAGE plpgsql;
Besonderheiten:
RETURNSist Pflicht- Kann
DECLARE,BEGIN,END,LOOP,IF,CASEverwenden COMMIT/ROLLBACKsind nicht erlaubt- Kann in
SELECT,UPDATE,CHECK,WHERE,RETURNINGaufgerufen werden
Aufruf:
SELECT square(5); -- gibt 25 zurück
Prozeduren in PL/pgSQL
Prozeduren sind ein Mechanismus zur Steuerung von Aktionen. Sie sind ideal, wenn du:
- Viele Schritte mit Logik ausführen willst;
- Große Datenmengen aktualisieren und einfügen willst;
- Transaktionssteuerung brauchst:
COMMIT,ROLLBACK,SAVEPOINT.
CREATE PROCEDURE log_event(msg TEXT) AS $$
BEGIN
INSERT INTO logs(message) VALUES (msg);
COMMIT;
END;
$$ LANGUAGE plpgsql;
Besonderheiten:
- Kein
RETURNS - Wird nur mit
CALLaufgerufen COMMIT,ROLLBACK,SAVEPOINTsind erlaubt- Geeignet für Batch-Verarbeitung, Migrationen, ETL
Aufruf:
CALL log_event('Verarbeitung abgeschlossen');
Warum sind Funktionen und Prozeduren getrennt?
Weil sie unterschiedliche Ziele in SQL haben:
| Funktionen | Prozeduren |
|---|---|
| "Etwas berechnen und zurückgeben" | "Etwas machen und kein Ergebnis zurückgeben" |
| Aufruf aus SQL | Aufruf als Befehl |
| Können keine Transaktionen steuern | Können Transaktionen steuern |
Werden in SELECT, JOIN, WHERE verwendet |
Werden in CALL, Skripten verwendet |
Das wichtigste Prozedur-Feature — COMMIT
Prozeduren können Transaktionen in sich steuern. Das heißt, direkt in der Prozedur kannst du:
BEGIN;
-- logik
SAVEPOINT punkt1;
-- update-versuch
ROLLBACK TO punkt1;
COMMIT;
Und in Funktionen sind COMMIT und ROLLBACK verboten. Wenn du es versuchst, bekommst du: ERROR: invalid transaction termination in function
Das heißt, eine Funktion muss deterministisch und sicher sein, während eine Prozedur "dirty work" machen kann — aufräumen, loggen, einfügen.
Vergleichstabelle
| Besonderheit | FUNCTION |
PROCEDURE |
|---|---|---|
| Gibt Wert zurück | ✅ RETURNS |
❌ |
Wird in SELECT verwendet |
✅ | ❌ |
| Aufruf | SELECT, PERFORM, DO |
Nur CALL |
| Kann in Trigger verwendet werden | ✅ | ❌ (nur Funktionen) |
Transaktionen drin (COMMIT) |
❌ Verboten | ✅ Erlaubt |
| OUT-Parameter verwenden | Über RETURNS TABLE, RECORD |
Direkt über OUT-Parameter |
| Geeignet für Berechnungen | ✅ | 🚫 nicht gedacht |
| Geeignet für ETL, Laden | 🚫 eingeschränkt | ✅ ideal |
| Kann Cursor verwenden | ✅ Ja | ✅ Ja |
Wann was verwenden?
Verwende eine Funktion, wenn:
- du einen Rückgabewert willst;
- du sie in
SELECTaufrufst, Daten filterst; - es eine einfache Berechnung, Prüfung oder ein Wrapper für SQL ist.
Verwende eine Prozedur, wenn:
- du komplexe Aktionen ausführen willst;
- du Transaktionskontrolle brauchst;
- du Batches verarbeitest, Daten verschiebst, archivierst, loggst.
GO TO FULL VERSION