N'hésitez pas à mettre des contraintes sur la base de données. Vous serez sûr d'avoir une base de données cohérente, et c'est l'une des bonnes raisons d'utiliser une base de données. Surtout si vous avez plusieurs applications le demandant (ou juste une application mais avec un mode direct et un mode batch utilisant différentes sources).
Avec MySQL, vous n'avez pas de contraintes avancées comme vous le feriez dans postgreSQL mais au moins les contraintes de clé étrangère sont assez avancées.
Prenons un exemple, une table d'entreprise avec une table utilisateur contenant des personnes de cette entreprise
CREATE TABLE COMPANY (
company_id INT NOT NULL,
company_name VARCHAR(50),
PRIMARY KEY (company_id)
) ENGINE=INNODB;
CREATE TABLE USER (
user_id INT,
user_name VARCHAR(50),
company_id INT,
INDEX company_id_idx (company_id),
FOREIGN KEY (company_id) REFERENCES COMPANY (company_id) ON...
) ENGINE=INNODB;
Regardons la clause ON UPDATE :
- ON UPDATE RESTRICT : la valeur par défaut : si vous essayez de mettre à jour un company_id dans la table COMPANY, le moteur rejettera l'opération si au moins un UTILISATEUR établit un lien sur cette société.
- À LA MISE À JOUR PAS D'ACTION : identique à RESTRICT.
- ON UPDATE CASCADE : le meilleur habituellement : si vous mettez à jour un company_id dans une ligne de la table COMPANY, le moteur le mettra à jour en conséquence sur toutes les lignes USER référençant cette COMPANY (mais aucun déclencheur activé sur la table USER, avertissement). Le moteur suivra les changements pour vous, c'est bon.
- ON UPDATE SET NULL : si vous mettez à jour un company_id dans une ligne de la table COMPANY, le moteur définira les USER associés company_id sur NULL (devrait être disponible dans le champ USER company_id). Je ne vois aucune chose intéressante à faire avec cela sur une mise à jour, mais je peux me tromper.
Et maintenant du côté ON DELETE :
- ON DELETE RESTRICT : la valeur par défaut : si vous essayez de supprimer un ID company_id dans la table COMPANY, le moteur rejettera l'opération si un USER au moins établit un lien sur cette société, peut vous sauver la vie.
- SUR SUPPRIMER AUCUNE ACTION : identique à RESTRICT
- ON DELETE CASCADE : dangereux : si vous supprimez une ligne de société dans la table COMPANY, le moteur supprimera également les USER associés. Ceci est dangereux mais peut être utilisé pour effectuer des nettoyages automatiques sur les tables secondaires (donc cela peut être quelque chose que vous voulez, mais certainement pas pour un exemple COMPANY <-> USER)
- ON DELETE SET NULL : handful : si vous supprimez une ligne COMPANY, les USER associés auront automatiquement la relation avec NULL. Si Null est votre valeur pour les utilisateurs sans entreprise, cela peut être un bon comportement, par exemple, vous devez peut-être garder les utilisateurs dans votre application, en tant qu'auteurs de certains contenus, mais la suppression de l'entreprise n'est pas un problème pour vous.
généralement ma valeur par défaut est: ON DELETE RESTRICT ON UPDATE CASCADE . avec certains ON DELETE CASCADE
pour les tables de suivi (journaux - pas tous les journaux -, des choses comme ça) et ON DELETE SET NULL
lorsque la table principale est un `` attribut simple '' pour la table contenant la clé étrangère, comme une table JOB pour la table USER.
Éditer
Cela fait longtemps que je n'ai pas écrit ça. Maintenant, je pense que je devrais ajouter un avertissement important. MySQL a une grosse limitation documentée avec les cascades. Les cascades ne déclenchent pas de déclencheurs . Donc, si vous aviez trop confiance en ce moteur pour utiliser les déclencheurs, vous devriez éviter les contraintes de cascades.
Les déclencheurs MySQL ne s'activent que pour les modifications apportées aux tables par des instructions SQL. Ils ne s'activent pas pour les changements de vues, ni pour les changements apportés aux tables par les API qui ne transmettent pas d'instructions SQL au serveur MySQL
==> Voir ci-dessous la dernière édition, les choses bougent sur ce domaine
Les déclencheurs ne sont pas activés par des actions de clé étrangère.
Et je ne pense pas que cela sera réglé un jour. Les contraintes de clés étrangères sont gérées par le stockage InnoDb et les déclencheurs sont gérés par le moteur SQL MySQL. Les deux sont séparés. Innodb est le seul stockage avec gestion des contraintes, peut-être qu'ils ajouteront des déclencheurs directement dans le moteur de stockage un jour, peut-être pas.
Mais j'ai ma propre opinion sur l'élément que vous devez choisir entre la mauvaise mise en œuvre du déclencheur et le support très utile des contraintes de clés étrangères. Et une fois que vous vous serez habitué à la cohérence de la base de données, vous adorerez PostgreSQL.
12/2017-Mise à jour de cette modification sur MySQL:
comme indiqué par @IstiaqueAhmed dans les commentaires, la situation a changé à ce sujet. Suivez donc le lien et vérifiez la situation actuelle (qui pourrait changer à nouveau à l'avenir).
ON DELETE CASCADE : dangerous
- prenez avec une pincée de sel.SET NULL
dans unON UPDATE
: la mise à jour d'une entreprise représente un détachement de la relation Entreprise> Utilisateur. Par exemple: si une entreprise change de type d'entreprise, les utilisateurs précédents peuvent ne plus être liés à cette entreprise etNULL
peuvent donc être préférables pour cet indice.This includes changes to base tables that underlie updatable views
place de ce que vous avez collé, c'estThey do not activate for changes in views
CASCADE DELETE
est généralement également correcte, même préférée. Je ne le considère pas comme particulièrement dangereux.Ajout à la réponse @MarkR - une chose à noter serait que de nombreux frameworks PHP avec ORM ne reconnaissent pas ou n'utilisent pas la configuration avancée de la base de données (clés étrangères, suppression en cascade, contraintes uniques), et cela peut entraîner un comportement inattendu.
Par exemple, si vous supprimez un enregistrement à l'aide d'ORM et que vous
DELETE CASCADE
supprimerez des enregistrements dans des tables associées, la tentative d'ORM de supprimer ces enregistrements associés (souvent automatique) entraînera une erreur.la source
Vous devrez considérer cela dans le contexte de l'application. En général, vous devez concevoir une application, pas une base de données (la base de données faisant simplement partie de l'application).
Réfléchissez à la manière dont votre application doit répondre à divers cas.
L'action par défaut est de restreindre (c'est-à-dire de ne pas autoriser) l'opération, qui est normalement ce que vous voulez car elle empêche les erreurs de programmation stupides. Cependant, sur DELETE CASCADE peut également être utile. Cela dépend vraiment de votre application et de la façon dont vous avez l'intention de supprimer des objets particuliers.
Personnellement, j'utiliserais InnoDB parce qu'il ne jette pas vos données (cf MyISAM, qui le fait), plutôt que parce qu'il a des contraintes FK.
la source