Dus wat je wilt is om de transitieve sluitingen te materialiseren. Dat wil zeggen, gezien deze toepassingstabel ...
ID | PARENT_ID
------+----------
1 |
2 | 1
3 | 2
4 | 2
5 | 4
... de grafiektabel er als volgt uitziet:
PARENT_ID | CHILD_ID
-----------+----------
1 | 2
1 | 3
1 | 4
1 | 5
2 | 3
2 | 4
2 | 5
4 | 5
Het is mogelijk om een dergelijke tabel in Oracle te onderhouden, hoewel u er uw eigen framework voor moet gebruiken. De vraag is of het de overhead waard is. Als de brontabel volatiel is, kan het vers houden van de grafiekgegevens meer cycli kosten dan u bespaart op de query's. Alleen u kent het profiel van uw gegevens.
Ik denk niet dat je zo'n grafiektabel kunt onderhouden met CONNECT BY-query's en trapsgewijze externe sleutels. Te veel indirecte activiteit, te moeilijk om goed te krijgen. Er is ook een gematerialiseerde weergave uit, omdat we geen SQL-query kunnen schrijven die de 1->5
zal zappen opnemen wanneer we het bronrecord verwijderen voor ID=4
.
Dus ik raad je aan een paper te lezen met de titel Maintaining Transitive Closure of Graphs in SQL door Dong, Libkin, Su en Wong. Dit bevat veel theorie en wat knoestige (Oracle) SQL, maar het geeft je de basis om de PL/SQL te bouwen die je nodig hebt om een grafiektabel te onderhouden.
"Kun je uitleggen dat het te moeilijk is om te onderhouden met CONNECT BY/cascading FK's? Als ik de toegang tot de tabel regel en alle invoegingen/updates/verwijderingen plaatsvinden via opgeslagen procedures, wat voor soort scenario's zijn er dan waar dit zou mislukken?"
Beschouw het record 1->5
wat een kortsluiting is van 1->2->4->5
. Wat gebeurt er als we, zoals ik al eerder zei, het bronrecord voor ID=4
. verwijderen? ? Trapsgewijze externe sleutels kunnen de vermeldingen voor 2->4
. verwijderen en 4->5
. Maar dan blijft er 1->5
. over (en inderdaad 2->5
) in de grafiektabel, hoewel ze niet langer een geldige rand in de grafiek vertegenwoordigen .
Wat zou kunnen werken (ik denk dat ik het niet heb gedaan) zou zijn om een extra synthetische sleutel in de brontabel te gebruiken, zoals deze.
ID | PARENT_ID | NEW_KEY
------+-----------+---------
1 | | AAA
2 | 1 | BBB
3 | 2 | CCC
4 | 2 | DDD
5 | 4 | EEE
De grafiektabel ziet er nu als volgt uit:
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
Dus de grafiektabel heeft een externe sleutel die verwijst naar de relatie in de brontabel die deze heeft gegenereerd, in plaats van te linken naar de ID. Verwijder vervolgens het record voor ID=4
zou cascade-verwijderingen van alle records in de grafiektabel waarbij NEW_KEY=DDD
.
Dit zou werken als een bepaald ID slechts nul of één ouder-ID kan hebben. Maar het zal niet werken als het is toegestaan om dit te laten gebeuren:
ID | PARENT_ID
------+----------
5 | 2
5 | 4
Met andere woorden de rand 1->5
staat voor beide 1->2->4->5
en 1->2->5
. Wat werkt, hangt dus af van de complexiteit van uw gegevens.