Вам действительно нужно, чтобы значения последовательности были смежными, или вам просто нужно иметь возможность отображать смежные значения? Самый простой способ сделать это состоит в том, чтобы позволить фактической последовательности стать разреженной и вычислить ранг на основе порядка:
select id,
name,
dense_rank() over (order by pos) as pos,
pos as sparse_pos
from my_table
(примечание: это специфичный для Oracle запрос)
Если вы сделаете позицию разреженной в первую очередь, это даже упростит повторный порядок, поскольку вы можете сделать каждую новую позицию на полпути между двумя существующими. Например, если у вас была такая таблица:
+----+--------+-----+
| id | name | pos |
+----+--------+-----+
| 1 | one | 100 |
| 2 | two | 200 |
| 3 | three | 300 |
| 4 | four | 400 |
+----+--------+-----+
Когда придет время переместить ID 4 в положение 2, вы просто измените положение на 150.
Дальнейшее объяснение:
Используя приведенный выше пример, пользователь изначально видит следующее (потому что вы маскируете позицию):
+----+--------+-----+
| id | name | pos |
+----+--------+-----+
| 1 | one | 1 |
| 2 | two | 2 |
| 3 | three | 3 |
| 4 | four | 4 |
+----+--------+-----+
Когда пользователь через ваш интерфейс указывает, что запись в позиции 4 должна быть перемещена в позицию 2, вы обновите позицию с идентификатором 4 до 150, а затем повторно выполните свой запрос. Пользователь видит это:
+----+--------+-----+
| id | name | pos |
+----+--------+-----+
| 1 | one | 1 |
| 4 | four | 2 |
| 2 | two | 3 |
| 3 | three | 4 |
+----+--------+-----+
Единственная причина, по которой это не сработает, заключается в том, что пользователь редактирует данные непосредственно в базе данных. Хотя даже в этом случае я был бы склонен использовать такое решение с помощью представлений и вместо триггеров.