Oracle
 sql >> Database >  >> RDS >> Oracle

Rilevamento del ciclo con il factoring ricorsivo delle sottoquery

Dalla documentazione su CONNECT_BY_ISCYCLE :

Il CONNECT_BY_ISCYCLE pseudocolonna restituisce 1 se la riga corrente ha un figlio che è anche il suo antenato

e quello su CYCLE :

Una riga è considerata un ciclo se una delle righe precedenti ha gli stessi valori per le colonne del ciclo.

Nel tuo esempio, riga 2 ha un figlio che è anche il suo antenato, ma il suo id non è stato ancora restituito.

In altre parole, CONNECT_BY_ISCYCLE controlla i figli (che devono ancora essere restituiti), mentre CYCLE controlla la riga corrente (che è già stato restituito).

CONNECT BY è basato su righe, mentre ricorsivo CTE sono basati su insiemi.

Nota che la documentazione di Oracle su CYCLE menziona una "fila di antenati". Tuttavia, in generale, non esiste il concetto di "riga di antenati" in un CTE ricorsivo . È un'operazione basata su set che può produrre risultati completamente fuori dall'albero. In generale, la parte di ancoraggio e la parte ricorsiva possono utilizzare anche le diverse tabelle.

Dal ricorsivo CTE sono solitamente usato per costruire alberi gerarchici, Oracle deciso di aggiungere un controllo del ciclo. Ma a causa del modo basato sul set, il ricorsivo CTE 's opera, è generalmente impossibile dire se il passaggio successivo genererà un ciclo o meno, perché senza una chiara definizione della "riga predecessore" non è nemmeno possibile definire la condizione del ciclo.

Per eseguire il passaggio "successivo", l'intero set "corrente" deve essere disponibile, ma per generare ogni riga del set corrente (che include la colonna del ciclo) dobbiamo solo avere i risultati dell'operazione "successivo".

Non è un problema se il set corrente è sempre composto da una singola riga (come in CONNECT BY ), ma è un problema se l'operazione ricorsiva è definita su un insieme nel suo insieme.

Non ho esaminato Oracle 11 ancora, ma SQL Server implementa CTE ricorsivo 's semplicemente nascondendo un CONNECT BY dietro di loro, il che richiede l'introduzione di numerose restrizioni (tutte le quali vietano effettivamente tutte le operazioni basate su insiemi).

PostgreSQL L'implementazione, invece, è veramente set-based:puoi fare qualsiasi operazione con la parte di ancoraggio nella parte ricorsiva. Tuttavia, non ha alcun mezzo per rilevare i cicli, perché i cicli non sono definiti in primo luogo.

Come accennato in precedenza, MySQL non implementa CTE 's affatto (non implementa HASH JOIN 's o MERGE JOIN Inoltre, solo i loop nidificati, quindi non sorprenderti molto).

Ironia della sorte, oggi ho ricevuto una lettera proprio su questo argomento, che tratterò nel mio blog.

Aggiornamento:

CTE ricorsivo è in SQL Server non sono più di CONNECT BY sotto mentite spoglie. Vedi questo articolo nel mio blog per dettagli scioccanti:

  • SQL Server:i CTE ricorsivi sono davvero basati su set?