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

Crear una tabla/vista aplanada de un conjunto de datos definido jerárquicamente

Entonces lo que quieres es materializar los cierres transitivos. Es decir, dada esta tabla de aplicaciones...

 ID   | PARENT_ID
------+----------
    1 | 
    2 |         1
    3 |         2
    4 |         2
    5 |         4

... la tabla de gráficos se vería así:

 PARENT_ID | CHILD_ID
-----------+----------
         1 |        2
         1 |        3
         1 |        4
         1 |        5
         2 |        3
         2 |        4
         2 |        5
         4 |        5

Es posible mantener una tabla como esta en Oracle, aunque necesitará implementar su propio marco para ello. La pregunta es si vale la pena los gastos generales. Si la tabla de origen es volátil, mantener actualizados los datos del gráfico puede costar más ciclos de los que ahorrará en las consultas. Solo tú conoces el perfil de tus datos.

No creo que pueda mantener una tabla gráfica de este tipo con consultas CONNECT BY y claves externas en cascada. Demasiada actividad indirecta, demasiado difícil de hacer bien. También se descarta una vista materializada, porque no podemos escribir una consulta SQL que elimine el 1->5 registro cuando eliminamos el registro fuente para ID=4 .

Entonces, le sugiero que lea un documento llamado Mantenimiento del cierre transitivo de gráficos en SQL por Dong, Libkin, Su y Wong. Esto contiene mucha teoría y algo de SQL retorcido (Oracle), pero le dará la base para construir el PL/SQL que necesita para mantener una tabla gráfica.

"¿Puede ampliar la parte acerca de que es demasiado difícil de mantener con CONNECT BY/FK en cascada? Si controlo el acceso a la tabla y todas las inserciones/actualizaciones/eliminaciones se realizan a través de procedimientos almacenados, ¿qué tipo de escenarios existen en los que esto podría fallar?"

Considere el registro 1->5 que es un cortocircuito de 1->2->4->5 . Ahora, ¿qué sucede si, como dije antes, eliminamos el registro fuente para ID=4? ? Las claves foráneas en cascada podrían eliminar las entradas para 2->4 y 4->5 . Pero eso deja 1->5 (y de hecho 2->5 ) en la tabla del gráfico aunque ya no representan un borde válido en el gráfico .

Lo que podría funcionar (creo que no lo he hecho) sería usar una clave sintética adicional en la tabla de origen, como esta.

 ID   | PARENT_ID | NEW_KEY
------+-----------+---------
    1 |           | AAA
    2 |         1 | BBB
    3 |         2 | CCC
    4 |         2 | DDD
    5 |         4 | EEE

Ahora la tabla gráfica se vería así:

 PARENT_ID | CHILD_ID | NEW_KEY
-----------+----------+---------
         1 |        2 | BBB
         1 |        3 | CCC
         1 |        4 | DDD
         1 |        5 | DDD
         2 |        3 | CCC
         2 |        4 | DDD
         2 |        5 | DDD
         4 |        5 | DDD

Entonces, la tabla del gráfico tiene una clave externa que hace referencia a la relación en la tabla de origen que la generó, en lugar de vincularla a la ID. Luego borrando el registro para ID=4 eliminaría en cascada todos los registros en la tabla del gráfico donde NEW_KEY=DDD .

Esto funcionaría si cualquier identificación dada solo puede tener cero o una identificación principal. Pero no funcionará si está permitido que esto suceda:

 ID   | PARENT_ID
------+----------
    5 |         2
    5 |         4

En otras palabras, el borde 1->5 representa tanto 1->2->4->5 y 1->2->5 . Entonces, lo que podría funcionar depende de la complejidad de sus datos.