SQL · Bases de données

Contraintes SQL expliquées : le guide complet pour des données fiables

PRIMARY KEY, FOREIGN KEY, UNIQUE, CHECK, NOT NULL, DEFAULT : maîtrisez toutes les contraintes SQL pour garantir l'intégrité et la qualité de vos données.

Niveau : débutant à intermédiaire | Temps de lecture : 12 min | Publié : avril 2026

1. Une contrainte SQL, c'est quoi ?

Une contrainte SQL est une règle que l'on applique à une colonne ou à une table pour garantir l'intégrité et la qualité des données. Elle empêche l'insertion, la mise à jour ou la suppression de données qui ne respectent pas certaines conditions.

Analogie simple

Imaginez un formulaire administratif : certaines cases sont obligatoires (NOT NULL), certaines doivent être uniques comme le numéro de sécurité sociale (UNIQUE), d'autres doivent respecter un format (CHECK). Les contraintes SQL sont les "règles du formulaire" de votre base de données.

99%
des bases professionnelles utilisent des contraintes
Stack Overflow Survey, 2025
-85%
d'erreurs de données avec contraintes
Étude DBTA, 2026

Vue d'ensemble des 6 contraintes SQL

Schéma des 6 contraintes avec icônes (assisté par Nanao Banana 2)

2. Pourquoi utiliser les contraintes ?

Avantage n°1 : Qualité des données garantie

Les contraintes empêchent les données invalides d'entrer dans la base. C'est une couche de protection au niveau base de données, indépendante de l'application.

Avantage n°2 : Documentation vivante

Les contraintes documentent directement les règles métier dans le schéma. Un développeur qui découvre la base comprend immédiatement : "ce champ est obligatoire", "cette valeur doit être unique", etc.

Avantage n°3 : Performance

Les contraintes (surtout PRIMARY KEY et UNIQUE) créent automatiquement des index, accélérant les recherches.

Avantage n°4 : Centralisation des règles

Plutôt que de vérifier les règles dans chaque application qui accède à la base (API, script, interface admin), une seule définition au bon endroit.

Le principe d'or : Ne faites jamais confiance aux données entrantes. Les contraintes SQL sont votre dernière ligne de défense.

3. NOT NULL : l'obligation de présence

NOT NULL
CREATE TABLE clients (
    id INT PRIMARY KEY,
    nom VARCHAR(100) NOT NULL,     -- Obligatoire
    email VARCHAR(100),            -- Optionnel (peut être NULL)
    age INT                        -- Optionnel
);

-- ✅ VALIDE
INSERT INTO clients (id, nom) VALUES (1, 'Dupont');

-- ❌ ERREUR - nom ne peut pas être NULL
INSERT INTO clients (id) VALUES (2);

Quand l'utiliser : Pour toutes les données essentielles à l'enregistrement : nom, identifiant métier, date de création, etc.

⚠️ Attention : NULL n'est pas une chaîne vide ''. Une chaîne vide est une valeur, NULL est l'absence de valeur. NOT NULL bloque NULL mais autorise '' (sauf contrainte CHECK supplémentaire).

4. UNIQUE : l'interdiction de doublon

UNIQUE
CREATE TABLE clients (
    id INT PRIMARY KEY,
    nom VARCHAR(100),
    email VARCHAR(100) UNIQUE,     -- Email unique dans toute la table
    telephone VARCHAR(20) UNIQUE   -- Téléphone unique aussi
);

