mysql видалити в безпечному режимі - -


87

У мене є інструктор таблиці, і я хочу видалити записи, які мають зарплату в діапазоні. Інтуїтивний спосіб такий:

delete from instructor where salary between 13000 and 15000;

Однак у безпечному режимі я не можу видалити запис без надання первинного ключа (ідентифікатора).

Тому я пишу такий 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. що насправді означає це повідомлення про помилку і чому мій код помилковий?
  2. як переписати цей код, щоб він працював у безпечному режимі?

Дякую!


Ви хотіли тримати безпечний режим увімкненим? і ви використовуєте робочий стіл mySql?
wribit

відповідь на обидва ваші запитання - так. І я здивований, що коли я використовував jdbc для видалення записів у базах даних mysql без ПК, це не видає помилки. Тож безпечний режим призначений лише для робочого середовища MySQL?
roland luo

1
ні - я запитував, тому що якщо ви хочете вимкнути його в робочому середовищі mySQL, я міг би сказати вам, як. Особисто я працюю з цим ...
Потрібно

Відповіді:


224

Погугливши, здається, популярною відповіддю є "просто вимкнути безпечний режим" :

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 .


6
Дякуємо за пояснення! Однак я спробував ваш код у робочому середовищі mysql, і він все одно сказав: "Ви використовуєте безпечний режим оновлення, і ви намагалися оновити таблицю без ДЕ, де використовується стовпець KEY".
roland luo

Це несподівано. Ваш первинний ключ під іншою назвою? Я помічаю, що ваше запитання, здається, вказує, що воно назване ID, тоді як моя відповідь використовує id.
рутер

Так, я зміню його на ідентифікатор, і він не працює. Я спробував видалити з інструктора, де ID = '1', і це працює, тому ідентифікатор є первинним ключем
roland luo

1
@rolandluo Я знаю, що це було давно, але мені цікаво, чи ти коли-небудь з’ясовував обхідний шлях. Очевидно, що цей метод спрацював за інших обставин, тому мені цікаво, чому ваш випадок відрізняється. Щось конкретне для вашого сервера чи версії, можливо?
рутер

19

Ви можете обдурити MySQL, думаючи, що ви насправді вказуєте стовпець первинного ключа. Це дозволяє "замінити" безпечний режим.

Якщо припустити, що у вас є таблиця з автоматично збільшуючим числовим первинним ключем, ви можете зробити наступне:

DELETE FROM tbl WHERE id <> 0

12

Вимкнення безпечного режиму в робочому середовищі Mysql 6.3.4.0

Меню редагування => Налаштування => Редактор SQL: Інший розділ: натисніть "Безпечні оновлення" ..., щоб зняти прапорець

Налаштування робочого середовища


2
"як переписати цей код, щоб він працював у безпечному режимі ?" ==> Ваша відповідь розповідає, як вимкнути безпечний режим;)
ByteHamster

2
Вибачте, я абсолютно неправильно зрозумів запитання. Я знайшов цю тему, коли мені не вдалося видалити з таблиць за допомогою робочого середовища Mysql, і було подібне запитання в коментарі до робочого середовища MySQL, але я не можу створювати коментарі. Я думав, що було б непоганим місцем написати це тут для подальшої довідки ...
Пітер Б,

0

У мене є набагато простіше рішення, воно працює для мене; це також обхідний шлях, але він може бути корисним, і вам не доведеться змінювати свої налаштування. Я припускаю, що ви можете використовувати значення, якого ніколи не буде, тоді ви використовуєте його у своєму реченні WHERE

ВИДАЛИТИ З MyTable ДЕ MyField IS_NOT_EQUAL AnyValueNoItemOnMyFieldWillEverHave

Мені це рішення теж не надто подобається, тому я тут, але воно працює, і, здається, краще, ніж те, на що на нього відповіли

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.