Почему MySQL не может обновить таблицу и выбрать из той же таблицы в подзапросе

В нижней части MySQL v5.6 страница документации для команды UPDATE написано:

You cannot update a table and select from the same table in a subquery.

Например, это не удастся:

UPDATE actor
SET last_name = 'foo'
WHERE actor_id IN (
    SELECT actor_id 
    FROM actor 
    WHERE last_name = 'bar');

Примечание. Предположим, что столбец last_name не является частью индекса.

Почему это не разрешено и есть ли стабильный обходной путь?

P.S. - Спасибо за обходной путь! Не могли бы вы также объяснить, почему приведенный выше пример не разрешен?

Освоение архитектуры микросервисов с 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
В предыдущей статье мы завершили установку базы данных, для тех, кто не знает.
1
0
72
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

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

Это простой трюк:

UPDATE actor
SET last_name = 'foo'
WHERE last_name = 'bar'

Что бы вы ни делали, это то же самое, что и приведенный выше запрос.

Объяснение: Вы не можете просто обновить то, что выбрали.

Если вы хотите продолжить свой поток, дайте псевдоним для подзапроса, используя временную таблицу,

UPDATE actor a1
SET a1.last_name = 'foo'
WHERE a1.actor_id IN (
    SELECT a2.actor_id 
    FROM actor a2
    WHERE a2.last_name = 'bar');

ИЛИ

UPDATE actor a1 SET a1.last_name='foo' 
WHERE a1.actor_id IN (SELECT a2.actor_id 
                    from (SELECT * FROM actor) a2 
                    WHERE a2.last_name = 'bar');

Другими словами, в MySQL вы не можете изменить ту же таблицу, которую вы используете в части SELECT. Это поведение задокументировано здесь.

И в stackoverflow ссылка1 и ссылка2.

Note:This is because your update could be cyclical… what if updating that record causes something to happen which made the WHERE condition FALSE? You know that isn’t the case, but the engine doesn’t. There also could be opposing locks on the table in the operation.

Спасибо за Ваш ответ. Не могли бы вы объяснить, почему я не могу обновить то, что выбираю.

urig 29.05.2019 11:34

Вы пытались избежать подзапроса?

UPDATE actor
SET last_name = 'foo'
WHERE last_name = 'bar';

Слишком много где ).

Déjà vu 29.05.2019 09:07

Это работает, и я удивлен - не должно ли использование столбца, отличного от PK, в предложении WHERE запускать безопасный режим обновления MySQL для блокировки этой команды?

urig 29.05.2019 09:11

Итак, причина, по которой ваш оператор SQL работает, заключается в том, что в моей БД (пример БД Sakila) есть индекс (ключ) в столбце last_name. Так что это не стабильный обходной путь, к сожалению.

urig 29.05.2019 11:33

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