2012-12-10 3 views
10

Ich habe eine folgende Tabelle:Postgres 9.2 PL/pgSQL einfaches Update in Schleife

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

Und ich bin auf der Suche nach einer einfachen Möglichkeit position mit Inkrementieren ganzen Zahlen (pro Elternteil) zu aktualisieren. So, nachdem ich fertig bin, sollte die Tabelle wie folgt aussehen:

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

Was ich glaube, ich brauche, ist eine Funktion, die alle Zeilen Schleifen über für einen bestimmten trail, hat eine einfache Inkrementierung Index und aktualisiert die position Säule. Ich bin ein pgSQL-Neuling, aber ich bin froh zu hören, dass es einfachere Möglichkeiten gibt, dies zu tun.

Die Lösung, die ich jetzt bin versucht, sieht wie folgt aus

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; 

Ich bin mir ziemlich sicher, dass es sauberer sein können, und es muss nicht Funktionen nutzen.

+0

Ich habe meine ursprüngliche Frage ein wenig geändert. Anfangs dachte ich, die Ausführung stünde wegen eines Fehlers fest, aber das war nicht der Fall. Ich habe einen GUI-Client benutzt, dessen Prozesse eingefroren waren, als ich versuchte, die 'photos' Tabelle zu modifizieren. Dies blockierte natürlich die Tabelle für jeden anderen Prozess, der versuchte, sie zu aktualisieren. Alles ist in Ordnung, die Lösung, die ich gepostet habe, ich suche nach einem besseren tho ' – ellmo

Antwort

15

Sie benötigen keine gespeicherte Funktion dafür. Sie können das mit einer einzigen Anweisung tun.

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

Oh Gott, ich versuche, meinen ersten Beitrag zu bearbeiten, so dass Ihre Antwort passen würde (das ist mein Fehler, ich habe andere Namen verwendet in der Frage_), aber ich denke, dass Sie auch Ihre Antwort changing) Auch 'row_number()' Methode blies meine Meinung. Dies ist perfekt. – ellmo