Wenn Ihre Kaskadierung ein Produkt löscht, weil es Mitglied einer Kategorie war, die getötet wurde, haben Sie Ihre Fremdschlüssel nicht ordnungsgemäß eingerichtet. In Anbetracht Ihrer Beispieltabellen sollten Sie die folgende Tabelle einrichten:
CREATE TABLE categories (
id int unsigned not null primary key,
name VARCHAR(255) default null
)Engine=InnoDB;
CREATE TABLE products (
id int unsigned not null primary key,
name VARCHAR(255) default null
)Engine=InnoDB;
CREATE TABLE categories_products (
category_id int unsigned not null,
product_id int unsigned not null,
PRIMARY KEY (category_id, product_id),
KEY pkey (product_id),
FOREIGN KEY (category_id) REFERENCES categories (id)
ON DELETE CASCADE
ON UPDATE CASCADE,
FOREIGN KEY (product_id) REFERENCES products (id)
ON DELETE CASCADE
ON UPDATE CASCADE
)Engine=InnoDB;
Auf diese Weise können Sie ein Produkt ODER eine Kategorie löschen, und nur die zugehörigen Datensätze in category_products sterben daneben. Die Kaskade bewegt sich nicht weiter nach oben und löscht die übergeordnete Produkt- / Kategorietabelle.
z.B
products: boots, mittens, hats, coats
categories: red, green, blue, white, black
prod/cats: red boots, green mittens, red coats, black hats
Wenn Sie die Kategorie 'rot' löschen, stirbt nur der Eintrag 'rot' in der Kategorietabelle sowie die beiden Einträge prod / cat: 'rote Stiefel' und 'rote Mäntel'.
Das Löschen wird nicht weiter kaskadiert und die Kategorien "Stiefel" und "Mäntel" werden nicht entfernt.
Kommentar Follow-up:
Sie verstehen immer noch falsch, wie kaskadierte Löschvorgänge funktionieren. Sie wirken sich nur auf die Tabellen aus, in denen die "On Delete Cascade" definiert ist. In diesem Fall wird die Kaskade in der Tabelle "category_products" festgelegt. Wenn Sie die Kategorie 'rot' löschen, sind die einzigen Datensätze, die in Kategorien_Produkten kaskadiert werden, diejenigen, bei denen category_id = red
. Es werden keine Datensätze berührt, bei denen 'category_id = blue' ist, und es wird nicht zur Tabelle "products" weitergeleitet, da in dieser Tabelle kein Fremdschlüssel definiert ist.
Hier ist ein konkreteres Beispiel:
categories: products:
+----+------+ +----+---------+
| id | name | | id | name |
+----+------+ +----+---------+
| 1 | red | | 1 | mittens |
| 2 | blue | | 2 | boots |
+---++------+ +----+---------+
products_categories:
+------------+-------------+
| product_id | category_id |
+------------+-------------+
| 1 | 1 | // red mittens
| 1 | 2 | // blue mittens
| 2 | 1 | // red boots
| 2 | 2 | // blue boots
+------------+-------------+
Angenommen, Sie löschen Kategorie 2 (blau):
DELETE FROM categories WHERE (id = 2);
Das DBMS überprüft alle Tabellen, deren Fremdschlüssel auf die Tabelle 'Kategorien' verweist, und löscht die Datensätze, in denen die übereinstimmende ID 2 lautet. Da wir nur die Fremdschlüsselbeziehung in definiert haben products_categories
, erhalten Sie diese Tabelle einmal am Löschen abgeschlossen:
+------------+-------------+
| product_id | category_id |
+------------+-------------+
| 1 | 1 | // red mittens
| 2 | 1 | // red boots
+------------+-------------+
In der products
Tabelle ist kein Fremdschlüssel definiert , sodass die Kaskade dort nicht funktioniert. Sie haben also immer noch Stiefel und Fäustlinge aufgelistet. Es gibt nur noch keine "blauen Stiefel" und keine "blauen Fäustlinge" mehr.