如何编写触发器来重新排序序列号?

时间:2011-10-14 14:31:05

标签: oracle plsql triggers

我在Oracle中有一个简单的表,有三列:

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

SEQ字段基于0,允许用户拖动记录并重新排序列表(使用jQuery可排序)。我正在试图弄清楚如何更改所有序列号,以便它们在数据库中以正确的顺序结束。

我在更新前开始创建触发器,以根据SEQ:OLD值更改所有:NEW个数字,但在我意识到这会导致无限循环时停止当我更新一堆记录时触发器会继续运行。

有没有办法可以触发执行此操作,还是应该手动将其写入代码?

提前致谢

3 个答案:

答案 0 :(得分: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。

答案 1 :(得分:1)

最简单的做法是废弃使用连续序列的想法,而是将移动的记录更新为给定位置的上一个和下一个值的平均值。

例如,假设您有此列表:

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

要将“Ted”移动到列表中的第二个空格,您可以将序列设置为15(20 + 10/2)。如果你后来在“Fred”和“Ted”之间移动某人,他们会获得12.5的seq。如果你真的觉得有必要,你可以在整个表格(而不是每一行)上设置after update触发器,将SEQ设置为均匀间隔的值。

答案 2 :(得分:0)

使用链表方法。

将记录指向订单前面的记录。然后你最小化更新。