Les contraintes d'intégrité : domaine, entité, référence
Une base de données sans garde-fous devient vite incohérente : commandes sans client, doublons d'identifiants, âges négatifs. Les contraintes d'intégrité - domaine, entité, référence - sont les trois règles qui protègent la cohérence d'une base de données relationnelle. Au programme de l'UE 8 du DCG, elles sont régulièrement testées, notamment à travers la vérification d'un schéma relationnel.
Pourquoi des contraintes d'intégrité ?
Le modèle relationnel, formalisé par Edgar F. Codd en 1970, ne se limite pas à organiser les données en tables : il repose sur des contraintes, c'est-à-dire des règles que toute base doit respecter pour rester cohérente. Sans elles, une modification d'adresse peut être faite dans un enregistrement et oubliée dans un autre, une suppression peut entraîner la perte involontaire d'informations, une insertion peut créer des données « orphelines » que rien ne rattache au reste de la base.
Trois contraintes structurent le modèle : la contrainte de domaine, la contrainte d'entité et la contrainte d'intégrité référentielle.
La contrainte de domaine : des valeurs autorisées
Chaque attribut d'une table doit appartenir à un domaine de valeurs défini. Le domaine spécifie le type de données autorisé (texte, entier, date, décimal...) et éventuellement les valeurs acceptées.
Exemples concrets : un champ « Âge » doit être un entier positif ; un champ « Email » doit contenir un « @ » ; un champ « Sexe » doit valoir « M » ou « F ». En SQL, cette contrainte se traduit par le choix du type de chaque colonne (INT, VARCHAR, DATE...) et, le cas échéant, par des restrictions complémentaires.
La contrainte d'entité : l'unicité de la clé primaire
Chaque table doit avoir une clé primaire qui identifie de façon unique chaque enregistrement. Deux règles en découlent : la clé primaire ne peut pas être nulle (NULL), et chaque valeur de la clé est unique dans la table - jamais de doublons.
Cette contrainte garantit qu'on peut toujours désigner une ligne sans ambiguïté. Une table CLIENT où deux clients partageraient le même NumClient rendrait toute requête, toute facture, toute commande suspecte.
La contrainte d'intégrité référentielle : pas de données orphelines
Toute valeur d'une clé étrangère (FK) doit correspondre à une valeur existante de la clé primaire référencée dans l'autre table, ou être nulle si l'association est optionnelle.
Exemple : dans la table COMMANDE, la clé étrangère #NumClient doit correspondre à un NumClient qui existe effectivement dans la table CLIENT. Sinon, on aurait une commande « orpheline » sans client identifié.
Cette contrainte a trois conséquences pratiques, très souvent interrogées à l'examen :
- On ne peut pas insérer un enregistrement avec une clé étrangère qui ne référence rien.
- On ne peut pas supprimer un enregistrement si d'autres enregistrements le référencent (sauf avec l'option CASCADE).
- On ne peut pas modifier une clé primaire si elle est référencée ailleurs (sauf avec CASCADE).
L'option CASCADE mérite un mot : avec DELETE CASCADE, la suppression d'un enregistrement entraîne automatiquement la suppression de tous les enregistrements qui le référencent. C'est dangereux, mais parfois souhaité - par exemple la suppression en cascade des lignes d'un panier d'achat quand on supprime le panier.
Un exemple concret : services et employés
Prenons un schéma minimal de gestion du personnel :
- DEPARTEMENT(CodeDept, NomDept)
- EMPLOYE(NumEmp, Nom, #CodeDept)
Trois situations illustrent l'intégrité référentielle. Peut-on insérer un employé avec #CodeDept = « D99 » si D99 n'existe pas dans DEPARTEMENT ? Non : l'intégrité référentielle interdit d'insérer une clé étrangère sans clé primaire correspondante. Peut-on supprimer le département « D01 » s'il a des employés ? Non par défaut : la suppression est bloquée car des employés référencent D01. Que se passe-t-il avec CASCADE ? La suppression de D01 entraîne automatiquement celle de tous les employés du département - une option à manier avec une extrême prudence.
Côté contrainte d'entité : chaque employé doit avoir un NumEmp unique et non nul. Côté contrainte de domaine : NumEmp est un entier, Nom une chaîne de caractères de longueur bornée.
Les erreurs fréquentes
- Confondre contrainte d'entité et contrainte de domaine : la première porte sur la clé primaire (unicité, non-nullité), la seconde sur les valeurs autorisées de chaque attribut (type, plage).
- Croire qu'une clé étrangère peut pointer vers une valeur inexistante : c'est précisément ce que l'intégrité référentielle interdit - la seule exception est la valeur NULL quand l'association est optionnelle.
- Oublier que la contrainte référentielle bloque aussi les suppressions et les modifications, pas seulement les insertions : les trois opérations sont concernées.
- Confondre NULL et chaîne vide : NULL signifie « valeur inconnue ou non applicable » ; une chaîne vide est une valeur à part entière. La clé primaire refuse NULL ; une clé étrangère optionnelle peut l'accepter.
FAQ
Quelle est la différence entre les trois contraintes d'intégrité ?
La contrainte de domaine contrôle le type et la plage de valeurs de chaque attribut. La contrainte d'entité garantit l'unicité et la non-nullité de la clé primaire. La contrainte référentielle garantit que toute clé étrangère pointe vers une clé primaire existante. Domaine = les valeurs, entité = l'identification, référence = les liens.
Une clé étrangère peut-elle être NULL ?
Oui, si l'association est optionnelle : un employé temporairement sans département peut avoir #CodeDept à NULL. En revanche, si la règle de gestion impose un rattachement (cardinalité 1,1), la clé étrangère doit être déclarée NOT NULL.
Quel lien entre contraintes d'intégrité et normalisation ?
Les contraintes garantissent la cohérence des données au quotidien ; la normalisation garantit la bonne structure des tables (absence de redondances et d'anomalies). Les deux se complètent : un schéma normalisé avec des contraintes bien déclarées est la définition même d'une base fiable.
Entraînez-vous
Soit le schéma : SERVICE(CodeService, NomService) et SALARIE(NumSalarie, Nom, Salaire, #CodeService). Répondez par vrai ou faux en justifiant.
- L'insertion du salarié (501, « Diallo », 2400, « S07 ») est acceptée alors que S07 n'existe pas dans SERVICE.
- La table SALARIE peut contenir deux lignes avec NumSalarie = 501 si les noms sont différents.
- La suppression du service « S01 », référencé par douze salariés, est possible par défaut ; avec DELETE CASCADE, elle supprimerait aussi les douze salariés.
Afficher le corrigé
1. Faux. La contrainte d'intégrité référentielle interdit d'insérer une clé étrangère sans clé primaire correspondante dans la table référencée : S07 doit exister dans SERVICE avant l'insertion. Seule alternative : insérer le salarié avec #CodeService à NULL, si l'association est optionnelle.
2. Faux. La contrainte d'entité impose l'unicité de la clé primaire : deux lignes ne peuvent jamais partager le même NumSalarie, quels que soient les autres attributs. La clé primaire ne peut pas non plus être NULL.
3. Faux puis vrai. Par défaut, la suppression de S01 est bloquée par l'intégrité référentielle, car douze salariés le référencent : on évite ainsi des salariés « orphelins » rattachés à un service inexistant. Avec l'option DELETE CASCADE, la suppression de S01 entraînerait automatiquement la suppression des douze salariés - comportement parfois voulu, mais dangereux : à justifier explicitement dans une copie.