環路

2012-12-10 26 views
10

的Postgres 9.2 PL/pgSQL的簡單更新我有如下表:環路

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

而且我在尋找一個簡單的方法來更新position與遞增的整數(每個父)。所以我完成後,該表應該是這樣的:

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

我想我需要的,是一個功能,即遍歷一個給定trail所有行,有一個簡單的遞增索引並更新position柱。不過,我是一名pgSQL新手,所以我很樂意聽到有更簡單的方法來做到這一點。

我想,現在的解決方案是這樣的

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; 

我敢肯定它可能是更清潔,它不具有使用功能。

+0

我改變了我的原始問題了一下。起初我認爲執行因某種錯誤而凍結,但情況並非如此。我使用的是一個GUI客戶端,其中一個進程在嘗試修改'photos'表時凍結了,當然這個進程鎖定了其他進程嘗試更新它的表。現在一切都很好,我發佈的解決方案的作品,我正在尋找更好的一個' – ellmo

回答

15

您不需要爲此存儲的函數。你可以用一條語句來做到這一點。

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

哦,上帝,我試圖編輯我的初始帖子,以便您的答案適合(_that是我的錯誤,我用不同的名字在問題_中),但我認爲你也在回答你的答案:) 另外'row_number()'方法讓我大跌眼鏡。太棒了。 – ellmo