Z dokumentacji dotyczącej CONNECT_BY_ISCYCLE
:
CONNECT_BY_ISCYCLE
pseudokolumna zwraca 1
jeśli bieżący wiersz ma dziecko, które jest również jego przodkiem
i to w CYCLE
:
Uznaje się, że wiersz tworzy cykl, jeśli jeden z jego wierszy przodków ma te same wartości dla kolumn cyklu.
W twoim przykładzie wiersz 2
ma dziecko, które jest również jego przodkiem, ale jego id
nie został jeszcze zwrócony.
Innymi słowy, CONNECT_BY_ISCYCLE
sprawdza dzieci (które jeszcze nie zostały zwrócone), podczas gdy CYCLE
sprawdza bieżący wiersz (który już został zwrócony).
CONNECT BY
jest oparty na wierszach, podczas gdy rekurencyjne CTE
są oparte na zestawach.
Zwróć uwagę, że dokumentacja Oracle dotycząca CYCLE
wspomina o „rzędu przodków”. Jednak ogólnie rzecz biorąc, nie istnieje pojęcie „rzędu przodka” w rekurencyjnym CTE
. Jest to operacja oparta na zbiorach, która może przynieść wyniki całkowicie poza drzewem. Ogólnie rzecz biorąc, część zakotwiczona i część rekurencyjna mogą nawet używać różnych tabel.
Od rekursywnego CTE
są zazwyczaj używany do budowania drzew hierarchicznych, Oracle
postanowił dodać kontrolę cyklu. Ale ze względu na sposób oparty na zbiorach rekurencyjne CTE
, generalnie nie można stwierdzić, czy następny krok wygeneruje cykl, czy nie, ponieważ bez jasnej definicji warunku cyklu „rzędu przodka” również nie można zdefiniować.
Aby wykonać „następny” krok, cały „bieżący” zestaw musi być dostępny, ale aby wygenerować każdy wiersz bieżącego zestawu (w tym kolumnę cyklu) wystarczy mieć wyniki operacji „następny”.
Nie jest problemem, jeśli bieżący zestaw zawsze składa się z jednego wiersza (jak w CONNECT BY
), ale jest to problem, jeśli operacja rekurencyjna jest zdefiniowana na zbiorze jako całości.
Nie zajrzałem do Oracle 11
jeszcze, ale SQL Server
implementuje rekurencyjne CTE
wystarczy ukryć CONNECT BY
za nimi, co wymaga nałożenia licznych ograniczeń (z których wszystkie skutecznie zabraniają wszelkich operacji opartych na zestawach).
PostgreSQL
Z drugiej strony implementacja 's jest naprawdę oparta na zbiorach:możesz wykonać dowolną operację z częścią zakotwiczoną w części rekurencyjnej. Nie ma jednak żadnych środków do wykrywania cykli, ponieważ cykle nie są zdefiniowane w pierwszej kolejności.
Jak wspomniano wcześniej, MySQL
nie implementuje CTE
w ogóle (nie implementuje HASH JOIN
's lub MERGE JOIN
s również tylko zagnieżdżone pętle, więc nie zdziw się zbytnio).
Jak na ironię, otrzymałem dzisiaj list na ten właśnie temat, który opiszę na moim blogu.
Aktualizacja:
Rekurencyjne CTE
jest w SQL Server
są nie większe niż CONNECT BY
w przebraniu. Zobacz ten artykuł na moim blogu, aby uzyskać szokujące szczegóły:
- SQL Server:czy rekursywne CTE jest naprawdę oparte na zestawie?