我在Oracle中有一个简单的表,有三列:
ID NCHAR(10)
NAME NCHAR(50)
SEQ NUMBER
SEQ
字段基于0,允许用户拖动记录并重新排序列表(使用jQuery可排序)。我正在试图弄清楚如何更改所有序列号,以便它们在数据库中以正确的顺序结束。
我在更新前开始创建触发器,以根据SEQ
和:OLD
值更改所有:NEW
个数字,但在我意识到这会导致无限循环时停止当我更新一堆记录时触发器会继续运行。
有没有办法可以触发执行此操作,还是应该手动将其写入代码?
提前致谢
答案 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)
使用链表方法。
将记录指向订单前面的记录。然后你最小化更新。