0Pricing
SQL Academy · Lektion

Endlosschleifen vermeiden

Tiefenbegrenzungen und Zykluserkennung

Endlosschleifen vermeiden ist eine kostenlose SQL Academy-Lektion auf CoddyKit. Dies ist Lektion 4 von 4. Du kannst die komplette Lektion unten kostenlos lesen – dann übst du sie direkt im Browser mit einem integrierten Code-Editor und einem KI-Tutor rund um die Uhr. Sie ist Teil des SQL Academy-Lernpfads, und dein Fortschritt wird über Web und CoddyKit-App synchronisiert. Der SQL Academy-Kurs umfasst insgesamt 4 Lektionen.

Das Problem der Endlosschleife

Rekursive CTEs sind leistungsfähig, bergen aber ein ernst zu nehmendes Risiko: Wenn Ihre Abfrage nie einen Basisfall erreicht, läuft sie unendlich weiter, verbraucht den gesamten verfügbaren Speicher und bringt die Datenbanksitzung zum Absturz.

Zu verstehen, warum Endlosschleifen entstehen, ist der erste Schritt, um sie zu verhindern.

Wann endet eine Schleife nie?

Eine rekursive CTE läuft unbegrenzt weiter, wenn der rekursive Term fortlaufend neue Zeilen erzeugt, ohne jemals einen Zustand zu erreichen, in dem keine neuen Zeilen mehr generiert werden.

Das geschieht meist in zwei Fällen: bei einer fehlenden oder falschen Abbruchbedingung oder bei zyklischen Daten, in denen Knoten A auf B und B wieder auf A verweist.

-- Simple recursive CTE that WOULD loop forever
-- (do NOT run this as-is; illustration only)
WITH RECURSIVE counter AS (
  SELECT 1 AS n          -- base case
  UNION ALL
  SELECT n + 1           -- recursive term
  FROM counter
  -- no WHERE clause to stop it!
)
SELECT n FROM counter;

Ein Tiefenlimit hinzufügen

Die einfachste Schutzmaßnahme ist ein Tiefenzähler. Fügen Sie eine Spalte hinzu, die bei jedem rekursiven Schritt um 1 erhöht wird, und stoppen Sie, sobald sie eine maximale Tiefe überschreitet.

Damit endet die Abfrage unabhängig von den Daten, und das gewählte Limit bildet eine Sicherheitsgrenze.

WITH RECURSIVE counter AS (
  SELECT 1 AS n
  UNION ALL
  SELECT n + 1
  FROM counter
  WHERE n < 10       -- stop at depth 10
)
SELECT n FROM counter;

Tiefenlimit in einer Hierarchieabfrage

Beim Durchlaufen einer Mitarbeiterhierarchie können Sie die Tiefe zusammen mit dem Pfad verfolgen. Die Klausel WHERE depth < 5 verhindert, dass mehr als 5 Ebenen durchlaufen werden, selbst wenn die Daten tiefere oder zyklische Verknüpfungen enthalten.

CREATE TEMP TABLE employees (
  id   INT PRIMARY KEY,
  name TEXT,
  manager_id INT
);

INSERT INTO employees VALUES
  (1, 'Alice', NULL),
  (2, 'Bob',   1),
  (3, 'Carol', 2),
  (4, 'Dave',  3);

WITH RECURSIVE hierarchy AS (
  SELECT id, name, manager_id, 1 AS depth
  FROM employees
  WHERE manager_id IS NULL          -- root

  UNION ALL

  SELECT e.id, e.name, e.manager_id, h.depth + 1
  FROM employees e
  JOIN hierarchy h ON e.manager_id = h.id
  WHERE h.depth < 5                 -- depth limit
)
SELECT id, name, depth FROM hierarchy ORDER BY depth, id;

Was ist Zykluserkennung?

Ein Zyklus tritt in Graphdaten auf, wenn das Verfolgen von Kanten schließlich zu einem Knoten zurückführt, den Sie bereits besucht haben. Ein Beispiel: A → B → C → A.

Ein Tiefenlimit beendet die Abfrage auch bei zyklischen Daten, zeigt Ihnen aber nicht, wo der Zyklus liegt. Das leistet die explizite Zykluserkennung.

CREATE TEMP TABLE edges (
  from_node INT,
  to_node   INT
);

-- Introduce a cycle: 1->2->3->1
INSERT INTO edges VALUES
  (1, 2),
  (2, 3),
  (3, 1),   -- cycle back to 1
  (1, 4);   -- also a non-cyclic branch

SELECT * FROM edges;

Besuchte Knoten mit einem Array verfolgen

