我想在SQL表中表示"hi","hello","goodbye","good day","howdy"(带有该顺序)列表:
pk | i | val
------------
1 | 0 | hi
0 | 2 | hello
2 | 3 | goodbye
3 | 4 | good day
5 | 6 | howdy
Run Code Online (Sandbox Code Playgroud)
'pk'是主键列.无视其价值观.
'i'是定义'val'列中值的顺序的"索引".它仅用于建立顺序,而值则不重要.
我遇到的问题是在维护订单的同时将值插入列表中.例如,如果我想插入"嘿"并且我希望它出现在 "你好"和"再见"之间,那么我必须改变"再见"和"美好的一天"的"i"值(但最好不要"你好"为新入场腾出空间".
那么,是否有一个标准的SQL模式来进行移位操作,但只移位必要的元素?(注意,一个简单的"UPDATE表SET i = i + 1 WHERE i> = 3"不起作用,因为它违反了'i'上的唯一性约束,并且它也不必要地更新了"howdy"行.)
或者,有没有更好的方式来表示有序列表?我想你可以让'i'成为一个浮点值并在它们之间选择值,但是当没有这样的值时你必须有一个单独的重新平衡操作.
或者,是否有一些标准算法用于在任意其他字符串之间生成字符串值,如果我要使'i'为varchar?
或者我应该将其表示为链接列表?我正在避免这种情况,因为我也希望能够执行SELECT .. ORDER BY以按顺序获取所有元素.
当我阅读你的帖子时,我一直在想"链表",最后,我仍然认为这是要走的路.
如果您使用的是Oracle,并且链接列表是一个单独的表(或者甚至是具有自引用ID的同一个表 - 我会避免),那么您可以使用CONNECT BY查询和伪列LEVEL来确定排序顺序.
您可以通过使用级联触发器轻松实现这一点,该触发器将插入/更新操作中等于新条目的任何“索引”条目更新为索引值+1。这将级联所有行,直到第一个间隙停止级联 -有关 PostgreSQL 实现,请参阅此博客条目中的第二个示例。
这种方法应该独立于所使用的 RDBMS 工作,只要它支持在更新/插入之前触发触发器即可。如果您在代码中实现了所需的行为,它基本上会做您会做的事情(增加所有以下索引值,直到遇到间隙),但以更简单、更有效的方式。
或者,如果您可以接受 SQL Server 的限制,请检查Hierarchyid 类型。虽然主要用于定义嵌套层次结构,但您也可以将其用于平面排序。它有点类似于使用浮点数的方法,因为它允许通过分配小数值在两个位置之间插入,从而避免需要更新其他条目。
归档时间: |
|
查看次数: |
6973 次 |
最近记录: |