1

Temat: Jakie rozwiązanie byłoby najlepsze?

Ostatnio edytowany przez janekw (2011-07-07 23:54:47)

2

Odp: Jakie rozwiązanie byłoby najlepsze?

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)

3

Odp: Jakie rozwiązanie byłoby najlepsze?

Serdeczne dziękuję za pomoc smile 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)

4

Odp: Jakie rozwiązanie byłoby najlepsze?

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

5

Odp: Jakie rozwiązanie byłoby najlepsze?

6

Odp: Jakie rozwiązanie byłoby najlepsze?

Wszystko już jasne. Dzieki.