2012-12-10 8 views
10

Mam poniższej tabeli:PostgreSQL 9.2 PL/PGSQL prosta zmiana w pętli

+----+----------+----------+ 
| id | trail_id | position | 
+----+----------+----------+ 
| 11 | 16  | NULL  | 
| 12 | 121  | NULL  | 
| 15 | 121  | NULL  | 
| 19 | 42  | NULL  | 
| 20 | 42  | NULL  | 
| 21 | 42  | NULL  | 
+----+----------+----------+ 

I szukam prosty sposób zaktualizować position z całkowitymi inkrementacji (za rodzica). Więc po skończę, tabela powinna wyglądać następująco:

+----+-----------+----------+ 
| id | trail_id | position | 
+----+-----------+----------+ 
| 11 | 16  | 1  | 
| 12 | 121  | 1  | 
| 15 | 121  | 2  | 
| 19 | 42  | 1  | 
| 20 | 42  | 2  | 
| 21 | 42  | 3  | 
+----+-----------+----------+ 

Co Chyba muszę, to funkcja, która obwodów nad wszystkich wierszy dla danej trail, posiada prosty indeks inkrementacji i aktualizuje position kolumna. Jestem początkującym pgSQL, więc z przyjemnością usłyszę, że są prostsze sposoby na zrobienie tego.

Rozwiązanie Próbuję teraz wygląda to

CREATE FUNCTION fill_positions(tid integer) RETURNS integer AS $$ 
DECLARE 
    pht RECORD; 
    i INTEGER := 0; 
BEGIN 
    FOR pht IN SELECT * FROM photos WHERE photos.trail_id = tid LOOP 
     i := i + 1; 
     UPDATE photos SET position = i WHERE id = pht.id; 
    END LOOP; 
    RETURN i; 
END; 
$$ LANGUAGE plpgsql; 

jestem całkiem pewny może być czystsze i nie trzeba używać funkcji.

+0

Zmieniłem nieco moje pierwotne pytanie. Początkowo myślałem, że wykonanie zamarza z powodu jakiegoś błędu, jednak nie było tak. Używałem klienta GUI, którego jeden z procesów zamarzał przy próbie modyfikacji tabeli 'photos', to oczywiście zablokowało tabelę dla jakiegokolwiek innego procesu próbującego ją zaktualizować. Teraz wszystko jest w porządku, rozwiązanie, które napisałem, działa, szukam lepszego. " – ellmo

Odpowiedz

15

Nie potrzebujesz do tego funkcji zapisanej. Możesz to zrobić za pomocą pojedynczej instrukcji.

with new_numbers as (
    select id, 
      trail_id, 
      row_number() over (partition by trail_id order by id) as position 
    from photos 
) 
update photos 
    set position = nn.position 
from new_numbers nn 
where nn.id = photos.id; 
+0

Och, Boże, próbuję edytować mój pierwszy wpis, żeby twoja odpowiedź pasowała (to mój błąd, użyłem różnych nazwisk w pytaniu_), ale myślę, że też zmienisz swoją odpowiedź :) Również metoda 'row_number()' rozwiała mój umysł. To jest doskonałe. – ellmo