Пожалуйста, рассмотрите следующий сценарий:
actor
. (Да, это из образца базы данных Sakila).last_name
.Когда я запускаю этот запрос, он работает:
DELETE FROM actor WHERE last_name = 'foo';
Когда я запускаю этот запрос:
DELETE FROM actor WHERE last_name LIKE '%fo' OR last_name LIKE 'fo%';
Это не удается с этим сообщением об ошибке:
Error Code: 1175. You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column. To disable safe mode, toggle the option in Preferences -> SQL Editor and reconnect.
Почему режим безопасного обновления останавливает вторую команду и разрешает первую команду?
Спасибо @Barmar. Это где-нибудь задокументировано? ИМХО, с предикатом =
можно сильно навредить. Просто обратите внимание на фамилию «Смит» :)
Документация здесь, но в ней не упоминается эта деталь. Я просто экстраполирую.
Общая идея безопасных обновлений состоит в том, чтобы блокировать запросы, которые могут затронуть намного больше строк, чем вы ожидали.
@Бармар. Теперь я вижу, что страница, на которую вы ссылаетесь, дает (несколько расплывчатый) ответ на мой вопрос. См. "...если оптимизатор решит не использовать индекс ключевого столбца:". Хотите опубликовать ответ с этими деталями? Я приму это.
LIKE 'fo%'
следует использовать индекс, поэтому я не думаю, что это объяснение. Если бы это было LIKE '%fo'
, это объяснило бы это.
Почему вы используете обратную кавычку во втором примере вместо '
. DELETE FROM actor WHERE last_name LIKE 'fo%';
?
@lukasz-szozda Tx. Опечатка. Исправление сейчас.
Не могу воспроизвести ошибку. Я получаю ошибку с LIKE '%a'
, но не с LIKE 'a%'
.
Какой тип шаблона вы на самом деле использовали?
Согласно документация:
It is possible for UPDATE and DELETE statements to produce an error in safe-updates mode even with a key specified in the WHERE clause, if the optimizer decides not to use the index on the key column.
Такой тест, как LIKE 'fo%'
, обычно использует индекс (индекс можно использовать для сопоставления с началом столбца), поэтому он не должен вызывать ошибку. Но такой тест, как LIKE '%fo'
, не может быть проиндексирован (он не указывает начало столбца, поэтому необходимо полное сканирование), поэтому вы получаете ошибку.
Благодарю. Ты прав. LIKE 'fo%'
должно работать. В моем случае это не удается из-за ограничения внешнего ключа. Одна из удаляемых записей имеет соответствующую запись в другой таблице. Изменение моего вопроса на использование LIKE '%fo'
, потому что это с самого начала дало мне ошибку 1175.
То есть вы действительно не получили ошибку о безопасном режиме обновления?
Я сделал, только то, что я использовал в верстаке, было WHERE first_name LIKE '%fo' OR first_name LIKE 'fo%';
. Извините - я должен был быть более точным в своем описании проблемы.
=
очень специфичен, вряд ли он удалит строку, которую вы не собирались.LIKE
может легко соответствовать большему, чем вы ожидаете.