Fra dokumentation på CONNECT_BY_ISCYCLE
:
CONNECT_BY_ISCYCLE
pseudokolonne returnerer 1
hvis den aktuelle række har et barn, som også er dens forfader
og det på CYCLE
:
En række anses for at danne en cyklus, hvis en af dens forfaderrækker har de samme værdier for cykluskolonnerne.
I dit eksempel, række 2
har et barn, som også er dets forfader, men dets id
er ikke returneret endnu.
Med andre ord, CONNECT_BY_ISCYCLE
tjekker børnene (som endnu ikke skal returneres), mens CYCLE
kontrollerer den aktuelle række (som allerede er returneret).
CONNECT BY
er rækkebaseret, mens rekursiv CTE
's er sæt-baserede.
Bemærk, at Oracles dokumentation om CYCLE
nævner en "forfaderrække". Men generelt set er der ikke noget begreb om en "forfaderrække" i en rekursiv CTE
. Det er en sæt-baseret operation, som kan give resultater helt ud af træet. Generelt kan ankerdelen og den rekursive del endda bruge de forskellige tabeller.
Siden rekursiv CTE
's er normalt bruges til at bygge hierarkitræer, Oracle
besluttede at tilføje et cyklustjek. Men på grund af den sæt-baserede måde den rekursive CTE
's fungerer, er det generelt umuligt at sige, om det næste trin vil generere en cyklus eller ej, for uden en klar definition af "forfaderrækken" kan cyklusbetingelsen heller ikke defineres.
For at udføre det "næste" trin skal hele det "aktuelle" sæt være tilgængeligt, men for at generere hver række i det aktuelle sæt (som inkluderer cykluskolonnen) skal vi blot have resultaterne af den "næste" operation.
Det er ikke et problem, hvis det aktuelle sæt altid består af en enkelt række (som i CONNECT BY
), men det er et problem, hvis den rekursive operation defineres på et sæt som en helhed.
Undersøgte ikke Oracle 11
endnu, men SQL Server
implementerer rekursiv CTE
ved blot at skjule en CONNECT BY
bag dem, hvilket kræver, at der placeres adskillige restriktioner (som alle reelt forbyder alle sæt-baserede operationer).
PostgreSQL
's implementering er på den anden side virkelig set-baseret:du kan udføre enhver operation med ankerdelen i den rekursive del. Det har dog ingen midler til at detektere cyklusser, fordi cyklusser ikke er defineret i første omgang.
Som nævnt før, MySQL
implementerer ikke CTE
's overhovedet (den implementerer ikke HASH JOIN
's eller MERGE JOIN
s også, kun de indlejrede løkker, så bliv ikke overrasket meget).
Ironisk nok modtog jeg et brev i dag om netop dette emne, som jeg vil dække i min blog.
Opdatering:
Rekursiv CTE
er i SQL Server
er ikke mere end CONNECT BY
i forklædning. Se denne artikel i min blog for chokerende detaljer:
- SQL-server:er de rekursive CTE'er virkelig set-baserede?