Mysql
 sql >> Base de données >  >> RDS >> Mysql

Contraintes de clé étrangère MySQL, suppression en cascade

Si votre cascade supprime un produit car il faisait partie d'une catégorie qui a été supprimée, vous avez mal configuré vos clés étrangères. Compte tenu de vos exemples de tables, vous devriez avoir la configuration de table suivante :

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;

De cette façon, vous pouvez supprimer un produit OU une catégorie, et seuls les enregistrements associés dans categories_products mourront à côté. La cascade ne montera pas plus haut dans l'arborescence et supprimera la table de produits/catégories parent.

ex.

products: boots, mittens, hats, coats
categories: red, green, blue, white, black

prod/cats: red boots, green mittens, red coats, black hats

Si vous supprimez la catégorie 'rouge', seule l'entrée 'rouge' dans le tableau des catégories meurt, ainsi que les deux entrées prod/chats :'bottes rouges' et 'manteaux rouges'.

La suppression n'ira pas plus loin et ne supprimera pas les catégories "bottes" et "manteaux".

suivi des commentaires :

vous ne comprenez toujours pas comment fonctionnent les suppressions en cascade. Ils n'affectent que les tables dans lesquelles la "cascade à la suppression" est définie. Dans ce cas, la cascade est définie dans la table "categories_products". Si vous supprimez la catégorie "rouge", les seuls enregistrements qui seront supprimés en cascade dans categories_products sont ceux où category_id = red . Il ne touchera aucun enregistrement où 'category_id =blue', et il ne se déplacera pas vers la table "products", car il n'y a pas de clé étrangère définie dans cette table.

Voici un exemple plus concret :

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
+------------+-------------+

Supposons que vous supprimiez la catégorie 2 (bleu) :

DELETE FROM categories WHERE (id = 2);

le SGBD examinera toutes les tables qui ont une clé étrangère pointant vers la table 'categories' et supprimera les enregistrements où l'identifiant correspondant est 2. Puisque nous avons uniquement défini la relation de clé étrangère dans products_categories , vous vous retrouvez avec ce tableau une fois la suppression terminée :

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

Il n'y a pas de clé étrangère définie dans les products table, donc la cascade ne fonctionnera pas là-bas, donc vous avez toujours des bottes et des mitaines répertoriées. Il n'y a plus de "bottes bleues" ni de "mitaines bleues".