web-dev-qa-db-de.com

mysql löschen im abgesicherten Modus

Ich habe einen Tischinstruktor und möchte die Datensätze löschen, deren Gehalt in einem Bereich liegt Eine intuitive Art ist wie folgt: 

delete from instructor where salary between 13000 and 15000;

Im abgesicherten Modus kann ich jedoch keinen Datensatz löschen, ohne einen Primärschlüssel (ID) anzugeben.

Also schreibe ich die folgende SQL: 

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

Es gibt jedoch einen Fehler:

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

Ich bin verwirrt, wenn ich schreibe

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

es wird kein Fehler ausgegeben.

Meine Frage ist:

  1. was bedeutet diese Fehlermeldung und warum ist mein Code falsch?
  2. wie schreibe ich diesen Code um, damit er im abgesicherten Modus funktioniert?

Vielen Dank!

69
roland luo

Beim Googeln scheint die beliebte Antwort zu sein - "Nur den sicheren Modus ausschalten" :

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

Wenn ich ehrlich bin, kann ich nicht behaupten, ich habe es mir zur Gewohnheit gemacht, im abgesicherten Modus zu laufen. Trotzdem bin ich mit dieser Antwort nicht ganz zufrieden, da davon ausgegangen wird, dass Sie Ihre Datenbankkonfiguration jedes Mal ändern sollten, wenn Sie auf ein Problem stoßen.

Ihre zweite Abfrage ist also näher an der Marke, hat jedoch ein anderes Problem: MySQL hat einige Einschränkungen für Unterabfragen, und eine davon ist, dass Sie eine Tabelle nicht ändern können, während Sie in einer Unterabfrage eine Auswahl treffen.

Zitieren aus dem MySQL-Handbuch, Einschränkungen für Unterabfragen :

Im Allgemeinen können Sie eine Tabelle nicht ändern und aus derselben Tabelle auswählen in einer Unterabfrage. Diese Einschränkung gilt beispielsweise für Anweisungen von die folgenden formulare:

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

Ausnahme: Das vorstehende Verbot gilt nicht, wenn Sie eine Unterabfrage für die geänderte Tabelle in der FROM-Klausel verwenden. Beispiel:

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

Hier wird das Ergebnis der Unterabfrage in der FROM-Klausel als temporäre Tabelle gespeichert, sodass die relevanten Zeilen in t bereits zum Zeitpunkt der Aktualisierung auf t ausgewählt wurden.

Das letzte Stück ist deine Antwort. Wählen Sie Ziel-IDs in einer temporären Tabelle aus und löschen Sie sie, indem Sie auf die IDs in dieser Tabelle verweisen:

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

SQLFiddle Demo .

178
rutter

Sie können MySQL dazu bringen, zu glauben, dass Sie tatsächlich eine Primärschlüsselspalte angeben. Dadurch können Sie den abgesicherten Modus "außer Kraft setzen".

Vorausgesetzt, Sie haben eine Tabelle mit einem automatisch inkrementierenden numerischen Primärschlüssel, können Sie Folgendes tun:

DELETE FROM tbl WHERE id <> 0
12
Hugo Zink

Deaktivieren des abgesicherten Modus in der MySQL-Workbench 6.3.4.0

Menü Bearbeiten => Voreinstellungen => SQL Editor: Andere Bereiche: Klicken Sie auf "Sichere Updates" ..., um die Option zu deaktivieren

Bildbeschreibung hier eingeben

10
Peter B

Ich habe eine weitaus einfachere Lösung, sie arbeitet für mich. Es ist auch eine Problemumgehung, kann jedoch verwendet werden und Sie müssen Ihre Einstellungen nicht ändern. Ich gehe davon aus, dass Sie einen Wert verwenden können, der niemals da sein wird. Dann verwenden Sie ihn für Ihre WHERE-Klausel

DELETE FROM MyTable WO MyField IS_NOT_EQUAL AnyValueNoItemOnMyFieldWillEverHave

Ich mag diese Lösung auch nicht sehr, deshalb bin ich hier, aber sie funktioniert und scheint besser zu sein als das, was sie beantwortet hat

0
Joaq

Anscheinend verfügt Ihre MySql-Sitzung über die Safe-Update-Option. Dies bedeutet, dass Sie keine Datensätze aktualisieren oder löschen können, ohne einen Schlüssel (z. B. Primärschlüssel) in der where-Klausel anzugeben.

Versuchen

SET SQL_SAFE_UPDATES = 0;

0
yakob abada