Contraintes : NOT NULL, UNIQUE, CHECK, EXCLUDE
IntermédiairePlus une règle est près des données, moins elle peut être contournée : une contrainte protège contre tous les clients de la base, pas seulement votre application.
CREATE TABLE produits (
id bigint GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
sku text NOT NULL UNIQUE,
prix numeric(12, 2) NOT NULL CHECK (prix >= 0),
stock integer NOT NULL DEFAULT 0 CHECK (stock >= 0),
statut text NOT NULL CHECK (statut IN ('brouillon', 'publie', 'archive'))
);
Unicité partielle et sur plusieurs colonnes#
-- Un seul compte actif par email (les comptes supprimés sont ignorés)
CREATE UNIQUE INDEX comptes_email_actif_idx ON comptes (email) WHERE supprime_le IS NULL;
-- Unicité d'un couple
ALTER TABLE inscriptions ADD CONSTRAINT inscription_unique UNIQUE (utilisateur_id, cours_id);
EXCLUDE : empêcher les chevauchements#
CREATE EXTENSION IF NOT EXISTS btree_gist;
CREATE TABLE reservations (
salle_id int NOT NULL,
periode tstzrange NOT NULL,
EXCLUDE USING gist (salle_id WITH =, periode WITH &&) -- même salle : pas de périodes qui se chevauchent
);
Cas pratique : une contrainte
EXCLUDEsur une plage de temps interdit les doubles réservations sans verrou applicatif ni condition de course : deux transactions concurrentes qui tentent de réserver la même salle sur des périodes qui se chevauchent verront l'une des deux échouer.