Temat: Jakie rozwiązanie byłoby najlepsze?
Ostatnio edytowany przez janekw (2011-07-07 23:54:47)
PostgreSQL to najbardziej zaawansowany system relacyjnych baz danych Open Source.
Nie jesteś zalogowany. Proszę się zalogować lub zarejestrować.
Strony 1
Zaloguj się lub zarejestruj by napisać odpowiedź
Ostatnio edytowany przez janekw (2011-07-07 23:54:47)
Myślę, że najlepszym wyjściem jest napisanie procedury PL/pgSQL, która odpowiednio aktualizuje kolumnę pNUM. Przykładowo:
DROP TABLE IF EXISTS tab;
CREATE TABLE tab (
kID INT8,
pID INT8,
pNUM INT8,
PRIMARY KEY(kID, pID)
);
DELETE FROM tab;
INSERT INTO tab (kID, pID) VALUES
(1, 1), (2, 2), (3, 3), (1, 2), (4, 1),
(5, 3), (6, 1), (7, 2), (8, 6), (9, 1),
(1, 7), (10, 90),
(6, 4);
Procedura:
CREATE OR REPLACE FUNCTION updateTab(kStart INT8, deep INT8 DEFAULT 1)
RETURNS void AS $$
DECLARE
p INT8;
k INT8;
isSet boolean;
BEGIN
UPDATE tab SET pNUM = kStart WHERE kID = kStart;
FOR p IN SELECT pID FROM tab WHERE kID = kStart
LOOP
FOR k IN SELECT kID FROM tab WHERE pID = p
LOOP
SELECT INTO isSet pNUM IS NOT NULL FROM tab WHERE kID = k LIMIT 1;
RAISE NOTICE 'k=%, isSet=%', k, isSet;
IF isSet = false THEN
RAISE NOTICE 'updateTab(%, %)', k, deep + 1;
PERFORM updateTab(k, deep + 1);
END IF;
END LOOP;
END LOOP;
RETURN;
END $$
LANGUAGE 'plpgsql';
Uruchomienie:
SELECT updateTab(1);
Przebieg:
NOTICE: k=4, isSet=f
NOTICE: updateTab(4, 2)
NOTICE: k=6, isSet=f
NOTICE: updateTab(6, 3)
NOTICE: k=9, isSet=f
NOTICE: updateTab(9, 4)
NOTICE: k=1, isSet=t
NOTICE: k=4, isSet=t
NOTICE: k=6, isSet=t
NOTICE: k=9, isSet=t
NOTICE: k=1, isSet=t
NOTICE: k=4, isSet=t
NOTICE: k=6, isSet=t
NOTICE: k=6, isSet=t
NOTICE: k=9, isSet=t
NOTICE: k=1, isSet=t
NOTICE: k=4, isSet=t
NOTICE: k=6, isSet=t
NOTICE: k=9, isSet=t
NOTICE: k=1, isSet=t
NOTICE: k=2, isSet=f
NOTICE: updateTab(2, 2)
NOTICE: k=7, isSet=f
NOTICE: updateTab(7, 3)
NOTICE: k=1, isSet=t
NOTICE: k=2, isSet=t
NOTICE: k=7, isSet=t
NOTICE: k=1, isSet=t
NOTICE: k=2, isSet=t
NOTICE: k=7, isSet=t
NOTICE: k=1, isSet=t
NOTICE: k=1, isSet=t
Wynik:
TABLE tab ORDER BY kID;
kid | pid | pnum
-----+-----+------
1 | 1 | 1
1 | 7 | 1
1 | 2 | 1
2 | 2 | 2
3 | 3 |
4 | 1 | 4
5 | 3 |
6 | 4 | 6
6 | 1 | 6
7 | 2 | 7
8 | 6 |
9 | 1 | 9
10 | 90 |
(13 rows)
Parametr deep pozwala określic głębokość/poziom, łatwo np. dodać warunek, który blokuje możliwość nieskończonej rekurencji.
Ostatnio edytowany przez gszpetkowski (2011-07-08 16:16:40)
Serdeczne dziękuję za pomoc Czy dobrze myślę, że aby dla rozpatrywanego przypadku zachować wspólną wartość pnum, należałoby Twoją procedurę opakować zewnętrzną?
Ostatnio edytowany przez janekw (2011-07-08 16:13:35)
Nie bardzo rozumiem co masz na myśli, wartości pnum są "na bieżąco" zachowywane w tabeli, dzięki czemu wiadomo, że nie należy ich ponownie wpisywać:
IF isSet = false THEN
Wszystko już jasne. Dzieki.
Posty [ 6 ]
Strony 1
Zaloguj się lub zarejestruj by napisać odpowiedź
[ Wygenerowano w 0.007 sekund, wykonano 10 zapytań ]