Eine robuste Technik zur Zykluserkennung besteht darin, ein Array mit den IDs besuchter Knoten durch die Rekursion zu führen. Bevor Sie den nächsten Knoten besuchen, prüfen Sie, ob er bereits im Array enthalten ist. Ist dies der Fall, überspringen Sie ihn.

PostgreSQL macht dies mit dem Operator ANY(array) und dem Array-Anfügeoperator || einfach.

WITH RECURSIVE traverse AS (
  -- Start from node 1
  SELECT from_node,
         to_node,
         ARRAY[from_node] AS visited
  FROM edges
  WHERE from_node = 1

  UNION ALL

  SELECT e.from_node,
         e.to_node,
         t.visited || e.from_node
  FROM edges e
  JOIN traverse t ON e.from_node = t.to_node
  WHERE NOT (e.from_node = ANY(t.visited))   -- skip visited nodes
)
SELECT from_node, to_node, visited
FROM traverse;

Die CYCLE-Klausel (PostgreSQL 14+)

PostgreSQL 14 führte eine integrierte CYCLE-Klausel für rekursive CTEs ein. Sie fügt automatisch zwei Spalten hinzu: ein boolesches Flag, das true ist, wenn ein Zyklus erkannt wird, und ein Array, das den durchlaufenen Pfad speichert.

Das ist sauberer, als das Array manuell zu verwalten.

WITH RECURSIVE traverse AS (
  SELECT from_node, to_node
  FROM edges
  WHERE from_node = 1

  UNION ALL

  SELECT e.from_node, e.to_node
  FROM edges e
  JOIN traverse t ON e.from_node = t.to_node
)
CYCLE from_node SET is_cycle USING path
SELECT from_node, to_node, is_cycle, path
FROM traverse;

Tiefenlimit und Zykluserkennung kombinieren

Die gemeinsame Verwendung eines Tiefenlimits und einer Zykluserkennung bietet die stärkste Sicherheitsgarantie:

  • Das Tiefenlimit bildet unabhängig von der Datenqualität eine feste Obergrenze.
  • Die Zykluserkennung stoppt sofort, sobald eine Schleife gefunden wird, und spart dadurch unnötige Iterationen.

Wenden Sie in Produktionsabfragen immer mindestens eine dieser Schutzmaßnahmen an.

WITH RECURSIVE traverse AS (
  SELECT from_node,
         to_node,
         1 AS depth,
         ARRAY[from_node] AS visited
  FROM edges
  WHERE from_node = 1

  UNION ALL

  SELECT e.from_node,
         e.to_node,
         t.depth + 1,
         t.visited || e.from_node
  FROM edges e
  JOIN traverse t ON e.from_node = t.to_node
  WHERE t.depth < 10                           -- depth limit
    AND NOT (e.from_node = ANY(t.visited))     -- cycle guard
)
SELECT from_node, to_node, depth, visited
FROM traverse;

Den vollständigen Pfad als Zeichenkette aufbauen

Zusätzlich zur Zykluserkennung ist es hilfreich, den vollständigen Durchlaufpfad als für Menschen lesbare Zeichenkette zu speichern. Durch die Verkettung von Knoten-IDs, die durch -> getrennt sind, können Sie den durch den Graphen genommenen Weg leicht anzeigen oder debuggen.

WITH RECURSIVE traverse AS (
  SELECT from_node,
         to_node,
         1 AS depth,
         ARRAY[from_node] AS visited,
         from_node::TEXT AS path_str
  FROM edges
  WHERE from_node = 1

  UNION ALL

  SELECT e.from_node,
         e.to_node,
         t.depth + 1,
         t.visited || e.from_node,
         t.path_str || ' -> ' || e.from_node::TEXT
  FROM edges e
  JOIN traverse t ON e.from_node = t.to_node
  WHERE t.depth < 10
    AND NOT (e.from_node = ANY(t.visited))
)
SELECT from_node, to_node, path_str, depth
FROM traverse
ORDER BY depth;

max_recursive_iterations festlegen

Einige Datenbanken (MariaDB, ältere MySQL-Versionen) verwenden eine Sitzungsvariable, um die Rekursion zu begrenzen. In PostgreSQL besteht der entsprechende Ansatz darin, sich auf den selbst implementierten Tiefenzähler oder auf Anweisungstimeouts zu verlassen.

Das Setzen von statement_timeout ist eine Schutzmaßnahme für den Notfall, die jede außer Kontrolle geratene Abfrage nach einer festgelegten Zeit beendet.

-- PostgreSQL: set a statement timeout as a safety net
SET statement_timeout = '5s';

-- Now any query that runs longer than 5 seconds is cancelled
WITH RECURSIVE counter AS (
  SELECT 1 AS n
  UNION ALL
  SELECT n + 1 FROM counter WHERE n < 1000000
)
SELECT MAX(n) FROM counter;

