Oneindige lussen vermijden
Dieptelimieten en cyclusdetectie.
Oneindige lussen vermijden is een gratis SQL Academy-les op CoddyKit. Dit is les 4 van 4. Je kunt de volledige les hieronder gratis lezen en daarna in de browser praktisch oefenen met een ingebouwde code-editor en een AI-begeleider die 24/7 beschikbaar is. Deze les maakt deel uit van het leertraject SQL Academy. Je voortgang wordt gesynchroniseerd op het web en in de CoddyKit-app. De cursus SQL Academy bevat in totaal 4 lessen.
Het probleem van de oneindige lus
Recursieve CTE's zijn krachtig, maar brengen een serieus risico met zich mee: als je query nooit een basisgeval bereikt, blijft deze voor altijd doorlopen. Daarbij wordt al het beschikbare geheugen verbruikt en loopt de databasesessie vast.
Begrijpen waarom oneindige lussen ontstaan, is de eerste stap om ze te voorkomen.
Wanneer eindigt een lus niet?
Een recursieve CTE blijft oneindig doorlopen wanneer de recursieve term nieuwe rijen blijft produceren zonder ooit een toestand te bereiken waarin geen nieuwe rijen meer worden gegenereerd.
Dit gebeurt meestal in twee situaties: bij een ontbrekende of onjuiste beëindigingsvoorwaarde, of bij cyclische gegevens waarbij knooppunt A naar B verwijst en B terug naar A.
-- 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;Een dieptelimiet toevoegen
De eenvoudigste beveiliging is een diepteteller. Voeg een kolom toe die bij elke recursieve stap met 1 wordt verhoogd en stop wanneer de maximale diepte wordt overschreden.
Zo wordt beëindiging gegarandeerd, ongeacht de gegevens, en vormt de gekozen limiet een veiligheidsgrens.
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;Dieptelimiet in een hiërarchische query
Bij het doorlopen van een hiërarchie van medewerkers kun je de diepte naast het pad bijhouden. De clausule WHERE depth < 5 voorkomt dat je verder dan 5 niveaus doorloopt, zelfs als de gegevens diepere of circulaire koppelingen bevatten.
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;Wat is cyclusdetectie?
Een cyclus ontstaat in graafgegevens wanneer het volgen van verbindingen uiteindelijk leidt naar een knooppunt dat je al hebt bezocht. Bijvoorbeeld: A → B → C → A.
Een dieptelimiet beëindigt de query nog steeds in cyclische gegevens, maar vertelt je niet waar de cyclus zich bevindt. Expliciete cyclusdetectie doet dat wel.
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;Bezochte knooppunten bijhouden met een array
Een robuuste techniek voor cyclusdetectie is om tijdens de recursie een array met ID's van bezochte knooppunten mee te voeren. Controleer voordat je het volgende knooppunt bezoekt of het al in de array staat. Als dat zo is, sla je het over.
PostgreSQL maakt dit eenvoudig met de operator ANY(array) en de operator || voor het toevoegen aan een array.
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;De CYCLE-clausule (PostgreSQL 14+)
PostgreSQL 14 introduceerde een ingebouwde CYCLE-clausule voor recursieve CTE's. Deze voegt automatisch twee kolommen toe: een booleaanse markering die true is wanneer een cyclus wordt gedetecteerd, en een array waarin het gevolgde pad wordt vastgelegd.
Dit is overzichtelijker dan de array handmatig bijhouden.
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;Dieptelimiet en cyclusdetectie combineren
Door zowel een dieptelimiet als cyclusdetectie te gebruiken, krijg je de sterkste beveiliging:
- De dieptelimiet vormt een harde grens, ongeacht de kwaliteit van de gegevens.
- Cyclusdetectie stopt meteen zodra een lus wordt gevonden, waardoor onnodige iteraties worden bespaard.
Pas in query's voor productie altijd minstens één van deze beveiligingen toe.
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;Het volledige pad als tekenreeks opbouwen
Naast cyclusdetectie is het handig om het volledige doorlooppad vast te leggen als een voor mensen leesbare tekenreeks. Door knooppunt-ID's te concatenëren en te scheiden met -> , kun je de gevolgde route door de graaf eenvoudig weergeven of 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 instellen
Sommige databases (MariaDB, oudere MySQL-versies) gebruiken een sessievariabele om recursie te begrenzen. In PostgreSQL is de equivalente aanpak het gebruiken van de diepteteller die je zelf schrijft, of van time-outs op instructieniveau.
Het instellen van een statement_timeout is een laatste veiligheidsnet dat elke op hol geslagen query na een bepaalde tijd beëindigt.
-- 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';De juiste dieptelimiet kiezen
Er bestaat geen universele dieptelimiet. Kies er een op basis van de maximaal realistische diepte in je gegevens:
- Een organisatieschema is zelden dieper dan 10-15 niveaus — gebruik
depth < 20als comfortabele buffer. - Een boomstructuur van een bestandssysteem kan 50-100 niveaus diep gaan.
- Het doorlopen van een graaf van een sociaal netwerk wordt vaak beperkt tot 3-6 stappen.
Stel de limiet hoog genoeg in om geldige gegevens op te nemen, maar laag genoeg om op hol geslagen query's vroeg te onderscheppen.
-- 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;Dieptelimieten versus cyclusdetectie
Welke techniek moet je gebruiken?
Samenvatting: recursieve query's veilig houden
Hier volgt een samenvatting van wat je hebt geleerd over het voorkomen van oneindige lussen in recursieve CTE's:
- Dieptelimiet — voeg een tellende kolom toe en stop met
WHERE depth < N. Altijd effectief en eenvoudig te implementeren. - Cyclusdetectie op basis van een array — neem ID's van bezochte knooppunten mee in een array en sla elk knooppunt over dat er al in staat. Stopt meteen bij de eerste cyclus.
- CYCLE-clausule (PostgreSQL 14+) — ingebouwde syntaxis die het bijhouden van cycli automatiseert met de kolommen
is_cycleenpath. - statement_timeout — een veiligheidsnet op databaseniveau voor op hol geslagen query's, maar geen vervanging voor de juiste logica.
- Combineer beide: gebruik in productie zowel een dieptelimiet als cyclusdetectie voor de sterkste garantie.
Met deze technieken kun je hiërarchieën en grafen vol vertrouwen doorlopen zonder dat de database dreigt vast te lopen.
Leer SQL met een AI-tutor — gratis
Schrijf echte code en voer die uit in je browser, krijg direct hulp van een AI-tutor die 24/7 beschikbaar is en ga verder waar je gebleven bent op het web of in de app.
- Cursussen
- 46
- Lessen
- 183
Veelgestelde vragen
Is de les “Oneindige lussen vermijden” gratis?
Ja — de volledige tekst van “Oneindige lussen vermijden” kun je hier gratis op het web lezen. Als je interactief wilt oefenen met een ingebouwde code-editor en een AI-begeleider die 24/7 beschikbaar is, en de rest van de cursus SQL Academy wilt ontgrendelen, kun je upgraden naar CoddyKit PRO. De cursus SQL Academy bevat in totaal 4 lessen.
Wat leer ik in “Oneindige lussen vermijden”?
Dieptelimieten en cyclusdetectie. Je oefent met SQL Academy door code rechtstreeks in de browser uit te voeren. Een AI-begeleider die 24/7 beschikbaar is beantwoordt je vragen terwijl je de les doorwerkt.
Heb ik ervaring nodig om met SQL Academy te beginnen?
Ervaring vooraf is niet nodig. SQL Academy op CoddyKit is opgebouwd voor beginners tot gevorderden, zodat je hier of bij het begin kunt starten en in je eigen tempo kunt leren. Dit is les 4 van 4.
Hoe lang duurt de les “Oneindige lussen vermijden”?
De meeste lessen van CoddyKit duren ongeveer 5–10 minuten. Elke les is kort en interactief, zodat je gestaag vooruitgaat en op het web en in de app precies verdergaat waar je was gebleven.
Kan ik code schrijven en uitvoeren in deze les over SQL Academy?
Ja. Elke les over SQL Academy bevat een ingebouwde code-editor, zodat je rechtstreeks in je browser echte code kunt schrijven en uitvoeren en direct feedback van AI krijgt — lokale installatie is niet nodig.
Alle lessen in deze cursus
- Hoe recursieve CTE's werken
- Een categoriestructuur doorlopen
- Reeksen genereren
- Oneindige lussen vermijden