sql >> Base de Datos >  >> RDS >> Oracle

Detección de ciclos con factorización de subconsultas recursivas

De la documentación en CONNECT_BY_ISCYCLE :

El CONNECT_BY_ISCYCLE pseudocolumna devuelve 1 si la fila actual tiene un hijo que también es su antepasado

y eso en CYCLE :

Se considera que una fila forma un ciclo si una de sus filas antepasadas tiene los mismos valores para las columnas del ciclo.

En su ejemplo, fila 2 tiene un hijo que también es su antepasado, pero su id aún no ha sido devuelto.

En otras palabras, CONNECT_BY_ISCYCLE revisa a los niños (que aún no se han devuelto), mientras que CYCLE comprueba la fila actual (que ya está devuelto).

CONNECT BY se basa en filas, mientras que CTE recursivo están basados ​​en conjuntos.

Tenga en cuenta que la documentación de Oracle en CYCLE menciona una "fila de antepasados". Sin embargo, en términos generales, no existe el concepto de una "fila de antepasado" en un CTE recursivo . Es una operación basada en conjuntos que puede producir resultados completamente fuera del árbol. En términos generales, la parte ancla y la parte recursiva incluso pueden usar tablas diferentes.

Desde CTE recursivo son normalmente utilizado para construir árboles de jerarquía, Oracle decidió agregar un control de ciclo. Pero debido a la forma basada en conjuntos, el recursivo CTE , generalmente es imposible saber si el siguiente paso generará un ciclo o no, porque sin una definición clara de la condición del ciclo "fila antecesora" tampoco se puede definir.

Para realizar el paso "siguiente", todo el conjunto "actual" debe estar disponible, pero para generar cada fila del conjunto actual (que incluye la columna de ciclo) solo necesitamos tener los resultados de la operación "siguiente".

No hay problema si el conjunto actual siempre consta de una sola fila (como en CONNECT BY ), pero es un problema si la operación recursiva se define en un conjunto como un todo.

No busqué en Oracle 11 todavía, pero SQL Server implementa CTE recursivo es simplemente ocultando un CONNECT BY detrás de ellos, lo que requiere colocar numerosas restricciones (todas las cuales prohíben efectivamente todas las operaciones basadas en conjuntos).

PostgreSQL La implementación de , por otro lado, está verdaderamente basada en conjuntos:puedes hacer cualquier operación con la parte ancla en la parte recursiva. Sin embargo, no tiene ningún medio para detectar ciclos, porque los ciclos no están definidos en primer lugar.

Como se mencionó antes, MySQL no implementa CTE 's en absoluto (no implementa HASH JOIN 's o MERGE JOIN s también, solo los bucles anidados, así que no te sorprendas mucho).

Irónicamente, hoy recibí una carta sobre este mismo tema, que trataré en mi blog.

Actualización:

CTE recursivo está en SQL Server no son más que CONNECT BY disfrazada. Vea este artículo en mi blog para detalles impactantes:

  • SQL Server:¿los CTE recursivos realmente están basados ​​en conjuntos?