Така че това, което искате, е да материализирате преходните затваряния. Тоест, като се има предвид тази таблица на приложението ...
ID | PARENT_ID
------+----------
1 |
2 | 1
3 | 2
4 | 2
5 | 4
... таблицата на графиката ще изглежда така:
PARENT_ID | CHILD_ID
-----------+----------
1 | 2
1 | 3
1 | 4
1 | 5
2 | 3
2 | 4
2 | 5
4 | 5
Възможно е да поддържате таблица като тази в Oracle, въпреки че ще трябва да развиете своя собствена рамка за нея. Въпросът е дали си струва режийните разходи. Ако таблицата източник е нестабилна, поддържането на свежи данни на графиката може да струва повече цикли, отколкото ще спестите от заявките. Само вие знаете профила на вашите данни.
Не мисля, че можете да поддържате такава таблица с графики със заявки CONNECT BY и каскадни външни ключове. Твърде много непряка дейност, твърде трудно да се оправи. Излиза също и материализиран изглед, тъй като не можем да напишем SQL заявка, която ще прекъсне 1->5
запис, когато изтрием изходния запис за ID=4
.
И така, предлагам ви да прочетете статия, наречена Поддържане на транзитивно затваряне на графики в SQL от Донг, Либкин, Су и Вонг. Това съдържа много теория и малко скучен (Oracle) SQL, но ще ви даде основание да изградите PL/SQL, от който се нуждаете, за да поддържате таблица с графики.
"можете ли да разширите частта за това, че е твърде трудно да се поддържа с CONNECT BY/каскадни FK? Ако контролирам достъпа до таблицата и всички вмъквания/актуализации/изтривания се извършват чрез запаметени процедури, какви видове сценарии има, при които това би се развалило?"
Помислете за записа 1->5
което е късо съединение от 1->2->4->5
. Сега какво ще стане, ако, както казах преди, изтрием изходния запис за ID=4
? Каскадирането на външни ключове може да изтрие записите за 2->4
и 4->5
. Но остава 1->5
(и наистина 2->5
) в таблицата на графиката, въпреки че те вече не представляват валиден ръб в графиката .
Това, което може да работи (мисля, че не съм го правил) би било да се използва допълнителен синтетичен ключ в таблицата на източника, като този.
ID | PARENT_ID | NEW_KEY
------+-----------+---------
1 | | AAA
2 | 1 | BBB
3 | 2 | CCC
4 | 2 | DDD
5 | 4 | EEE
Сега таблицата на графиката ще изглежда така:
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
Така че таблицата на графиката има външен ключ, който препраща към връзката в изходната таблица, която я е генерирала, вместо да се свързва с идентификатора. След това изтриване на записа за ID=4
ще каскадно изтрива всички записи в таблицата с графики, където NEW_KEY=DDD
.
Това би работило, ако даден идентификатор може да има само нула или един родителски идентификатори. Но няма да работи, ако е позволено това да се случи:
ID | PARENT_ID
------+----------
5 | 2
5 | 4
С други думи ръбът 1->5
представлява и двете 1->2->4->5
и 1->2->5
. И така, това, което може да работи, зависи от сложността на вашите данни.