[MySQL] 1. Liste aus Subquerry zwischenspeichern, 2. Trigger

joschilein

Multitalent
ID: 9301
L
5 Mai 2006
1.393
151
Ich möchte bestimmte Zeilen aus zwei Tabellen löschen. Das Problem ist wieder stark vereinfacht dargestellt:

Die erste Tabelle heißt "maulwuerfe". Dort sind alle Maulwürfe gespeichert und alle haben eine eindeutige id. In der zweiten Tabelle "loecher", sind Informationen zu den von den Maulwürfen gegrabenen Löchern gespeichert, unter anderem gibt es dort auch eine Spalte, die die id des Maulwurfs beinhaltet, der dieses Loch gegraben hat.

Nun möchte ich eine Reihe von Maulwürfen löschen (beispielweise weil sie gesprochen wurden und von dieser Erde verschwinden) und gleichzeitig sollen alle ihre Löcher ebenfalls gelöscht werden.
(Die Realitätsnähe ist natürlich nicht wirklich gegeben :roll: )

Es gäbe natürlich folgende Vorgehensweise:
1. SELECT id FROM maulwuerfe WHERE heilig=1
2. Schleife mit DELETE FROM loecher WHERE maulwurf=id
3. DELETE FROM maulwuerfe WHERE heilig=1

Da ich das gerne mit reinen SQL Mitteln lösen würde, käme folgende Zwischenlösung in Frage:

Code:
DELETE
FROM loecher
WHERE maulwurf = ANY(SELECT id
                                FROM maulwuerfe 
                                WHERE heilig=1)
Allerdings werden damit nur die Löcher gelöscht und die Abfrage wird wohl auch bei jeder Zeile der loecher-Tabelle ausgeführt (?), also müsste man die Liste aus Nr.1 doch irgendwie Speichern können um sie dann weiterverwenden zu können.. nur wie?


Alternativ ist mir auch noch die Idee gekommen, ob ich nicht auf die Maulwurf-Tabelle einen Trigger setze, der bei der Löschung eines Maulwurfs automatisch die Löcher-Tabelle bearbeitet und dort die entsprechenden Zeilen löscht. Die Frage ist hier weniger, wie der Trigger für diese Aktionen aussehen muss, sondern generell wie empfehlenswert Trigger sind. Ich habe damit bisher keine Erfahrung und könnte mir vorstellen, dass gerade bei Namensänderungen von Spalten Fehler entstehen.
 
Nur im Hinterkopf habend, dass DELETE auch 2 Tabellen akzeptiert, ratend:
Code:
[FONT=Courier New][B][COLOR=#9932cc]DELETE[/COLOR][/B] [B][COLOR=#9932cc]FROM[/COLOR][/B] `maulwuerfe`,`loecher`
[B][COLOR=#9932cc]WHERE[/COLOR][/B] `maufwurfid` [B][COLOR=#9932cc]IN[/COLOR][/B] ('hier deine Liste, die gelöscht werden solln')[/FONT]
 
Kann man eine solche Liste eigentlich als String schreiben? Ich hab das ganze Manual durchwühlt, aber ich finde dazu nichts.

Edit: Einfach bissel probieren tuts manchmal auch :roll: :arrow: z.B. (1, 2, 3)
 
Laut mysql kann man ja auch mehrere Tabellen im Delete angeben:
Bei der Mehrtabellensyntax löscht DELETE aus jeder Tabelle tbl_name die Datensätze, die die Bedingungen erfüllen.

Dann kannst du das doch in etwa so lösen?
Code:
DELETE
FROM loecher, maulwuerfe 
WHERE loecher.maulwurf = maulwuerfe.id AND maulwuerfe.heilig = 1

Da braucht man dann ja keine subquerys(?)
 
joschilein, trigger sind sehr empfehlenswert, werden zur Zeit aber noch nicht vom MySQL-Optimizer optimiert (also die Anfragen).
Sollte die vom Trigger ausgeführte Operationen keinen (komplexen) Join beinhalten, würde ich auf jedenfall einen Trigger bevorzugen (nutze ich in einer ähnlichen Form wie dein Eingangspost).
 
joschilein, trigger sind sehr empfehlenswert, werden zur Zeit aber noch nicht vom MySQL-Optimizer optimiert (also die Anfragen).
Sollte die vom Trigger ausgeführte Operationen keinen (komplexen) Join beinhalten, würde ich auf jedenfall einen Trigger bevorzugen (nutze ich in einer ähnlichen Form wie dein Eingangspost).

In dem Fall wohl nicht wirklich komplex ;)
Code:
mysql> CREATE DATABASE maulwurf
    -> ;
Query OK, 1 row affected (0.01 sec)

mysql> use maulwurf
Database changed
mysql> create table maulwurf (id INT, heilig INT, PRIMARY KEY (id));
Query OK, 0 rows affected (0.02 sec)

mysql> insert into maulwurf VALUES (1,0),(2,1),(3,0);
Query OK, 3 rows affected (0.00 sec)
Records: 3  Duplicates: 0  Warnings: 0

mysql> create table loecher (id int, maulwurf int, PRIMARY KEY(id));
Query OK, 0 rows affected (0.00 sec)

mysql> insert into loecher values(1,1),(2,2),(3,2),(4,3);
Query OK, 4 rows affected (0.00 sec)
Records: 4  Duplicates: 0  Warnings: 0

mysql> CREATE TRIGGER delloecher BEFORE DELETE ON maulwurf
    -> FOR EACH ROW DELETE FROM loecher WHERE loecher.maulwurf = OLD.id;
Query OK, 0 rows affected (0.00 sec)

mysql> delete from maulwurf where heilig = 1;
Query OK, 1 row affected (0.00 sec)

mysql> select * from maulwurf;
+----+--------+
| id | heilig |
+----+--------+
|  1 |      0 |
|  3 |      0 |
+----+--------+
2 rows in set (0.00 sec)

mysql> select * from loecher;
+----+----------+
| id | maulwurf |
+----+----------+
|  1 |        1 |
|  4 |        3 |
+----+----------+
2 rows in set (0.00 sec)

mysql>

Ansonsten die Variante von Moloc (wobei man bei mehreren Tabellen USING mit angeben muss).
 
Zuletzt bearbeitet: