Mam instruktora tabeli i chcę usunąć rekordy, które mają wynagrodzenie w przedziale. Intuicyjny sposób wygląda tak:
delete from instructor where salary between 13000 and 15000;
Jednak w trybie awaryjnym nie mogę usunąć rekordu bez podania klucza podstawowego (ID).
Więc piszę następujący sql:
delete from instructor where ID in (select ID from instructor where salary between 13000 and 15000);
Jednak jest błąd:
You can't specify target table 'instructor' for update in FROM clause
Jestem zdezorientowany, ponieważ kiedy piszę
select * from instructor where ID in (select ID from instructor where salary between 13000 and 15000);
nie powoduje błędu.
Moje pytanie brzmi:
- co naprawdę oznacza ten komunikat o błędzie i dlaczego mój kod jest nieprawidłowy?
- jak przepisać ten kod, aby działał w trybie awaryjnym?
Dzięki!
Odpowiedzi:
W wyszukiwarce Google popularną odpowiedzią wydaje się być „po prostu wyłącz tryb awaryjny” :
SET SQL_SAFE_UPDATES = 0; DELETE FROM instructor WHERE salary BETWEEN 13000 AND 15000; SET SQL_SAFE_UPDATES = 1;
Szczerze mówiąc, nie mogę powiedzieć, żebym kiedykolwiek miał w zwyczaju biegać w trybie awaryjnym. Mimo to nie jestem do końca zadowolony z tej odpowiedzi, ponieważ zakłada ona po prostu, że powinieneś zmieniać konfigurację bazy danych za każdym razem, gdy napotkasz problem.
Zatem twoje drugie zapytanie jest bliżej znaku, ale napotyka inny problem: MySQL nakłada kilka ograniczeń na podzapytania, a jednym z nich jest to, że nie możesz modyfikować tabeli podczas wybierania jej w podzapytaniu.
Cytowanie z podręcznika MySQL, Restrictions on Subqueries :
Ta ostatnia odpowiedź to twoja odpowiedź. Wybierz identyfikatory docelowe w tabeli tymczasowej, a następnie usuń, odwołując się do identyfikatorów w tej tabeli:
DELETE FROM instructor WHERE id IN ( SELECT temp.id FROM ( SELECT id FROM instructor WHERE salary BETWEEN 13000 AND 15000 ) AS temp );
Demo SQLFiddle .
źródło
ID
, podczas gdy moja odpowiedź używaid
.Możesz oszukać MySQL, aby pomyślał, że faktycznie określasz kolumnę klucza podstawowego. Pozwala to na „przesłonięcie” trybu awaryjnego.
Zakładając, że masz tabelę z automatycznie zwiększającym się liczbowym kluczem podstawowym, możesz wykonać następujące czynności:
DELETE FROM tbl WHERE id <> 0
źródło
Wyłączanie trybu awaryjnego w środowisku roboczym MySQL 6.3.4.0
Menu Edytuj => Preferencje => Edytor SQL: Sekcja Inne: kliknij „Bezpieczne aktualizacje” ... aby odznaczyć opcję
źródło
Mam znacznie prostsze rozwiązanie, działa dla mnie; jest to również obejście, ale może być użyteczne i nie musisz zmieniać ustawień. Zakładam, że możesz użyć wartości, której nigdy nie będzie, a następnie użyj jej w swojej klauzuli WHERE
USUŃ Z MyTable WHERE MyField IS_NOT_EQUAL AnyValueNoItemOnMyFieldWillEverHave
To rozwiązanie też mi się nie podoba, dlatego tu jestem, ale działa i wydaje się lepsze niż ta, na którą odpowiedziano
źródło