Mysql
 sql >> Datenbank >  >> RDS >> Mysql

MySQL-Fremdschlüsseleinschränkungen, Kaskadenlöschung

Wenn Ihre Kaskadierung ein Produkt löscht, weil es ein Mitglied einer Kategorie war, die getötet wurde, dann haben Sie Ihre Fremdschlüssel falsch eingerichtet. In Anbetracht Ihrer Beispieltabellen sollten Sie die folgende Tabellenkonfiguration haben:

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 werden daneben gelöscht. Die Kaskade bewegt sich nicht weiter nach oben im Baum 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, dann stirbt nur der Eintrag „rot“ in der Kategorientabelle, sowie die beiden Einträge prod/cats:„rote Stiefel“ und „rote Mäntel“.

Die Löschung wird nicht weiter kaskadieren und die Kategorien „Stiefel“ und „Mäntel“ nicht entfernen.

Kommentarfolge:

Sie missverstehen immer noch, wie kaskadierte Löschungen 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 „categories_products“ eingestellt. Wenn Sie die „rote“ Kategorie löschen, werden nur die Datensätze in der Kategorie „category_products“ gelöscht, bei denen category_id = red ist . Es wird keine Datensätze berühren, bei denen 'category_id =blue' ist, und es würde nicht zur Tabelle "products" weitergehen, 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 prüft alle Tabellen, die einen Fremdschlüssel haben, der auf die Tabelle „Kategorien“ zeigt, und löscht die Datensätze, bei denen die übereinstimmende ID 2 ist. Da wir die Fremdschlüsselbeziehung nur in products_categories definiert haben , erhalten Sie nach Abschluss des Löschvorgangs diese Tabelle:

+------------+-------------+
| product_id | category_id |
+------------+-------------+
| 1          | 1           | // red mittens
| 2          | 1           | // red boots
+------------+-------------+

In den products ist kein Fremdschlüssel definiert Tisch, also funktioniert die Kaskade dort nicht, also sind immer noch Stiefel und Fäustlinge aufgelistet. Es gibt einfach keine „blauen Stiefel“ und keine „blauen Fäustlinge“ mehr.