580 Stimmen

Löschen mit Join in MySQL

Hier ist das Skript zum Erstellen meiner Tabellen:

CREATE TABLE clients (
   client_i INT(11),
   PRIMARY KEY (client_id)
);
CREATE TABLE projects (
   project_id INT(11) UNSIGNED,
   client_id INT(11) UNSIGNED,
   PRIMARY KEY (project_id)
);
CREATE TABLE posts (
   post_id INT(11) UNSIGNED,
   project_id INT(11) UNSIGNED,
   PRIMARY KEY (post_id)
);

Wenn ich in meinem PHP-Code einen Kunden lösche, möchte ich alle Projektbeiträge löschen:

DELETE 
FROM posts
INNER JOIN projects ON projects.project_id = posts.project_id
WHERE projects.client_id = :client_id;

Die Tabelle posts hat keinen Fremdschlüssel client_id nur project_id . Ich möchte die Stellen in den Projekten löschen, die den Pass client_id .

Dies funktioniert im Moment nicht, da keine Beiträge gelöscht werden.

13 Stimmen

Ich denke, Yehosef Antwort sollte die akzeptierte sein, da er Join verwendet, wie Sie gefragt und dass es besser als mit einer IN-Klausel, wie yukondude vorgeschlagen...

3 Stimmen

Das bevorzugte Muster ist ein DELETE posts FROM posts JOIN projects ... und nicht eine IN (subquery) Muster. (Die Antwort von Yehosef gibt ein Beispiel für das bevorzugte Muster).

1 Stimmen

@GerardoGrignoli, führt es besser für eine bestimmte Engine oder Version von MySQL? Es gibt keinen Grund, warum die beiden Abfragen unterschiedlich funktionieren sollten, da sie AFAIK identisch sind. Natürlich, wenn ich einen Nickel für jedes Mal hätte, wenn mein Abfrageoptimierer etwas Dummes macht....

1456voto

Yehosef Punkte 17023

Sie müssen nur angeben, dass Sie die Einträge aus dem Verzeichnis posts Tisch:

DELETE posts
FROM posts
INNER JOIN projects ON projects.project_id = posts.project_id
WHERE projects.client_id = :client_id

EDIT: Weitere Informationen finden Sie unter diese alternative Antwort

127 Stimmen

Es sei darauf hingewiesen, dass dies die richtige Antwort ist, da der Join Sie zwingt, "DELETE posts FROM posts" anstelle des normalen "DELETE FROM posts" zu verwenden, da die zu löschende Tabelle nicht mehr eindeutig ist. Vielen Dank!

9 Stimmen

Beachten Sie, dass Sie hier nicht die Methode "as" verwenden können, z. B. inner join projects as p on p.project_id ...

16 Stimmen

Sie können einen Alias für verbundene Tabellen verwenden, aber nicht für die Haupttabelle (Beiträge). "DELETE posts FROM posts INNER JOIN projects p ON p.project_id = posts.project_id"

114voto

Pacerier Punkte 80774

Da Sie mehrere Tabellen auswählen, ist die Tabelle, aus der gelöscht werden soll, nicht mehr eindeutig. Y Wählen Sie :

DELETE posts FROM posts
INNER JOIN projects ON projects.project_id = posts.project_id
WHERE projects.client_id = :client_id

In diesem Fall, table_name1 y table_name2 sind dieselbe Tabelle, so dass dies funktionieren wird:

DELETE projects FROM posts INNER JOIN [...]

Sie können sogar aus beiden Tabellen löschen, wenn Sie das möchten:

DELETE posts, projects FROM posts INNER JOIN [...]

Beachten Sie, dass order by y limit funktioniert nicht bei Löschungen aus mehreren Tabellen .

Beachten Sie auch, dass Sie, wenn Sie einen Alias für eine Tabelle deklarieren, den Alias verwenden müssen, wenn Sie sich auf die Tabelle beziehen:

DELETE p FROM posts as p INNER JOIN [...]

Beiträge von Carpetsmoker und anderen .

5 Stimmen

