Mysql временно подавляет уникальный индекс - PullRequest
13 голосов
/ 07 декабря 2011

У меня есть таблица с уникальным индексом по двум столбцам, точнее, id_parent и sort_order

+----+-----------+------------+-------------+-------------+-------------+
| id | id_parent | sort_order | some_data   | other_data  | more_data   |
+----+-----------+------------+-------------+-------------+-------------+
| 1  |         1 |          1 | lorem ipsum | lorem ipsum | lorem ipsum |
| 2  |         1 |          2 | lorem ipsum | lorem ipsum | lorem ipsum |
| 3  |         1 |          3 | lorem ipsum | lorem ipsum | lorem ipsum |
+----+-----------+------------+-------------+-------------+-------------+

Теперь я хочу обновить их, их данные и их sort_order за один раз.sort_order изменится с 1 - 2 - 3 на, например, 2 - 3 - 1.

Но когда я начинаю выполнять операторы обновления, уникальный индекс блокирует меня, как и ожидалось, говоря, что я не могу иметь две строки с id_parent = 1 and sort_order = 2.Ну, я мог бы сейчас установить 4, обновить другие строки в правильном порядке, а затем установить этот.Но тогда мне нужно будет выполнить дополнительный оператор и, скорее всего, добавить дополнительную логику в мой язык сценариев, чтобы определить правильный порядок обновлений.Я также использую ORM, и это становится еще более неудобным.

Мой вопрос сейчас, есть ли какой-нибудь способ заставить mysql временно игнорировать этот индекс?Как запуск специальной транзакции, в которой индексы будут рассчитываться только перед ее совершением?

Ответы [ 3 ]

6 голосов
/ 07 декабря 2011

Насколько я знаю, это невозможно.

Единственный раз, когда я видел что-то подобное, это то, что вы можете отключить неуникальные ключи в таблицах myisam. Но не на InnoDB и не на уникальных ключах.

Однако, чтобы сохранить вам обновление или два, не нужно иметь точное число 1, 2 и 3. Вы также можете иметь 4, 5 и 6. Верно? Вы бы использовали его в порядке и ничего больше, поэтому точные цифры не важны. Это даже спасет вас от обновления, если вы умны. Из вашего примера

update table set sort_order = 4 where sort_order = 1 and id = 1 and id_parent = 1;

Новый порядок сортировки - 2, 3, 1. И всего за одно обновление.

5 голосов
/ 07 декабря 2011

'Но когда я запускаю обновление операторов …' - насколько я понимаю, вы пытались обновить значения, используя несколько операторов UPDATE, как в цикле.Это так?Как насчет обновления их за один раз?Например,

UPDATE atable
SET sort_order = CASE sort_order WHEN 3 THEN 1 ELSE sort_order + 1 END
WHERE id_parent = 1
  AND sort_order BETWEEN 1 AND 3

Один оператор является атомарным, поэтому к моменту окончания этого обновления значения sort_order, хотя и изменяются, остаются уникальными.

Iне могу проверить это в MySQL, извините, но это определенно работает в SQL Server, и я считаю, что поведение соответствует стандартам.

2 голосов
/ 10 июня 2014

Примечание: В некоторых комментариях упоминается, что приведенный ниже ответ не всегда подавляет уникальные ограничения, особенно в InnoDB.Если вы можете улучшить этот ответ, пожалуйста, нажмите «Изменить» и внесите улучшения.

Вы можете просто добавить эту строку в начале вашего скрипта:

SET UNIQUE_CHECKS=0;

Это обычноиспользуйте это вместе с:

SET FOREIGN_KEY_CHECKS=0;

Переменная UNIQUE_CHECKS упоминается в документации здесь:
http://dev.mysql.com/doc/refman/5.0/en/converting-tables-to-innodb.html

...