Подтвердить что ты не робот

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);

он не вызывает ошибку.

Мой вопрос:

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

Спасибо!

4b9b3361

Ответ 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

Мне не нравится это решение слишком много, поэтому я здесь, но он работает, и это кажется лучше, чем то, на что он был дан ответ