2011-10-14 76 views
0

我在Oracle中一個簡單的表有三列:我將如何編寫一個觸發器來重新排列序列號?

ID NCHAR(10) 
NAME NCHAR(50) 
SEQ NUMBER 

SEQ領域是基於0有允許用戶拖動記錄和重新排序列表(使用jQuery排序)。我試圖弄清楚如何改變所有的序列號,以便它們在數據庫中以正確的順序結束。

我開始創建觸發器之前更新改變都基於:OLD:NEWSEQ的數字,但是當我意識到這將導致無限循環當觸發只想繼續運行,因爲我已停止更新一堆記錄。

有沒有一種方法可以得到觸發器來執行此行爲,還是應該手動將其寫入代碼?

在此先感謝

+0

爲什麼要存儲新的序列?畢竟,用戶可以不斷改變它。爲什麼不只是通過(服務器端)更改查詢的順序,或者緩存數據sans命令並對緩存(客戶端)進行排序? – tbone

+0

這是一種元表,它包含以前在應用程序中硬編碼的信息。我正在製作管理頁面,以便管理員可以更改顯示內容的順序。沒有任何領域在邏輯上訂購記錄,我們想要的不僅僅是按字母順序排列的東西。它們也不會被排序在客戶端,因爲它們對於普通用戶來說顯得非常靜態。 – tedski

回答

1

做的最簡單的事情增加或減少是放棄使用連續序列的想法,而是將移動的記錄更新爲給定位置上的前一個值和下一個值的平均值。

例如,假設你有這樣的名單:

ID NAME SEQ 
1111 Fred 10 
2222 Bob  20 
3333 Ted  30 

爲「泰德」移動到列表中的第二空間,你設置的順序,以15(20 + 10/2)。如果您稍後在「Fred」和「Ted」之間移動某人,他們將獲得12.5的seq。如果您真的覺得需要,您可以在整個表(而不是每行)上設置after update觸發器,將SEQ設置爲均勻間隔的值。

+0

現在我想到了,我非常喜歡這個。每次只更新一次,沒有循環。謝謝! – tedski

0

使用鏈接列表方法。

按順序點擊記錄前面的記錄。那麼你最小化更新。

+0

我很熟悉鏈表,但我不確定自己完全理解。我是否會在遞歸使用觸發器之前或之後更新記錄(取決於順序),直到我沒有記錄? – tedski

+0

您將無法在觸發器的同一個表中執行此操作。更新將需要是外部的,否則,如果要觸發鏈接,則需要將鏈接移至另一個表。 (突變) – Randy

+0

是的,我仍然迷路。我想我最終會從我的應用程序手動完成 – tedski

1

通過觸發器對序列進行重新排序將非常困難,特別是如果SEQ是UNIQUE且由不可延遲的約束進行管理。你的更新會激活觸發器,這又會修改其他行,每次更新都會激活所述觸發器...

幸運的是,自從you can't modify/query the base table in a trigger以來,這種無限遞歸在Oracle中很難編碼。

在這種情況下,我會建議使用程序方法。在PLSQL例如:

PROCEDURE update_sequence(p_id NUMBER, 
          p_new_seq NUMBER) IS 
    l_old_seq NUMBER; 
BEGIN 
    SELECT seq INTO l_old_seq FROM my_table WHERE ID = p_id; 
    UPDATE my_table 
     SET seq = CASE WHEN ID = p_id 
         THEN p_new_seq 
         ELSE seq + sign(l_old_seq - p_new_seq) 
       END 
    WHERE seq BETWEEN least(l_old_seq, p_new_seq) 
        AND greatest(l_old_seq, p_new_seq); 
END; 

這將會把排在p_id序列p_new_seq和新的位置與舊之間的所有行都會有自己的序列或者通過1

+0

謝謝!實際上,我完成了幾乎完全相同的代碼,只從我的應用程序發送,而不是從程序發送。我想這將是一個更好的做法,使用一個過程。 – tedski

相關問題