Prérequis : le modèle relationnel (clé primaire, clé étrangère, schéma relationnel)
À l’issue de ce chapitre, vous saurez :
- expliquer le rôle des contraintes d’intégrité dans une base de données ;
- distinguer les trois types de contraintes : domaine, relation (clé primaire) et référence (clé étrangère) ;
- utiliser les mots-clés SQL
NOT NULL,UNIQUE,PRIMARY KEY,FOREIGN KEYetCHECKpour implémenter ces contraintes ; - prévoir le comportement du SGBD face à une insertion ou une modification qui viole une contrainte.
Pourquoi des contraintes ?
Un schéma relationnel définit la structure d’une base de données, mais il ne suffit pas à garantir la cohérence des données. Sans règles supplémentaires, rien n’empêcherait d’insérer un âge négatif, un identifiant en double ou une référence vers un enregistrement inexistant.
Les contraintes d’intégrité sont des règles que le SGBD vérifie automatiquement lors de chaque insertion, modification ou suppression. Si une opération viole une contrainte, le SGBD la refuse et les données restent intactes.
Les trois types de contraintes
Contrainte de domaine
Chaque attribut possède un domaine : le type de données qu’il peut contenir. Le SGBD refuse toute valeur qui ne respecte pas ce type.
Exemple. Si l’attribut age est déclaré de type INT, le SGBD refuse l’insertion de la chaîne 'vingt-cinq'.
On peut restreindre davantage un domaine avec le mot-clé CHECK. Par exemple, pour imposer que l’âge soit compris entre 0 et 150 :
CREATE TABLE Personnes (
id INTEGER PRIMARY KEY,
nom TEXT NOT NULL,
age INT CHECK (age >= 0 AND age <= 150)
);
Le mot-clé NOT NULL interdit les valeurs vides : chaque enregistrement devra avoir un nom.
Contrainte de relation (clé primaire)
Chaque enregistrement d’une table doit pouvoir être identifié de manière unique et non nulle par sa clé primaire. Cette contrainte combine deux propriétés :
- Unicité : deux lignes ne peuvent pas avoir la même valeur de clé primaire.
- Non-nullité : la clé primaire ne peut jamais être vide.
Exemple. Si la table Clients a pour clé primaire Id_client, alors l’insertion d’un second client avec le même Id_client est refusée par le SGBD.
En SQL, on déclare la clé primaire avec PRIMARY KEY :
CREATE TABLE Clients (
Id_client INTEGER PRIMARY KEY,
Nom TEXT NOT NULL,
Prenom TEXT,
Adresse TEXT
);
Le mot-clé UNIQUE peut être utilisé sur d’autres attributs pour imposer l’unicité sans en faire la clé primaire (par exemple, un numéro de sécurité sociale).
Contrainte de référence (clé étrangère)
Une clé étrangère doit toujours référencer une valeur existante dans la table cible. Cette contrainte protège contre les « liens morts ».
Concrètement, trois situations sont interdites :
- Insertion avec référence inexistante : on ne peut pas insérer un emprunt qui référence un livre inexistant.
- Suppression de la cible : on ne peut pas supprimer un client s’il est encore référencé dans une autre table (par exemple, des commandes en cours).
- Modification de la clé référencée : on ne peut pas modifier l’identifiant d’un client s’il est utilisé comme clé étrangère ailleurs.
Exemple. Soit le schéma suivant :
- Eleves(id_eleve, nom, prenom, #id_classe)
- Classes(id_classe, nom_classe, salle)
On tente d’inscrire un élève dans la classe 999, qui n’existe pas :
INSERT INTO Eleves (id_eleve, nom, prenom, id_classe)
VALUES (1, 'Martin', 'Lucas', 999);
Le SGBD refuse cette insertion car id_classe = 999 ne correspond à aucune ligne de la table Classes. C’est la contrainte d’intégrité référentielle. (Avec SQLite, cette vérification n’est active qu’après la commande PRAGMA foreign_keys = ON;.)
En SQL, on déclare la clé étrangère ainsi :
CREATE TABLE Eleves (
id_eleve INTEGER PRIMARY KEY,
nom TEXT NOT NULL,
prenom TEXT,
id_classe INT,
FOREIGN KEY (id_classe) REFERENCES Classes(id_classe)
);
Récapitulatif des mots-clés SQL
| Mot-clé SQL | Type de contrainte | Effet |
|---|---|---|
NOT NULL | Domaine | Interdit les valeurs vides |
CHECK (condition) | Domaine | Restreint les valeurs acceptables |
UNIQUE | Relation | Interdit les doublons sur un attribut |
PRIMARY KEY | Relation | Unicité + non-nullité (identifiant de la table) |
FOREIGN KEY ... REFERENCES | Référence | Impose que la valeur existe dans la table cible |
Activité : cette insertion est-elle acceptée ?
On considère le schéma suivant :
- Produits(id_produit, nom, prix) avec
CHECK (prix > 0) - Commandes(id_commande, #id_produit, quantite)
Données existantes :
| id_produit | nom | prix |
|---|---|---|
| 1 | Cahier | 2.50 |
| 2 | Stylo | 1.20 |
Pour chaque opération, indiquez si le SGBD l’accepte ou la refuse, et justifiez :
INSERT INTO Produits VALUES (3, 'Gomme', 0.80);Réponse
Acceptée. L'id_produit 3 n'existe pas encore (clé primaire respectée), le prix 0.80 est positif (CHECK respecté).INSERT INTO Produits VALUES (1, 'Colle', 1.50);Réponse
Refusée. L'id_produit 1 existe déjà dans la table (violation de la contrainte de clé primaire).INSERT INTO Produits VALUES (4, 'Règle', -2.00);Réponse
Refusée. Le prix est négatif, ce qui viole la contrainteCHECK (prix > 0)(contrainte de domaine).INSERT INTO Commandes VALUES (1, 5, 3);Réponse
Refusée. L'id_produit 5 n'existe pas dans la table Produits (violation de la contrainte de clé étrangère).DELETE FROM Produits WHERE id_produit = 2;(sachant qu’aucune commande ne référence le produit 2)Réponse
Acceptée. Le produit 2 n'est référencé par aucune commande, donc la suppression ne viole pas la contrainte de référence.
Vérifiez votre compréhension
- On tente d’insérer un enregistrement dans la table Commandes avec un
id_produitqui n’existe pas dans la table Produits. Que se passe-t-il ?Réponse
Le SGBD rejette l'insertion car la contrainte de clé étrangère (FOREIGN KEY) exige que la valeur référencée existe dans la table Produits. C'est la contrainte de référence qui protège contre les liens morts. - Quelle contrainte SQL empêche d’avoir deux employés avec le même numéro d’identifiant ?
Réponse
C'est la contraintePRIMARY KEY(qui combineUNIQUEetNOT NULL). Si on tente d'insérer un enregistrement avec un identifiant déjà existant, le SGBD refuse l'opération. - On souhaite que l’âge d’un employé soit toujours compris entre 16 et 70 ans. Quelle contrainte utiliser ?
Réponse
On utiliseCHECK (age >= 16 AND age <= 70). C'est une contrainte de domaine qui restreint les valeurs acceptables pour cet attribut.
- Les contraintes d’intégrité sont des règles vérifiées automatiquement par le SGBD pour garantir la cohérence des données.
- La contrainte de domaine (
NOT NULL,CHECK) restreint les valeurs acceptables pour un attribut. - La contrainte de relation (
PRIMARY KEY,UNIQUE) garantit l’unicité des enregistrements. - La contrainte de référence (
FOREIGN KEY ... REFERENCES) impose que chaque clé étrangère pointe vers une valeur existante dans la table cible. - Toute opération (insertion, modification, suppression) qui viole une contrainte est refusée par le SGBD.