Contraintes d'intégrité

Objectifs et prérequis

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 KEY et CHECK pour 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 :

  1. Insertion avec référence inexistante : on ne peut pas insérer un emprunt qui référence un livre inexistant.
  2. 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).
  3. 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é SQLType de contrainteEffet
NOT NULLDomaineInterdit les valeurs vides
CHECK (condition)DomaineRestreint les valeurs acceptables
UNIQUERelationInterdit les doublons sur un attribut
PRIMARY KEYRelationUnicité + non-nullité (identifiant de la table)
FOREIGN KEY ... REFERENCESRéférenceImpose 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_produitnomprix
1Cahier2.50
2Stylo1.20

Pour chaque opération, indiquez si le SGBD l’accepte ou la refuse, et justifiez :

  1. INSERT INTO Produits VALUES (3, 'Gomme', 0.80);

    RéponseAcceptée. L'id_produit 3 n'existe pas encore (clé primaire respectée), le prix 0.80 est positif (CHECK respecté).
  2. INSERT INTO Produits VALUES (1, 'Colle', 1.50);

    RéponseRefusée. L'id_produit 1 existe déjà dans la table (violation de la contrainte de clé primaire).
  3. INSERT INTO Produits VALUES (4, 'Règle', -2.00);

    RéponseRefusée. Le prix est négatif, ce qui viole la contrainte CHECK (prix > 0) (contrainte de domaine).
  4. INSERT INTO Commandes VALUES (1, 5, 3);

    RéponseRefusée. L'id_produit 5 n'existe pas dans la table Produits (violation de la contrainte de clé étrangère).
  5. DELETE FROM Produits WHERE id_produit = 2; (sachant qu’aucune commande ne référence le produit 2)

    RéponseAccepté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
  1. On tente d’insérer un enregistrement dans la table Commandes avec un id_produit qui n’existe pas dans la table Produits. Que se passe-t-il ?
    RéponseLe 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.
  2. Quelle contrainte SQL empêche d’avoir deux employés avec le même numéro d’identifiant ?
    RéponseC'est la contrainte PRIMARY KEY (qui combine UNIQUE et NOT NULL). Si on tente d'insérer un enregistrement avec un identifiant déjà existant, le SGBD refuse l'opération.
  3. On souhaite que l’âge d’un employé soit toujours compris entre 16 et 70 ans. Quelle contrainte utiliser ?
    RéponseOn utilise CHECK (age >= 16 AND age <= 70). C'est une contrainte de domaine qui restreint les valeurs acceptables pour cet attribut.
L'essentiel à retenir
  • 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.