-- ✅ VALIDE
INSERT INTO clients (id, nom, email) VALUES (1, 'Dupont', Cette adresse e-mail est protégée contre les robots spammeurs. Vous devez activer le JavaScript pour la visualiser.');

-- ❌ ERREUR - email déjà utilisé
INSERT INTO clients (id, nom, email) VALUES (2, 'Martin', Cette adresse e-mail est protégée contre les robots spammeurs. Vous devez activer le JavaScript pour la visualiser.');

Contrainte UNIQUE composite (plusieurs colonnes)

Composite UNIQUE
CREATE TABLE commandes (
    id INT PRIMARY KEY,
    client_id INT,
    produit_id INT,
    UNIQUE (client_id, produit_id)  -- Un même client ne peut pas commander deux fois le même produit
);

Particularité NULL : La plupart des SGBD autorisent plusieurs NULL sur une colonne UNIQUE (car NULL ≠ NULL). Vérifiez le comportement de votre SGBD.

Schéma contrainte UNIQUE sur email et téléphone

Illustration de la contrainte UNIQUE  (assisté par Nanao Banana 2)

5. PRIMARY KEY : l'identifiant unique

La clé primaire est le mariage de NOT NULL et UNIQUE. Chaque table ne peut avoir qu'une seule PRIMARY KEY.

PRIMARY KEY
-- Syntaxe 1 : sur une colonne
CREATE TABLE clients (
    id INT PRIMARY KEY,            -- Unique, non NULL, indexé
    nom VARCHAR(100)
);

-- Syntaxe 2 : sur plusieurs colonnes (clé composite)
CREATE TABLE lignes_commande (
    commande_id INT,
    produit_id INT,
    quantite INT,
    PRIMARY KEY (commande_id, produit_id)  -- Le couple est unique
);

-- Syntaxe 3 : avec nom explicite
CREATE TABLE clients (
    id INT,
    nom VARCHAR(100),
    CONSTRAINT pk_clients PRIMARY KEY (id)
);
Bonnes pratiques clé primaire :
  • Privilégiez un identifiant technique (auto-incrémenté, UUID) plutôt qu'une donnée métier (qui pourrait changer).
  • Les clés composites sont utiles mais peuvent complexifier les jointures.
  • Toute table devrait avoir une PRIMARY KEY.

6. FOREIGN KEY : le lien entre tables

FOREIGN KEY
CREATE TABLE clients (
    id INT PRIMARY KEY,
    nom VARCHAR(100)
);

CREATE TABLE commandes (
    id INT PRIMARY KEY,
    client_id INT,
    montant DECIMAL(10,2),
    CONSTRAINT fk_commandes_client
        FOREIGN KEY (client_id)
        REFERENCES clients(id)
        ON DELETE RESTRICT
        ON UPDATE CASCADE
);

-- ❌ ERREUR - client_id 999 n'existe pas dans clients
INSERT INTO commandes (id, client_id, montant) VALUES (1, 999, 100.00);
Rappel des options ON DELETE :
  • CASCADE : supprime les enfants automatiquement
  • RESTRICT / NO ACTION : bloque la suppression du parent
  • SET NULL : conserve les enfants sans lien (colonne nullable)
  • SET DEFAULT : affecte une valeur par défaut

Pour approfondir, consultez le guide complet sur la suppression en cascade.

7. CHECK : la validation personnalisée

CHECK
CREATE TABLE clients (
    id INT PRIMARY KEY,
    nom VARCHAR(100),
    age INT CHECK (age >= 18 AND age <= 120),      -- Âge entre 18 et 120 ans
    email VARCHAR(100),
    code_postal VARCHAR(5) CHECK (code_postal ~ '^[0-9]{5}$'),  -- Format 5 chiffres
    date_creation DATE DEFAULT CURRENT_DATE,
    CONSTRAINT chk_email CHECK (email LIKE '%@%')   -- Email doit contenir @
);

-- ✅ VALIDE
INSERT INTO clients (id, nom, age, email) VALUES (1, 'Dupont', 35, Cette adresse e-mail est protégée contre les robots spammeurs. Vous devez activer le JavaScript pour la visualiser.');

-- ❌ ERREUR - age 15 (< 18)
INSERT INTO clients (id, nom, age) VALUES (2, 'Martin', 15);

-- ❌ ERREUR - email sans @
INSERT INTO clients (id, nom, email) VALUES (3, 'Durand', 'pasunemail');
⚠️ Limitation MySQL : MySQL accepte la syntaxe CHECK mais ne l'applique pas (jusqu'à MySQL 8.0.16). Depuis MySQL 8.0.16, CHECK est bien appliqué. PostgreSQL et SQL Server le supportent pleinement.

8. DEFAULT : la valeur par défaut

DEFAULT
CREATE TABLE clients (
    id INT PRIMARY KEY,
    nom VARCHAR(100),
    statut VARCHAR(20) DEFAULT 'actif',           -- Par défaut 'actif'
    date_inscription DATE DEFAULT CURRENT_DATE,   -- Date du jour
    actif BOOLEAN DEFAULT TRUE,
    points INT DEFAULT 0
);

-- ✅ VALIDE - statut sera 'actif', date_inscription aujourd'hui
INSERT INTO clients (id, nom) VALUES (1, 'Dupont');

-- ✅ On peut aussi surcharger
INSERT INTO clients (id, nom, statut) VALUES (2, 'Martin', 'suspendu');

Fonctions usuelles pour DEFAULT :

  • CURRENT_DATE / NOW() : date/heure courante
  • CURRENT_USER : utilisateur courant (PostgreSQL)
  • UUID() / GEN_RANDOM_UUID() : identifiant unique
  • 0, 1, 'actif', TRUE : valeurs statiques

Schéma contrainte DEFAULT avec valeurs par défaut

Illustration de DEFAULT sur plusieurs colonnes (assisté par Nanao Banana 2)

9. Comparatif des 6 contraintes

Contrainte Empêche Garantit Index automatique
NOT NULL NULL Colonne toujours remplie Non
UNIQUE Doublons Valeurs toutes différentes Oui
PRIMARY KEY NULL + doublons Identifiant unique et obligatoire Oui
FOREIGN KEY Orphelins Lien valide entre tables Variable (recommandé manuellement)
CHECK Données hors condition Règle métier personnalisée Non
DEFAULT (N'interdit rien, fournit une valeur) Valeur par défaut si non spécifiée Non

10. Bonnes pratiques pour les contraintes

1. Nommez toujours vos contraintes

CONSTRAINT pk_clients PRIMARY KEY (id) plutôt que laisser un nom auto-généré. Facilite la maintenance et les modifications futures.

2. Une seule PRIMARY KEY par table

Une table ne peut avoir qu'une seule clé primaire. Pour plusieurs identifiants uniques, utilisez UNIQUE.

3. FOREIGN KEY = toujours nommée

Les FK sont les contraintes qu'on modifie le plus souvent. Un nom explicite (fk_commandes_clients) est indispensable.

4. Documentez les CHECK complexes

Les conditions CHECK peuvent devenir complexes. Ajoutez un commentaire SQL ou documentez dans le schéma.

5. Testez les contraintes en développement

Avant la mise en production, testez systématiquement que les contraintes rejettent bien les données invalides.

Convention de nommage recommandée :
  • pk_[table] pour PRIMARY KEY
  • fk_[table_enfant]_[table_parent] pour FOREIGN KEY
  • uk_[table]_[colonne(s)] pour UNIQUE
  • chk_[table]_[condition] pour CHECK

11. Erreurs fréquentes et solutions

Erreur 1 : NULL dans une colonne NOT NULL

ERROR: null value in column "nom" violates not-null constraint

Solution : Fournissez une valeur pour la colonne obligatoire ou ajoutez une valeur par défaut avec DEFAULT.

Erreur 2 : Doublon sur colonne UNIQUE

ERROR: duplicate key value violates unique constraint

Solution : Vérifiez avant insertion, ou utilisez ON CONFLICT (PostgreSQL) / INSERT IGNORE (MySQL).

Erreur 3 : Foreign key constraint fails

ERROR: insert or update on table "commandes" violates foreign key constraint

Solution : Insérez d'abord le parent, ou désactivez temporairement (déconseillé en production).

Erreur 4 : CHECK constraint violation

ERROR: new row for relation "clients" violates check constraint "chk_clients_age"

Solution : Vérifiez que la valeur respecte la condition, ou ajustez la contrainte.

Astuce : Pour déboguer, utilisez SHOW CREATE TABLE nom_table (MySQL) ou \d nom_table (PostgreSQL) pour voir toutes les contraintes existantes.

12. FAQ — Contraintes SQL

Peut-on ajouter une contrainte après la création de la table ?

Oui, avec ALTER TABLE. Exemple : ALTER TABLE clients ADD CONSTRAINT chk_age CHECK (age >= 18); Attention : si des données existantes violent la contrainte, l'opération échouera. Nettoyez d'abord les données invalides.

Une colonne peut-elle avoir plusieurs contraintes ?

Oui, bien sûr. Exemple : email VARCHAR(100) NOT NULL UNIQUE → obligatoire ET unique. On peut aussi cumuler NOT NULL, UNIQUE, CHECK, DEFAULT sur la même colonne.

Quelle est la différence entre UNIQUE et PRIMARY KEY ?

Une table ne peut avoir qu'une seule PRIMARY KEY, mais plusieurs contraintes UNIQUE. PRIMARY KEY interdit NULL, UNIQUE l'autorise (généralement). PRIMARY KEY est automatiquement indexée ; UNIQUE aussi mais l'index peut être non-cluster selon SGBD.

Les contraintes ralentissent-elles les insertions ?

Oui, légèrement. Chaque insertion vérifie les contraintes (recherche d'unicité, vérification CHECK, existence du parent pour FK). Le coût est généralement acceptable par rapport au bénéfice (données propres). Pour des imports massifs, on peut désactiver temporairement les contraintes, puis les réactiver.

Comment lister toutes les contraintes d'une table ?

MySQL : SHOW CREATE TABLE nom_table; ou SELECT * FROM information_schema.TABLE_CONSTRAINTS WHERE TABLE_NAME = 'nom_table';
PostgreSQL : \d nom_table ou SELECT * FROM information_schema.table_constraints WHERE table_name = 'nom_table';
SQL Server : sp_help 'nom_table';

Existe-t-il d'autres contraintes moins connues ?

Oui : EXCLUDE (PostgreSQL) pour des exclusions complexes, FOREIGN KEY avec MATCH FULL/PARTIAL/SIMPLE, DEFERRABLE pour différer les vérifications. Mais les 6 présentées couvrent 99% des besoins.

13. Conclusion

Les contraintes SQL sont les gardiennes de votre base de données. Elles garantissent que seules des données valides, cohérentes et complètes y entrent. Une base bien contrainte est une base fiable.

Récapitulatif des 6 contraintes

  • NOT NULL : champ obligatoire
  • UNIQUE : pas de doublon
  • PRIMARY KEY : identifiant unique et obligatoire
  • FOREIGN KEY : lien valide entre tables
  • CHECK : règle métier personnalisée
  • DEFAULT : valeur par défaut
Règle d'or finale : Ne laissez jamais votre application (ou vos utilisateurs) décider de l'intégrité des données. Les contraintes SQL sont votre meilleure assurance qualité.
 

Recevez la veille IA & Data qui compte vraiment

 

    Analyses claires, outils concrets et tendances IA sans bruit.     Rejoignez les lecteurs de IANA Data.