I’m storing a list for each user.
username|index|...
john | 1 |a
john | 2 |b
john | 3 |c
jane | 1 |...
jane | 2 |...
Suppose I were to do an addition for john before his index 2, I have to increment the index so that the new table becomes:
username|index|...
john | 1 |a
john | 2 |new value
john | 3 |b
john | 4 |c
jane | 1 |...
jane | 2 |...
My solution is to first increment john’s index that is greater than or equals to 2; and then do an insert statement.
The problem is that this produces a duplicate error:
UPDATE mytable
SET index = index + 1
WHERE username = 'john' AND
index >= 2
This is because I have a UNIQUE constraint on mytable (username, index)
.
What is the workaround for this?
2
Answers
You need to create a
DEFERRABLE
unique constraint for that to work, because such a constraint will be checked at the end of the statement.However, it is silly to update many rows when a new one is added. Use a
double precision
column to persist the order, because then you can always insert new values between old ones. Assign integer numbers to the order usingrow_number()
when you query the table.Apart from the fact that a view would be the best option to handle such kind of index, one way to do it is to have a subquery whose order of indices is inverted, so that older indices are updated first. Relevant is the
FOR UPDATE
clause, that the subquery has to have at the bottom of it.Output:
Check the demo here.