mysql verwijderen in veilige modus

Ik heb een tafelinstructeur en ik wil de records met een salaris in een bereik verwijderen
Een intuïtieve manier is als volgt:

delete from instructor where salary between 13000 and 15000;

In de veilige modus kan ik echter geen record verwijderen zonder een primaire sleutel (ID) op te geven.

Dus ik schrijf de volgende sql:

delete from instructor where ID in (select ID from instructor where salary between 13000 and 15000);

Er is echter een fout opgetreden:

You can't specify target table 'instructor' for update in FROM clause

Ik ben in de war, want als ik schrijf

select * from instructor where ID in (select ID from instructor where salary between 13000 and 15000);

het geeft geen fout.

Mijn vraag is:

  1. wat betekent deze foutmelding eigenlijk en waarom is mijn code verkeerd?
  2. hoe herschrijf ik deze code zodat deze werkt in de veilige modus?

Bedankt!


Antwoord 1, autoriteit 100%

Googelend, lijkt het populaire antwoord “gewoon zet veilige modus uit”:

SET SQL_SAFE_UPDATES = 0;
DELETE FROM instructor WHERE salary BETWEEN 13000 AND 15000;
SET SQL_SAFE_UPDATES = 1;

Als ik eerlijk ben, kan ik niet zeggen dat ik er ooit een gewoonte van heb gemaakt om in de veilige modus te rennen. Toch voel ik me niet helemaal op mijn gemak met dit antwoord, omdat het ervan uitgaat dat je je databaseconfiguratie moet wijzigen telkens als je een probleem tegenkomt.

Dus uw tweede zoekopdracht is dichter bij het doel, maar stuit op een ander probleem: MySQL past een paar beperkingen toe op subquery’s, en een daarvan is dat u een tabel niet kunt wijzigen terwijl u er in een subquery uit selecteert.

p>

Citaat uit de MySQL-handleiding, Beperkingen op subquery’s:

Over het algemeen kunt u een tabel niet wijzigen en uit dezelfde tabel selecteren
in een subquery. Deze beperking is bijvoorbeeld van toepassing op verklaringen van:
de volgende vormen:

DELETE FROM t WHERE ... (SELECT ... FROM t ...);
UPDATE t ... WHERE col = (SELECT ... FROM t ...);
{INSERT|REPLACE} INTO t (SELECT ... FROM t ...);

Uitzondering: het voorgaande verbod is niet van toepassing als u een subquery gebruikt voor de gewijzigde tabel in de FROM-clausule. Voorbeeld:

UPDATE t ... WHERE col = (SELECT * FROM (SELECT ... FROM t...) AS _t ...);

Hier wordt het resultaat van de subquery in de FROM-component opgeslagen als een tijdelijke tabel, dus de relevante rijen in t zijn al geselecteerd op het moment dat de update naar t plaatsvindt.

Dat laatste is uw antwoord. Selecteer doel-ID’s in een tijdelijke tabel en verwijder vervolgens door te verwijzen naar de ID’s in die tabel:

DELETE FROM instructor WHERE id IN (
  SELECT temp.id FROM (
    SELECT id FROM instructor WHERE salary BETWEEN 13000 AND 15000
  ) AS temp
);

SQLFiddle-demo.


Antwoord 2, autoriteit 9%

Je kunt MySQL voor de gek houden door te denken dat je eigenlijk een primaire sleutelkolom specificeert. Hiermee kunt u de veilige modus “overschrijven”.

Ervan uitgaande dat u een tabel heeft met een automatisch oplopende numerieke primaire sleutel, kunt u het volgende doen:

DELETE FROM tbl WHERE id <> 0

Antwoord 3, autoriteit 5%

Veilige modus uitschakelen in Mysql workbench 6.3.4.0

Bewerkmenu => Voorkeuren => SQL Editor: Andere sectie: klik op “Veilige updates” … om de optie uit te vinken

Workbench-voorkeuren


Antwoord 4

Ik heb een veel eenvoudigere oplossing, het werkt voor mij; het is ook een tijdelijke oplossing, maar kan bruikbaar zijn en u hoeft uw instellingen niet te wijzigen. Ik neem aan dat je waarde kunt gebruiken die er nooit zal zijn, dan gebruik je het in je WHERE-clausule

VERWIJDEREN UIT MyTable WAAR MyField IS_NOT_EQUAL AnyValueNoItemOnMyFieldWillEverHave

Ik hou ook niet zo van die oplossing, daarom ben ik hier, maar het werkt en het lijkt beter dan wat het is beantwoord

Other episodes