Beim Programmieren sind zwei Dinge wichtig: zu verstehen, was abgeht (vor allem, wenn alles schief läuft), und nützliche Daten zurückzugeben. Das gilt besonders für PL/pgSQL, weil alles auf dem Server läuft und Debugging nicht immer easy ist. Zum Glück gibt’s eingebaute Tools:
RAISE NOTICE – das ist der Weg, Nachrichten während der Ausführung einer Funktion auszugeben. Stell’s dir wie console.log in JavaScript oder print in Python vor. Du kannst Variablenwerte zeigen, den aktuellen Status ausgeben oder einfach ein "Hallo" an dein zukünftiges Ich dalassen.
RETURN QUERY – damit gibst du einen Datensatz zurück, zum Beispiel eine ganze Tabelle oder das Ergebnis eines komplexen Queries. So werden PL/pgSQL-Funktionen fast wie echte SQL-Queries.
Befehl RAISE NOTICE
RAISE NOTICE lässt dich Nachrichten während der Funktionsausführung auf dem Bildschirm anzeigen. Das Format sieht so aus:
RAISE NOTICE 'Nachricht: %', wert;
%ist ein Platzhalter für eine Variable, ähnlich wieprintfin C.- Nach dem Nachrichtentext kannst du Variablen angeben, die eingesetzt werden sollen.
Beispiel für die Nutzung
Stell dir vor, du schreibst eine Funktion, die die Anzahl der Studenten in verschiedenen Gruppen zählt. Du willst Zwischenwerte sehen, um zu checken, ob alles läuft.
CREATE OR REPLACE FUNCTION count_students_in_groups() RETURNS VOID AS $$
DECLARE
group_name TEXT;
student_count INT;
BEGIN
FOR group_name IN SELECT DISTINCT group_name FROM students LOOP
SELECT COUNT(*) INTO student_count
FROM students WHERE group_name = group_name;
-- Ergebnisse ausgeben
RAISE NOTICE 'Gruppe: %, Anzahl der Studenten: %', group_name, student_count;
END LOOP;
END;
$$ LANGUAGE plpgsql;
Wenn du diese Funktion aufrufst:
SELECT count_students_in_groups();
Siehst du solche Nachrichten in den Logs:
NOTICE: Gruppe: Mathematik, Anzahl der Studenten: 30
NOTICE: Gruppe: Philosophie, Anzahl der Studenten: 25
NOTICE: Gruppe: Biologie, Anzahl der Studenten: 18
Beachte, dass die Funktion nichts zurückgibt (sie ist mit RETURNS VOID erstellt), aber RAISE NOTICE zeigt dir, wie die Schleife läuft.
Nützliche Tricks mit RAISE
Neben NOTICE kannst du auch andere Nachrichtenlevel nutzen:
RAISE DEBUG– für extra Infos (wird nur angezeigt, wenn das Log-Level auf DEBUG steht).RAISE INFO– für allgemeine Infos.RAISE WARNING– für Warnungen.RAISE EXCEPTION– um Fehler zu erzeugen, das schauen wir uns später noch an.
Zum Debuggen sind NOTICE oder DEBUG am besten, weil sie praktisch sind und die Funktion nicht stoppen.
Befehl RETURN QUERY: Daten zurückgeben wie ein Profi
RETURN QUERY wird in PL/pgSQL genutzt, um einen Satz von Zeilen zurückzugeben. Damit kannst du das Ergebnis eines SQL-Queries direkt aus der Funktion zurückgeben. Die Syntax ist so:
RETURN QUERY <SQL-Query>;
Du kannst auch mehrere Queries kombinieren:
RETURN QUERY <SQL-Query 1>;
RETURN QUERY <SQL-Query 2>;
Beispiel 1: Funktion mit RETURN QUERY
Wir schreiben eine Funktion, die eine Liste von Studenten aus einer bestimmten Gruppe zurückgibt.
CREATE OR REPLACE FUNCTION get_students_by_group(group_name TEXT)
RETURNS TABLE(id INT, name TEXT) AS $$
BEGIN
RETURN QUERY
SELECT id, name
FROM students
WHERE group_name = group_name;
END;
$$ LANGUAGE plpgsql;
Jetzt rufen wir die Funktion auf:
SELECT * FROM get_students_by_group('Mathematik');
Um die Funktion zu testen, erstellen wir zuerst die Tabelle students und fügen Daten ein:
CREATE TABLE students (
id SERIAL PRIMARY KEY,
name TEXT NOT NULL,
group_name TEXT NOT NULL
);
INSERT INTO students (name, group_name) VALUES
('Otto Song', 'Physik'),
('Alex Lin', 'Mathematik'),
('Anna Vel', 'Mathematik'),
('Maria Chi', 'Geschichte');
Ergebnis:
| id | name |
|---|---|
| 2 | Alex Lin |
| 3 | Anna Vel |
Wie du siehst, funktioniert die Funktion wie ein normaler SQL-Query.
Beispiel 2: Mehrere Queries kombinieren
Was, wenn wir kombinierte Daten aus mehreren Tabellen zurückgeben wollen? Lass uns eine Liste von Studenten und Kursen zurückgeben, für die sie eingeschrieben sind.
CREATE OR REPLACE FUNCTION get_students_and_courses()
RETURNS TABLE(student_name TEXT, course_name TEXT) AS $$
BEGIN
RETURN QUERY
SELECT s.name, c.name
FROM students s
JOIN enrollments e ON s.id = e.student_id
JOIN courses c ON e.course_id = c.id;
END;
$$ LANGUAGE plpgsql;
Erstmal erstellen wir drei Tabellen: students, courses und enrollments, und fügen ein paar Daten ein:
-- Tabelle Studenten
CREATE TABLE students (
id SERIAL PRIMARY KEY,
name TEXT NOT NULL
);
-- Tabelle Kurse
CREATE TABLE courses (
id SERIAL PRIMARY KEY,
name TEXT NOT NULL
);
-- Tabelle Einschreibungen (Verknüpfungstabelle)
CREATE TABLE enrollments (
student_id INT REFERENCES students(id),
course_id INT REFERENCES courses(id)
);
-- Studenten hinzufügen
INSERT INTO students (name) VALUES
('Otto Song'),
('Alex Lin'),
('Anna Vel'),
('Maria Chi');
-- Kurse hinzufügen
INSERT INTO courses (name) VALUES
('Mathematik'),
('Physik'),
('Geschichte');
-- Einschreibungen hinzufügen
INSERT INTO enrollments (student_id, course_id) VALUES
(1, 2), -- Otto -> Physik
(2, 1), -- Alex -> Mathematik
(3, 1), -- Anna -> Mathematik
(4, 3); -- Maria -> Geschichte
In diesem Fall gibt der Funktionsaufruf:
SELECT * FROM get_students_and_courses();
folgendes Ergebnis zurück:
| student_name | course_name |
|---|---|
| Otto Song | Physik |
| Alex Lin | Mathematik |
| Anna Vel | Mathematik |
| Maria Chi | Geschichte |
Die Funktion kombiniert sauber die Daten aus drei Tabellen und zeigt, welcher Student in welchem Kurs eingeschrieben ist.
Kombinieren von RAISE NOTICE und RETURN QUERY
Manchmal willst du RETURN QUERY und RAISE NOTICE in einer Funktion nutzen, damit du die Ausführung kontrollieren und Zwischenstände sehen kannst.
Hier ein Beispiel für eine Funktion, die Studentendaten zurückgibt und gleichzeitig Nachrichten ausgibt, um den Ablauf zu zeigen:
CREATE OR REPLACE FUNCTION debug_students()
RETURNS TABLE(student_id INT, student_name TEXT) AS $$
DECLARE
count_students INT;
BEGIN
-- Anzahl der Studenten zählen
SELECT COUNT(*) INTO count_students FROM students;
RAISE NOTICE 'Insgesamt Studenten: %', count_students;
-- Studentendaten zurückgeben
RETURN QUERY
SELECT id, name FROM students;
RAISE NOTICE 'Funktion wurde beendet.';
END;
$$ LANGUAGE plpgsql;
Falls die Tabelle students noch nicht existiert, erstelle sie und füge Daten ein:
CREATE TABLE students (
id SERIAL PRIMARY KEY,
name TEXT NOT NULL
);
INSERT INTO students (name) VALUES
('Otto Song'),
('Alex Lin'),
('Anna Vel'),
('Maria Chi');
Jetzt, wenn du die Funktion aufrufst:
SELECT * FROM debug_students();
bekommst du sowohl Daten als auch Nachrichten:
| student_id | student_name |
|---|---|
| 1 | Otto Song |
| 2 | Alex Lin |
| 3 | Anna Vel |
| 4 | Maria Chi |
Nachrichtenausgabe in der Konsole:
NOTICE: Insgesamt Studenten: 4
NOTICE: Funktion wurde beendet.
Typische Fehler bei der Nutzung
Fehler mit Variablen in RAISE NOTICE: Wenn du vergisst, eine Variable zu deklarieren oder dich im Namen vertippst, bekommst du den Fehler variable does not exist. Check immer, dass die Variablen korrekt deklariert sind.
Fehler beim Rückgabetyp: Wenn du RETURN QUERY nutzt, aber beim Erstellen der Funktion kein RETURNS TABLE angibst, gibt PostgreSQL einen Fehler aus. Achte darauf, dass die Rückgabetypen zu den zurückgegebenen Daten passen.
Fehler mit Platzhaltern in RAISE: Wenn die Anzahl der Platzhalter % nicht zu den Variablen passt, gibt’s einen Fehler. Zum Beispiel:
RAISE NOTICE 'Wert: %, %', value1;
Das führt zu einem Fehler, weil die zweite Variable fehlt.
GO TO FULL VERSION