@Yehosef, Es gibt eine Gruppe von Leuten, die die CAPS wirklich krass finden. Ich glaube, ich bin nicht der Einzige, ich habe auch schon einige Leute gesehen, die Kleinbuchstaben verwenden.

1 Stimmen

Das ist nur fair - ich respektiere Ihr Recht, Ihre Antwort in dem Stil zu schreiben, den Sie mögen ;)

1 Stimmen

Du magst wirklich keine großgeschriebenen Schlüsselwörter, oder? :D Ich habe gerade gesehen, wie du geschrieben hast <!doctype..> wenn andere Leute schreiben würden <!DOCTYPE..> ^^ Aber deine Antwort hat mir trotzdem geholfen, also nimm mein Upvote :)

53voto

Property Spain Punkte 479

Sie können auch ALIAS verwenden, wie dies funktioniert es gerade auf meine Datenbank verwendet! t ist die Tabelle müssen aus löschen!

DELETE t FROM posts t
INNER JOIN projects p ON t.project_id = p.project_id
AND t.client_id = p.client_id

1 Stimmen

Dies ist nützlich bei Compound Key Joins, um die Wiederholung der Tabellennamen zu vermeiden

1 Stimmen

"Sie können einen Alias für verbundene Tabellen verwenden, aber nicht für die Haupttabelle (posts). 'DELETE posts FROM posts INNER JOIN projects p ON p.project_id = posts.project_id'" -@Weboide

3 Stimmen

Tatsächlich (zitiert nach dev.mysql.com/doc/refman/5.0/de/delete.html ) "Wenn Sie einen Alias für eine Tabelle deklarieren, müssen Sie den Alias verwenden, wenn Sie sich auf die Tabelle beziehen: DELETE t1 FROM test AS t1, test2 WHERE ..." also ist die Verwendung eines Alias in Ordnung.

52voto

ivanhoe Punkte 4129

Oder dasselbe, nur mit einer etwas anderen (IMO freundlicheren) Syntax:

DELETE FROM posts 
USING posts, projects 
WHERE projects.project_id = posts.project_id AND projects.client_id = :client_id;

BTW, mit Mysql mit Joins ist fast immer ein Weg schneller als Subqueries...

0 Stimmen

Was bedeutet der Begriff USING?

1 Stimmen

13 Stimmen

@bigtex777: Bitte beachten Sie, dass das Schlüsselwort USING in SELECT-Anweisungen wenig mit dem gleichen Schlüsselwort in einer DELETE-Anweisung zu tun hat. In SELECTs gibt es die Liste der zu verknüpfenden Spalten an, während es in DELETEs eine Liste aller Tabellen in einer Verknüpfung ist

29voto

yukondude Punkte 23093

Ich bin eher an die Subquery-Lösung für dieses Problem gewöhnt, aber ich habe sie nicht in MySQL ausprobiert:

DELETE  FROM posts
WHERE   project_id IN (
            SELECT  project_id
            FROM    projects
            WHERE   client_id = :client_id
        );

90 Stimmen

Sie sollten die Verwendung des IN-Schlüsselworts in SQL wirklich vermeiden (auch wenn es für Anfänger in der Regel leichter zu verstehen ist) und stattdessen (wenn möglich) JOIN verwenden, da Unterabfragen in der Regel sehr viel langsamer sind.

14 Stimmen

Dies neigt dazu, die DB zum Absturz zu bringen, wenn eine große Anzahl von Zeilen durch die Unterabfrage zurückgegeben werden. Außerdem ist es immens langsam.

0 Stimmen

@user276648 und Raj Sekharan haben Recht: Das ist eine langsame Methode. Aber ich erinnere mich genau, dass ich mit einer RDBMS-Engine zu tun hatte, die sich weigerte, ein DELETE mit einem Join durchzuführen. Ich wünschte, ich könnte mich erinnern, welche. Auf jeden Fall finde ich das IN auf den ersten Blick leichter zu verstehen, und solange es kein quantifizierbares Leistungsproblem gibt, würde ich es so lassen, wie es ist.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X