Предположим, у вас есть такие данные:
id | pos
---+----
8 | 1
3 | 2
6 | 3
7 | 4
2 | 5
1 | 6
, и вы хотите переместить 2 из положения 5 в положение 3.
Все, что вам нужно сделать, это:
update t set pos = pos + 1 where pos >= 3 and pos < 5
Чтобы сделать отверстие:
id | pos
---+----
8 | 1
3 | 2
|
6 | 4
7 | 5
2 | 5
1 | 6
А затем это:
update t set pos = 3 where id = 2
, чтобы заполнить отверстие:
id | pos
---+----
8 | 1
3 | 2
2 | 3
6 | 4
7 | 5
1 | 6
Вы бы,конечно, все эти обновления должны быть включены в транзакцию.
Если у вас есть ограничение pos
во избежание дублирования (хорошая идея), тогда вы можете использовать pos = 0
в качестве временного значения:
update t set pos = 0 where id = 2;
update t set pos = post + 1 where pos >= 3 and pos < 5;
update t set pos = 3 where id = 2;
В качестве альтернативы, если вы используете последнюю версию PostgreSQL (AFAIK 9.0+), вы можете отложить свое уникальное ограничение до конца транзакции и не беспокоиться о временном дублировании.
Другие случаи аналогичны и оставлены в качестве упражнения.