-- Reset to default when done
SET statement_timeout = '0';

Das richtige Tiefenlimit wählen

Es gibt kein allgemeingültiges Tiefenlimit. Wählen Sie Ihres anhand der maximal realistischen Tiefe Ihrer Daten:

  • Ein Organigramm überschreitet selten 10–15 Ebenen — verwenden Sie depth < 20 als großzügigen Puffer.
  • Ein Dateisystembaum kann 50–100 Ebenen tief sein.
  • Das Durchlaufen eines sozialen Netzwerks wird häufig auf 3–6 Sprünge begrenzt.

Setzen Sie das Limit hoch genug, um gültige Daten zu erfassen, aber niedrig genug, um außer Kontrolle geratene Abfragen frühzeitig zu erkennen.

-- Example: org chart with a generous but safe depth cap
WITH RECURSIVE org AS (
  SELECT id, name, manager_id, 1 AS depth
  FROM employees
  WHERE manager_id IS NULL

  UNION ALL

  SELECT e.id, e.name, e.manager_id, o.depth + 1
  FROM employees e
  JOIN org o ON e.manager_id = o.id
  WHERE o.depth < 20    -- realistic upper bound for an org chart
)
SELECT id, name, depth
FROM org
ORDER BY depth, name;

Tiefenlimits oder Zykluserkennung

Welche Technik sollten Sie verwenden?

Zusammenfassung: Rekursive Abfragen sicher halten

Hier ist eine Zusammenfassung dessen, was Sie über das Vermeiden von Endlosschleifen in rekursiven CTEs gelernt haben:

  • Tiefenlimit — fügen Sie eine Zählerspalte hinzu und stoppen Sie mit WHERE depth < N. Immer wirksam und einfach zu implementieren.
  • Array-basierte Zykluserkennung — führen Sie die IDs besuchter Knoten in einem Array weiter und überspringen Sie jeden bereits enthaltenen Knoten. Stoppt beim ersten Zyklus.
  • CYCLE-Klausel (PostgreSQL 14+) — integrierte Syntax, die die Zyklusverfolgung mit den Spalten is_cycle und path automatisiert.
  • statement_timeout — eine Schutzmaßnahme auf Datenbankebene für außer Kontrolle geratene Abfragen, aber kein Ersatz für eine korrekte Logik.
  • Beides kombinieren — verwenden Sie in Produktionsabfragen sowohl ein Tiefenlimit als auch eine Zykluserkennung, um die größtmögliche Sicherheit zu gewährleisten.

Mit diesen Techniken können Sie Hierarchien und Graphen zuverlässig durchlaufen, ohne Datenbankabstürze zu riskieren.

Häufig gestellte Fragen

Ist die Lektion „Endlosschleifen vermeiden“ kostenlos?

Ja — der vollständige Text von „Endlosschleifen vermeiden“ ist hier im Web kostenlos zu lesen. Um sie interaktiv zu üben (integrierter Code-Editor und 24/7 KI-Tutor) und den Rest des SQL Academy-Kurses freizuschalten, upgrade auf CoddyKit PRO. Der SQL Academy-Kurs umfasst insgesamt 4 Lektionen.

Was lerne ich in „Endlosschleifen vermeiden“?

Tiefenbegrenzungen und Zykluserkennung Du übst SQL Academy mit praktischem Code, den du direkt im Browser ausführst, und ein 24/7 KI-Tutor beantwortet deine Fragen während du die Lektion bearbeitest.

Brauche ich Erfahrung, um SQL Academy zu starten?

Keine Vorkenntnisse erforderlich. SQL Academy auf CoddyKit ist für Anfänger bis fortgeschrittene Lernende strukturiert, sodass du hier starten oder von Anfang an beginnen und in deinem eigenen Tempo voranschreiten kannst. Dies ist Lektion 4 von 4.

Wie lange dauert die Lektion „Endlosschleifen vermeiden“?

Die meisten CoddyKit-Lektionen dauern etwa 5–10 Minuten. Jede ist kompakt und interaktiv, sodass du stetig Fortschritte machst und genau dort weitermachst, wo du aufgehört hast – im Web und in der App.

Kann ich in dieser SQL Academy-Lektion Code schreiben und ausführen?

Ja. Jede SQL Academy-Lektion enthält einen integrierten Code-Editor, sodass du echten Code direkt in deinem Browser schreibst und ausführst und sofort KI-Feedback erhältst — ohne lokale Einrichtung erforderlich.

Alle Lektionen in diesem Kurs

  1. So funktionieren rekursive CTEs
  2. Einen Kategoriebaum durchlaufen
  3. Sequenzen und Reihen erzeugen
  4. Endlosschleifen vermeiden
← Zurück zu SQL Academy