Verschachtelte Schleifen sind Schleifen, die innerhalb anderer Schleifen laufen. Stell dir eine Interview-Fragerunde vor, bei der eine Frage zu weiteren Nachfragen führt. Die Logik von verschachtelten Schleifen ist: Die äußere Schleife macht eine Iteration, und die innere Schleife läuft für jede Iteration der äußeren Schleife durch.
Beispiel: Einmaleins-Tabelle
Wir schreiben eine Funktion, die eine Einmaleins-Tabelle für die Zahlen von 1 bis 5 erstellt. Das ist ein klassisches Beispiel für verschachtelte Schleifen:
CREATE OR REPLACE FUNCTION generate_multiplication_table()
RETURNS VOID AS $$
BEGIN
FOR i IN 1..5 LOOP -- Äußere Schleife
FOR j IN 1..5 LOOP -- Innere Schleife
RAISE NOTICE '% x % = %', i, j, i * j; -- Ergebnis loggen
END LOOP;
END LOOP;
END;
$$ LANGUAGE plpgsql;
-- Funktionsaufruf:
SELECT generate_multiplication_table();
So funktioniert's:
- Die äußere Schleife nimmt die Werte
ivon 1 bis 5. - Für jeden Wert von
inimmt die innere Schleife die Wertejvon 1 bis 5. - Bei jedem Schritt werden
iundjkombiniert, um das Ergebnis der Multiplikation zu berechnen. - Die Ausgabe sieht wie eine Mini-Tabelle aus:
1 x 1 = 1
1 x 2 = 2
...
5 x 5 = 25
Praxis: Schnittmengen in zwei Tabellen finden
Jetzt machen wir ein etwas "realistischeres" Beispiel. Stell dir vor, wir haben zwei Tabellen:
students(Studenten, ihre Namen),courses(Kurse, für die sie eingeschrieben sind).
Wir wollen Studenten finden, die in mehr als einem Kurs eingeschrieben sind. Wir nutzen verschachtelte Schleifen:
CREATE OR REPLACE FUNCTION find_students_with_multiple_courses()
RETURNS TABLE(student_name TEXT, course_name TEXT) AS $$
BEGIN
FOR student IN SELECT DISTINCT student_name FROM students LOOP
FOR course IN SELECT DISTINCT course_name FROM courses WHERE student_id = student.student_id LOOP
RETURN QUERY SELECT student.student_name, course.course_name;
END LOOP;
END LOOP;
END;
$$ LANGUAGE plpgsql;
-- Funktionsaufruf:
SELECT * FROM find_students_with_multiple_courses();
Rekursion
Rekursion bedeutet, dass eine Funktion sich selbst aufruft. Das ist so, als würdest du einen Kumpel bitten, SQL zu erklären, und er sagt: Lies die Doku, die wiederum auf diese Lektion verweist… Verwechsele Rekursion nicht mit einer Endlosschleife. Bei Rekursion gibt es immer eine "Abbruchbedingung" (der Punkt, an dem die Funktion aufhört, sich selbst aufzurufen).
Beispiel: Fakultät einer Zahl berechnen
Die Fakultät einer Zahl n ist das Produkt aller Zahlen von 1 bis n. Zum Beispiel ist die Fakultät von 5 (geschrieben als 5!) 5 * 4 * 3 * 2 * 1 = 120. So kann man das mit Rekursion umsetzen:
CREATE OR REPLACE FUNCTION calculate_factorial(n INTEGER)
RETURNS INTEGER AS $$
BEGIN
-- Abbruchbedingung: Fakultät von 0 oder 1 ist 1
IF n = 0 OR n = 1 THEN
RETURN 1;
END IF;
-- Rekursiver Funktionsaufruf
RETURN n * calculate_factorial(n - 1);
END;
$$ LANGUAGE plpgsql;
-- Funktionsaufruf:
SELECT calculate_factorial(5); -- Ergebnis: 120
So funktioniert's:
- Wenn
n0 oder 1 ist, wird 1 zurückgegeben. - Wenn
n > 1, ruft die Funktion sich selbst mit dem Argumentn - 1auf und multipliziert das Ergebnis mitn. - So "stapeln" sich die Aufrufe und werden dann in eine Richtung aufgelöst.
Praktisches Beispiel: Fibonacci-Zahlen
Fibonacci-Zahlen sind eine Zahlenfolge, bei der jede Zahl die Summe der beiden vorherigen ist. Die Folge beginnt so: 0, 1, 1, 2, 3, 5, 8....
Schreiben wir eine Funktion, die die n-te Zahl der Folge berechnet:
CREATE OR REPLACE FUNCTION fibonacci(n INTEGER)
RETURNS INTEGER AS $$
BEGIN
-- Abbruchbedingung: Die ersten zwei Zahlen sind bekannt
IF n = 0 THEN
RETURN 0;
ELSIF n = 1 THEN
RETURN 1;
END IF;
-- Rekursiver Funktionsaufruf
RETURN fibonacci(n - 1) + fibonacci(n - 2);
END;
$$ LANGUAGE plpgsql;
-- Funktionsaufruf:
SELECT fibonacci(6); -- Ergebnis: 8
Wann sollte man verschachtelte Schleifen und Rekursion verwenden?
Verschachtelte Schleifen sind super für Tabellenarbeit:
- Vergleiche von Werten zwischen zwei Tabellen.
- Komplexe Datenkombinationen bauen.
Rekursion ist besser für:
- Berechnung von Folgen (z.B. Fakultäten, Fibonacci).
- Arbeiten mit hierarchischen Strukturen (z.B. Kategoriebaum für Produkte).
Typische Fehler
Verschachtelte Schleifen sind manchmal echte Performance-Killer, besonders bei großen Tabellen. Nutze sie nur, wenn du das Ergebnis nicht mit normalen SQL-Mitteln bekommst.
Bei Rekursion musst du unbedingt eine klare "Abbruchbedingung" haben. Sonst bekommst du einen endlosen Funktionsaufruf und wahrscheinlich einen Stack Overflow.
Komplexe verschachtelte Konstrukte können das Debugging erschweren. Hilf dir mit RAISE NOTICE, um Zwischenergebnisse auszugeben.
GO TO FULL VERSION