Ich habe eine Tabelle Ausbilder und möchte die Datensätze löschen, deren Gehalt in einem bestimmten Bereich liegt. Ein intuitiver Weg ist wie folgt:
delete from instructor where salary between 13000 and 15000;
Im abgesicherten Modus kann ich einen Datensatz jedoch nicht 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 tritt jedoch ein Fehler auf:
You can't specify target table 'instructor' for update in FROM clause
Ich bin verwirrt, denn wenn ich schreibe
select * from instructor where ID in (select ID from instructor where salary between 13000 and 15000);
keine Fehlermeldung erzeugt.
Meine Frage ist:
Danke!
Wenn man sich umschaut, scheint die gängige Antwort zu sein "schalten Sie einfach den abgesicherten Modus aus":
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, dass ich es mir jemals zur Gewohnheit gemacht habe, im abgesicherten Modus zu arbeiten. Trotzdem bin ich mit dieser Antwort nicht ganz zufrieden, da sie einfach davon ausgeht, dass Sie Ihre Datenbankkonfiguration jedes Mal ändern sollten, wenn Sie auf ein Problem stoßen.
Ihre zweite Abfrage ist näher am Ziel, stößt aber auf ein anderes Problem: MySQL wendet einige Einschränkungen auf Unterabfragen an, und eine davon ist, dass Sie eine Tabelle nicht ändern können, während Sie in einer Unterabfrage aus ihr auswählen.
Ich zitiere aus dem MySQL-Handbuch, Restrictions on Subqueries:
Im Allgemeinen können Sie eine Tabelle nicht ändern und aus derselben Tabelle auswählen in einer Unterabfrage. Diese Einschränkung gilt zum Beispiel für Statements der der folgenden Formen:
DELETE FROM t WHERE ... (SELECT ... FROM t ...); UPDATE t ... WHERE col = (SELECT ... FROM t ...); {INSERT|REPLACE} INTO t (SELECT ... FROM t ...);
Ausnahme: Das obige Verbot gilt nicht, wenn Sie in der FROM-Klausel eine Subquery für die geänderte Tabelle 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, so dass die relevanten Zeilen in t bereits ausgewählt sind, wenn die Aktualisierung von t erfolgt.
Der letzte Teil ist Ihre Antwort. Wählen Sie Ziel-IDs in einer temporären Tabelle aus und löschen Sie dann, 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
);
Sie können MySQL austricksen, so dass es denkt, Sie würden tatsächlich eine Primärschlüsselspalte angeben. Dadurch können Sie den sicheren Modus außer Kraft setzen.
Angenommen, Sie haben eine Tabelle mit einem automatisch inkrementierenden numerischen Primärschlüssel, könnten Sie Folgendes tun:
DELETE FROM tbl WHERE id <> 0
Ausschalten des abgesicherten Modus in Mysql Workbench 6.3.4.0
Menü Bearbeiten => Einstellungen => SQL-Editor : Abschnitt Sonstiges: Klicken Sie auf "Sichere Updates" ... um die Option zu deaktivieren