Почему безопасный режим обновления MySQL не разрешает предикат LIKE?

Пожалуйста, рассмотрите следующий сценарий:

  • У меня есть таблица MySQL с именем actor. (Да, это из образца базы данных Sakila).
  • В таблице есть столбец varchar с именем last_name.
  • В столбце есть (НЕ ПЕРВИЧНЫЙ) КЛЮЧ.
  • Безопасный режим обновления MySQL включен.

Когда я запускаю этот запрос, он работает:

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.

Почему режим безопасного обновления останавливает вторую команду и разрешает первую команду?

= очень специфичен, вряд ли он удалит строку, которую вы не собирались. LIKE может легко соответствовать большему, чем вы ожидаете.
Barmar 29.05.2019 20:45

Спасибо @Barmar. Это где-нибудь задокументировано? ИМХО, с предикатом = можно сильно навредить. Просто обратите внимание на фамилию «Смит» :)

urig 29.05.2019 20:47

Документация здесь, но в ней не упоминается эта деталь. Я просто экстраполирую.

Barmar 29.05.2019 20:49

Общая идея безопасных обновлений состоит в том, чтобы блокировать запросы, которые могут затронуть намного больше строк, чем вы ожидали.

Barmar 29.05.2019 20:50

@Бармар. Теперь я вижу, что страница, на которую вы ссылаетесь, дает (несколько расплывчатый) ответ на мой вопрос. См. "...если оптимизатор решит не использовать индекс ключевого столбца:". Хотите опубликовать ответ с этими деталями? Я приму это.

urig 29.05.2019 20:54
LIKE 'fo%' следует использовать индекс, поэтому я не думаю, что это объяснение. Если бы это было LIKE '%fo', это объяснило бы это.
Barmar 29.05.2019 20:56

Почему вы используете обратную кавычку во втором примере вместо '. DELETE FROM actor WHERE last_name LIKE 'fo%';?

Lukasz Szozda 29.05.2019 20:59

@lukasz-szozda Tx. Опечатка. Исправление сейчас.

urig 29.05.2019 21:04

Не могу воспроизвести ошибку. Я получаю ошибку с LIKE '%a', но не с LIKE 'a%'.

Barmar 29.05.2019 21:05

Какой тип шаблона вы на самом деле использовали?

Barmar 29.05.2019 21:09
Освоение архитектуры микросервисов с Laravel: Лучшие практики, преимущества и советы для разработчиков
Освоение архитектуры микросервисов с Laravel: Лучшие практики, преимущества и советы для разработчиков
В последние годы архитектура микросервисов приобрела популярность как способ построения масштабируемых и гибких приложений. Laravel , популярный PHP...
Как построить CRUD-приложение в Laravel
Как построить CRUD-приложение в Laravel
Laravel - это популярный PHP-фреймворк, который позволяет быстро и легко создавать веб-приложения. Одной из наиболее распространенных задач в...
Освоение PHP и управление базами данных: Создание собственной СУБД - часть II
Освоение PHP и управление базами данных: Создание собственной СУБД - часть II
В предыдущем посте мы создали функциональность вставки и чтения для нашей динамической СУБД. В этом посте мы собираемся реализовать функции обновления...
Документирование API с помощью Swagger на Springboot
Документирование API с помощью Swagger на Springboot
В предыдущей статье мы уже узнали, как создать Rest API с помощью Springboot и MySql .
Роли и разрешения пользователей без пакета Laravel 9
Роли и разрешения пользователей без пакета Laravel 9
Этот пост изначально был опубликован на techsolutionstuff.com .
Как установить LAMP Stack - Security 5/5 на виртуальную машину Azure Linux VM
Как установить LAMP Stack - Security 5/5 на виртуальную машину Azure Linux VM
В предыдущей статье мы завершили установку базы данных, для тех, кто не знает.
0
10
67
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Согласно документация:

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.

urig 29.05.2019 21:53

То есть вы действительно не получили ошибку о безопасном режиме обновления?

Barmar 29.05.2019 21:54

Я сделал, только то, что я использовал в верстаке, было WHERE first_name LIKE '%fo' OR first_name LIKE 'fo%';. Извините - я должен был быть более точным в своем описании проблемы.

urig 29.05.2019 21:56

Другие вопросы по теме