Reputation: 878
I have the following table with a unique index by field "position_in_list":
CREATE TABLE `planned_operation` (
`id` bigint(20) NOT NULL,
`position_in_list` bigint(20) NOT NULL,
`name` varchar(255) not null
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
ALTER TABLE `planned_operation`
ADD PRIMARY KEY (`id`),
ADD UNIQUE KEY `position_in_list` (`position_in_list`);
ALTER TABLE `planned_operation`
MODIFY `id` bigint(20) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=3;
INSERT INTO `planned_operation` (`id`, `position_in_list`, `name`) VALUES
(1, 1, 'first'),
(2, 2, 'second');
Then I have a trivial task, this is a change in position when updating the list. Accordingly, you need to update the list of items before which the record was inserted. In order not to perform thousands of updates, I execute one query:
update planned_operation
set position_in_list = case position_in_list
when 2 then 3
when 1 then 2
end
where position_in_list in (1, 2)
But when executing an error is issued:
#1062 - Duplicate entry '1' for key 'position_in_list'
Is there any way to avoid an error? Without disabling the unique index
Upvotes: 0
Views: 1823
Reputation: 48865
You want deferrable constraints.
Unfortunately, MySQL does not implement deferrable constraint checks -- an integral part of SQL that few database engines implement.
As far as I know only PostgreSQL and Oracle (partial) do implement them.
In simple words, this means that MySQL checks the unique constraint on every single row change inside an UPDATE
statement. With deferrable constraints you could defer this check to the end of the statement, or even to the end of the database transaction.
Now, you would need to switch to PostgrSQL or Oracle to defer contraints checks to the end of the statement (as you seem to want). I guess that's way out of the scope for you, but it's a theoretical option.
For a more in depth discussion you could look into Deferrable Constraints answer.
Upvotes: 2