Mysql delete в безопасном режиме
У меня есть инструктор таблицы, и я хочу удалить записи с зарплатой в диапазоне
Интуитивно понятный способ:
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);
он не вызывает ошибку.
Мой вопрос:
- что действительно означает это сообщение об ошибке и почему мой код неправильный?
- как переписать этот код, чтобы он работал в безопасном режиме?
Спасибо!
Ответы
Ответ 1
Похоже, что популярный ответ выглядит "просто отключить безопасный режим" :
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
);
демоверсия SQLFiddle.
Ответ 2
Вы можете обмануть MySQL, думая, что на самом деле вы указываете столбец первичного ключа. Это позволяет вам "переопределить" безопасный режим.
Предполагая, что у вас есть таблица с автоматически увеличивающимся числовым первичным ключом, вы можете сделать следующее:
DELETE FROM tbl WHERE id <> 0
Ответ 3
Отключение безопасного режима в Workbench Mysql 6.3.4.0
Меню "Правка" = > "Настройки" = > "Редактор SQL": другой раздел: нажмите "Безопасные обновления"..., чтобы снять флажок
введите здесь описание изображения
Ответ 4
Похоже, что в вашем сеансе MySql есть опция безопасных обновлений. Это означает, что вы не можете обновлять или удалять записи без указания ключа (например, первичного ключа) в предложении where.
Try
SET SQL_SAFE_UPDATES = 0;
Ответ 5
У меня гораздо более простое решение, оно работает для меня; это также обходное решение, но может быть использовано, и вам не нужно менять настройки. Я предполагаю, что вы можете использовать значение, которое никогда не будет там, тогда вы используете его в своем предложении WHERE
DELETE FROM MyTable WHERE MyField IS_NOT_EQUAL AnyValueNoItemOnMyFieldWillEverHave
Мне не нравится это решение слишком много, поэтому я здесь, но он работает, и это кажется лучше, чем то, на что он был дан ответ