I have a “tasks” table with a priority column, which has a unique constraint.
I’m trying to swap the priority value of two rows, but I keep violating the constraint. I saw this statement somewhere in a similar situation, but it wasn’t with MySQL.
UPDATE tasks
SET priority =
CASE
WHEN priority=2 THEN 3
WHEN priority=3 THEN 2
END
WHERE priority IN (2,3);
This will lead to the error:
Error Code: 1062. Duplicate entry '3' for key 'priority_UNIQUE'
Is it possible to accomplish this in MySQL without using bogus values and multiple queries?
EDIT:
Here’s the table structure:
CREATE TABLE `tasks` (
`id` int(11) NOT NULL,
`name` varchar(200) DEFAULT NULL,
`priority` varchar(45) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `priority_UNIQUE` (`priority`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
No. (none that I can think of).
The problem is how MySQL processes updates. MySQL (in difference with other DBMS that implement
UPDATEproperly), processes updates in a broken manner. It enforces checking ofUNIQUE(and other) constraints after every single row update and not – as it should be doing – after the wholeUPDATEstatement completes. That’s why you don’t have this issue with (most) other DBMS.For some updates (like increasing all or some ids,
id=id+1), this can be solved by using – another non-standard feature – anORDER BYin the update.For swapping the values from two rows, that trick can’t help. You’ll have to use
NULLor a bogus value (that doesn’t exist but is allowed in your column) and 2 or 3 statements.You could also temporarily remove the unique constraint but I don’t think that’s a good idea really.
So, if the unique column is a signed integer and there are no negative values, you can use 2 statements wrapped up in a transaction: