Exercices de consolidation SQL – Contraintes, Types et Requêtes
Exercice 1 — Colonnes auto-générées et contraintes de base
Objectif
Savoir créer des tables avec des identifiants auto-générés et des contraintes garantissant la cohérence des données.
Crée trois tables utilisant différentes méthodes d’auto-incrémentation :
CREATE TABLE test_serial ( id SERIAL PRIMARY KEY, libelle TEXT ); CREATE TABLE test_identity_always ( id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY, libelle TEXT ); CREATE TABLE test_identity_default ( id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, libelle TEXT );Insère quelques lignes dans chaque table et observe les valeurs générées. Que se passe-t-il si on force une valeur pour
iddans les deux tables utilisantIDENTITY? Explique la différence entre ALWAYS et BY DEFAULT.Supprime les tables, puis recrée une table unique
employeavec les colonnes suivantes :idauto-généréprenometnomobligatoiressalairepositif et inférieur à 10 000- une contrainte nommée
ck_employe_salaire
Ajoute ensuite une colonne
poste TEXTqui peut être nulle, et impose qu’un salarié ne puisse pas avoir deux fois le même couple(nom, prenom).
Exercice 2 — Types de données et validation
Objectif
Choisir les types adaptés et poser les contraintes de validation adéquates.
Crée une table
produitavec les colonnes suivantes :idauto-généré,nomobligatoire (TEXTouVARCHAR),prixde typeNUMERIC(10,2)et contrainteCHECK (prix BETWEEN 0 AND 10000),stockentier non négatif.
Insère plusieurs produits valides puis un produit invalide (prix négatif, stock nul, etc.). Que se passe-t-il ? Observe le message d’erreur généré par PostgreSQL.
Renomme la contrainte
CHECKexistante avec un nom explicite (ck_produit_prix) et ajoute une contrainteUNIQUEsur le nom du produit.Explique la différence entre
NUMERIC(10,2)etREALdans ce contexte. Pourquoi l’un est-il préférable à l’autre ?
Exercice 3 — Contraintes de référence et politiques d’effacement
Objectif
Relier des tables entre elles et comprendre les stratégies ON DELETE.
Crée une table
client:CREATE TABLE client ( id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY, nom TEXT NOT NULL );Crée une table
commandeliée àclient:CREATE TABLE commande ( id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY, id_client BIGINT REFERENCES client(id) ON DELETE CASCADE, date_commande DATE NOT NULL );Insère quelques clients et commandes associées. Supprime un client, puis observe l’effet sur ses commandes.
Recrée la table avec
ON DELETE RESTRICTet compare les comportements.Explique dans quels cas on privilégierait l’une ou l’autre politique.
Exercice 4 — Jointures : combiner les données
Objectif
Comprendre les différences entre les types de jointures et savoir les illustrer.
Crée deux tables simples :
CREATE TABLE a (id INT, val TEXT); CREATE TABLE b (id INT, val TEXT); INSERT INTO a VALUES (1,'a1'), (2,'a2'), (3,'a3'); INSERT INTO b VALUES (2,'b2'), (3,'b3'), (4,'b4');Exécute et analyse :
SELECT * FROM a INNER JOIN b USING(id); SELECT * FROM a LEFT JOIN b USING(id); SELECT * FROM a RIGHT JOIN b USING(id); SELECT * FROM a FULL JOIN b USING(id);Dessine les ensembles correspondants ou décris en mots les lignes présentes dans chaque résultat.
Reformule la requête
LEFT JOINci-dessus sous forme équivalente utilisantNOT EXISTSouIS NULL.Décris un cas concret (dans un schéma client/commande par exemple) où un
FULL JOINest utile.
Exercice 5 — Agrégats et sous-requêtes
Objectif
Utiliser GROUP BY, HAVING, et des sous-requêtes pour extraire des informations synthétiques.
Reprends la table
produitet ajoute une tablecategorie:CREATE TABLE categorie ( id SERIAL PRIMARY KEY, nom TEXT ); ALTER TABLE produit ADD COLUMN id_categorie INT REFERENCES categorie(id);Insère plusieurs catégories et produits.
Calcule par catégorie :
- le nombre de produits,
- le prix moyen,
- le prix maximum et minimum.
Affiche uniquement les catégories dont le prix moyen est supérieur à 100.
Rédige une requête qui retourne les produits plus chers que la moyenne globale de tous les produits.
Exercice 6 — Contraintes avancées et validation différée
Objectif
Explorer des contraintes plus complexes et leur validation.
Crée une table
reservation:CREATE TABLE reservation ( id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY, id_client INT, debut DATE, fin DATE );Ajoute une contrainte
CHECK (fin >= debut)et teste des cas valides / invalides.Supprime la contrainte et recrée-la avec
NOT VALID, puis valide-la ensuite avec :ALTER TABLE reservation VALIDATE CONSTRAINT ck_reservation_dates;Explique l’intérêt du mot-clé
NOT VALIDdans une base en production.
Exercice 7 — Agrégation et sous-requêtes corrélées
Objectif
Aller plus loin dans la compréhension des requêtes imbriquées et des comparaisons par groupe.
Reprends les tables
clientetcommande. Ajoute une colonnemontant NUMERIC(10,2)danscommande.Calcule pour chaque client le montant total dépensé (
SUM(montant)).Trouve le client ayant dépensé le plus.
Même question, mais sans utiliser
MAX(): avec une sous-requête corrélée.
Exercice 8 — Clés et contraintes d’unicité
Objectif
Différencier PRIMARY KEY, UNIQUE, et FOREIGN KEY.
Crée une table
departement:CREATE TABLE departement ( code TEXT PRIMARY KEY, nom TEXT UNIQUE );Crée une table
employeavec une clé étrangère versdepartement(code).Explique les différences entre :
PRIMARY KEYUNIQUEFOREIGN KEYet donne un exemple où chacune est pertinente.