Oracle
 sql >> Datenbank >  >> RDS >> Oracle

Zyklenerkennung mit rekursiver Subquery-Factoring

Aus der Dokumentation zu CONNECT_BY_ISCYCLE :

Der CONNECT_BY_ISCYCLE Pseudospalte gibt 1 zurück wenn die aktuelle Zeile ein Kind hat, das auch ihr Vorfahre ist

und das auf CYCLE :

Eine Zeile wird als Zyklus angesehen, wenn eine ihrer Vorgängerzeilen die gleichen Werte für die Zyklusspalten hat.

In Ihrem Beispiel Zeile 2 hat ein Kind, das auch sein Vorfahre ist, aber seine id wurde noch nicht zurückgegeben.

Mit anderen Worten, CONNECT_BY_ISCYCLE überprüft die Kinder (die noch zurückgegeben werden müssen), während CYCLE überprüft die aktuelle Zeile (die bereits zurückgegeben wird).

CONNECT BY ist zeilenbasiert, während rekursiv CTE sind satzbasiert.

Beachten Sie, dass die Dokumentation von Oracle auf CYCLE erwähnt eine "Ahnenreihe". Im Allgemeinen gibt es jedoch kein Konzept einer "Vorfahrenzeile" in einem rekursiven CTE . Es handelt sich um eine mengenbasierte Operation, die Ergebnisse vollständig aus dem Baum heraus liefern kann. Im Allgemeinen können der Ankerteil und der rekursive Teil sogar die unterschiedlichen Tabellen verwenden.

Seit rekursivem CTE sind normalerweise Wird verwendet, um Hierarchiebäume zu erstellen, Oracle beschlossen, eine Zyklusprüfung hinzuzufügen. Aber aufgrund des mengenbasierten Weges der rekursive CTE 's funktionieren, ist es im Allgemeinen unmöglich zu sagen, ob der nächste Schritt einen Zyklus erzeugt oder nicht, da ohne eine klare Definition der "Ahnenreihe" auch keine Zyklusbedingung definiert werden kann.

Um den "nächsten" Schritt auszuführen, muss der gesamte "aktuelle" Satz verfügbar sein, aber um jede Zeile des aktuellen Satzes (einschließlich der Zyklusspalte) zu generieren, brauchen wir nur die Ergebnisse der "nächsten" Operation.

Es ist kein Problem, wenn der aktuelle Satz immer aus einer einzigen Zeile besteht (wie in CONNECT BY ), aber es ist ein Problem, wenn die rekursive Operation auf einer Menge als Ganzes definiert ist.

Ich habe mir Oracle 11 nicht angeschaut noch, aber SQL Server implementiert rekursiven CTE durch einfaches Ausblenden eines CONNECT BY hinter ihnen, was das Platzieren zahlreicher Einschränkungen erfordert (die alle effektiv alle satzbasierten Operationen verbieten).

PostgreSQL Die Implementierung von hingegen ist wirklich mengenbasiert:Sie können jede Operation mit dem Ankerteil im rekursiven Teil ausführen. Es hat jedoch keine Möglichkeit, Zyklen zu erkennen, da Zyklen von vornherein nicht definiert sind.

Wie bereits erwähnt, MySQL implementiert CTE nicht überhaupt (es implementiert HASH JOIN nicht 's oder MERGE JOIN s auch, nur die verschachtelten Schleifen, also wundern Sie sich nicht allzu sehr).

Ironischerweise habe ich heute einen Brief zu genau diesem Thema erhalten, das ich in meinem Blog behandeln werde.

Aktualisierung:

Rekursiver CTE 's in SQL Server sind nicht mehr als CONNECT BY verkleidet. Siehe diesen Artikel in meinem Blog für schockierende Details:

  • SQL Server:Sind die rekursiven CTEs wirklich satzbasiert?