Je souhaite utiliser des clés étrangères pour conserver l'intégrité et éviter les orphelins (j'utilise déjà innoDB).
Comment créer une instruction SQL DELETE ON CASCADE?
Si je supprime une catégorie, comment puis-je m'assurer qu'elle ne supprimera pas les produits qui sont également liés à d'autres catégories.
Le tableau croisé dynamique "categories_products" crée une relation plusieurs-à-plusieurs entre les deux autres tables.
categories
- id (INT)
- name (VARCHAR 255)
products
- id
- name
- price
categories_products
- categories_id
- products_id
mysql
foreign-keys
innodb
Cudos
la source
la source
Réponses:
Si votre mise en cascade supprime l'arme nucléaire d'un produit parce qu'il faisait partie d'une catégorie qui a été tuée, c'est que vous avez mal configuré vos clés étrangères. Compte tenu de vos exemples de tables, vous devriez avoir la configuration de table suivante:
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 se déplacera pas plus haut dans l'arborescence et supprimera la table de produits / catégories parent.
par exemple
Si vous supprimez la catégorie «rouge», alors seule l'entrée «rouge» dans le tableau des catégories meurt, ainsi que les deux entrées prod / cats: «red boots» et «red coats».
La suppression ne se répercutera 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 le tableau "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:
Disons que vous supprimez la catégorie # 2 (bleu):
le SGBD examinera toutes les tables qui ont une clé étrangère pointant vers la table 'categories', et supprimera les enregistrements où l'ID correspondant est 2. Puisque nous n'avons défini la relation de clé étrangère que dans
products_categories
, vous vous retrouvez avec cette table une fois le la suppression est terminée:Il n'y a pas de clé étrangère définie dans le
products
tableau, 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».la source
CASCADE
opérations. Sinon, la valeur par défaut de MySQL, MyISAM, sera utilisée et MyISAM ne prend pas en charge lesCASCADE
opérations. Pour ce faire, ajoutez simplementENGINE InnoDB
avant le dernier;
.J'ai été confus par la réponse à cette question, alors j'ai créé un cas de test dans MySQL, j'espère que cela aide
la source
Je pense (je ne suis pas certain) que les contraintes de clé étrangère ne feront pas exactement ce que vous voulez étant donné la conception de votre table. La meilleure chose à faire est peut-être de définir une procédure stockée qui supprimera une catégorie comme vous le souhaitez, puis d'appeler cette procédure chaque fois que vous souhaitez supprimer une catégorie.
Vous devez également ajouter les contraintes de clé étrangère suivantes à la table de liaison:
La clause CONSTRAINT peut, bien entendu, également apparaître dans l'instruction CREATE TABLE.
Après avoir créé ces objets de schéma, vous pouvez supprimer une catégorie et obtenir le comportement souhaité en émettant
CALL DeleteCategory(category_ID)
(où category_ID est la catégorie à supprimer), et il se comportera comme vous le souhaitez. Mais n'émettez pas uneDELETE FROM
requête normale , sauf si vous voulez un comportement plus standard (c'est-à-dire supprimer de la table de liaison uniquement et laisser laproducts
table seule).la source
KEY pkey (product_id),
la troisièmeCREATE TABLE
requête dans la réponse acceptée?