sql >> Databasteknik >  >> RDS >> Oracle

Cykeldetektering med rekursiv subquery factoring

Från dokumentation på CONNECT_BY_ISCYCLE :

CONNECT_BY_ISCYCLE pseudokolumn returnerar 1 om den aktuella raden har ett barn som också är dess förfader

och det på CYCLE :

En rad anses utgöra en cykel om en av dess förfadersrader har samma värden för cykelkolumnerna.

I ditt exempel, rad 2 har ett barn som också är dess förfader, men dess id har inte returnerats än.

Med andra ord, CONNECT_BY_ISCYCLE kontrollerar barnen (som ännu inte har returnerats), medan CYCLE kontrollerar den aktuella raden (som redan är tillbaka).

CONNECT BY är radbaserad, medan rekursiv CTE s är uppsättningsbaserade.

Observera att Oracles dokumentation om CYCLE nämner en "förfaderrad". Men generellt sett finns det inget koncept för en "förfaderrad" i en rekursiv CTE . Det är en uppsättningsbaserad operation som kan ge resultat helt utanför trädet. Generellt sett kan ankardelen och den rekursiva delen till och med använda de olika tabellerna.

Sedan rekursiv CTE s är vanligtvis används för att bygga hierarkiträd, Oracle beslutade att lägga till en cykelkontroll. Men på grund av det uppsättningsbaserade sättet den rekursiva CTE s fungerar är det i allmänhet omöjligt att säga om nästa steg genererar en cykel eller inte, för utan en tydlig definition av "förfäderraden" kan cykelvillkoret inte heller definieras.

För att utföra "nästa" steg, måste hela "nuvarande" uppsättningen vara tillgänglig, men för att generera varje rad i den aktuella uppsättningen (som inkluderar cykelkolumnen) behöver vi bara ha resultaten av "nästa" operationen.

Det är inget problem om den aktuella uppsättningen alltid består av en enda rad (som i CONNECT BY ), men det är ett problem om den rekursiva operationen definieras på en uppsättning som helhet.

Tittade inte på Oracle 11 ännu, men SQL Server implementerar rekursiv CTE genom att bara dölja en CONNECT BY bakom dem, vilket kräver att man placerar många restriktioner (som alla i praktiken förbjuder alla set-baserade operationer).

PostgreSQL s implementering, å andra sidan, är verkligen set-baserad:du kan göra vilken operation som helst med ankardelen i den rekursiva delen. Det har dock inga medel för att upptäcka cykler, eftersom cykler inte definieras i första hand.

Som nämnts tidigare, MySQL implementerar inte CTE s alls (den implementerar inte HASH JOIN s eller MERGE JOIN s också, bara de kapslade slingorna, så bli inte mycket förvånad).

Ironiskt nog fick jag ett brev idag om just detta ämne, som jag kommer att ta upp i min blogg.

Uppdatering:

Rekursiv CTE är i SQL Server är inte fler än CONNECT BY i förklädnad. Se den här artikeln i min blogg för chockerande detaljer:

  • SQL-server:är de rekursiva CTE:erna verkligen uppsättningsbaserade?


  1. Bästa typen av indexering när det finns LIKE-klausul

  2. Är NOLOCK (Sql Server-tips) dålig praxis?

  3. MySQL Syntax felmeddelande Operand bör innehålla 1 kolumn(er)

  4. MySQL – Hur man genererar slumptal