mysql удалить в безопасном режиме
у меня есть инструктор таблица и я хочу удалить записи, которые имеют зарплату в диапазоне Интуитивный способ выглядит так:
delete from instructor where salary between 13000 and 15000;
однако в безопасном режиме я не могу удалить запись без предоставления первичного ключа(ID).
поэтому я пишу следующий sql:
delete from instructor where ID in (select ID from instructor where salary between 13000 and 15000);
однако, есть ошибка:
You can't specify target table 'instructor' for update in FROM clause
Я в замешательстве, потому что когда я пишу
select * from instructor where ID in (select ID from instructor where salary between 13000 and 15000);
это не приводит к ошибке.
мой вопрос это:
- что на самом деле означает это сообщение об ошибке и почему мой код неправильный?
- как переписать этот код, чтобы он работал в безопасном режиме?
спасибо!
4 ответа:
Googling вокруг, популярный ответ, кажется,"выключить безопасный режим":
SET SQL_SAFE_UPDATES = 0; DELETE FROM instructor WHERE salary BETWEEN 13000 AND 15000; SET SQL_SAFE_UPDATES = 1;
если честно, я не могу сказать, что у меня когда-либо была привычка работать в безопасном режиме. Тем не менее, я не совсем согласен с этим ответом, так как он просто предполагает, что вы должны изменить конфигурацию своей базы данных каждый раз, когда вы сталкиваетесь с проблемой.
Итак, ваш второй запрос ближе к отметке, но попадает в другую проблему: MySQL применяет несколько ограничений к подзапросам, и один из них заключается в том, что вы не можете изменить таблицу при выборе из нее в подзапросе.
цитирование из руководства MySQL,ограничения на подзапросы:
В общем, вы не можете изменить таблицу и выбрать из той же таблицы в подзапросе. Например, это ограничение применяется к отчетности следующие формы:
DELETE FROM t WHERE ... (SELECT ... FROM t ...); UPDATE t ... WHERE col = (SELECT ... FROM t ...); {INSERT|REPLACE} INTO t (SELECT ... FROM t ...);
исключение: предыдущий запрет не применяется, если вы используете подзапрос для измененной таблицы в предложении FROM. Пример:
UPDATE t ... WHERE col = (SELECT * FROM (SELECT ... FROM t...) AS _t ...);
здесь результат подзапроса в предложении FROM хранится как временная таблица,поэтому соответствующие строки в t уже были выбраны к моменту обновления до t.
этот последний бит-ваш ответ. Выберите целевые идентификаторы во временной таблице, а затем удалите, сославшись на идентификаторы в этой таблице:
DELETE FROM instructor WHERE id IN ( SELECT temp.id FROM ( SELECT id FROM instructor WHERE salary BETWEEN 13000 AND 15000 ) AS temp );
вы можете обмануть MySQL, думая, что вы на самом деле указываете столбец первичного ключа. Это позволяет "переопределить" безопасный режим.
предполагая, что у вас есть таблица с автоматически увеличивающимся числовым первичным ключом, вы можете сделать следующее:
DELETE FROM tbl WHERE id <> 0