Table profils / classes
Création de la table de relation entre utilisateurs et classes
Notions théoriques
Comprendre les relations many-to-many
Dans une base de données relationnelle, une relation many-to-many (n:m) signifie qu’un enregistrement dans une table peut être lié à plusieurs enregistrements dans une autre table, et inversement.
Dans notre projet, un utilisateur peut appartenir à plusieurs classes, et une classe peut contenir plusieurs utilisateurs.
Un SGBDR comme PostgreSQL (et Supabase) ne permet pas de créer une relation many-to-many directement entre deux tables. Il faut créer une table intermédiaire appelée table de jointure.
La table de jointure class_members
Cette table permet de relier les utilisateurs (auth.users) aux classes (public.classes). Elle contient :
Colonne | Type | Description |
---|---|---|
id | uuid | Identifiant unique de la relation |
class_id | uuid | Référence à la classe (clé étrangère) |
user_id | uuid | Référence à l’utilisateur (clé étrangère) |
joined_at | timestamp with time zone | Date d’inscription à la classe |
Clés étrangères et ON DELETE CASCADE
Les colonnes class_id
et user_id
sont des clés étrangères. Elles permettent de garantir que les valeurs insérées existent bien dans les tables référencées.
class_id uuid REFERENCES public.classes(id) ON DELETE CASCADE
user_id uuid REFERENCES auth.users(id) ON DELETE CASCADE
La clause ON DELETE CASCADE
signifie que si une classe ou un utilisateur est supprimé, tous les enregistrements associés dans class_members
seront aussi supprimés automatiquement.
Il est important d’utiliser CASCADE
uniquement si la suppression automatique est bien souhaitée. Cela peut entraîner la perte de données si mal utilisé.
Contrainte UNIQUE sur deux colonnes
Il faut éviter qu’un même utilisateur soit inscrit deux fois à la même classe. Pour cela, on ajoute une contrainte :
UNIQUE(class_id, user_id)
Cette contrainte empêche l’insertion de doublons pour un même couple (classe, utilisateur).
Valeurs par défaut
Comme dans les autres tables :
id
est généré automatiquement avecuuid_generate_v4()
joined_at
est rempli automatiquement avec l’heure actuelle (en UTC)
id uuid default uuid_generate_v4()
joined_at timestamp with time zone default timezone('utc'::text, now())
Résumé de la structure
Voici le script complet pour créer la table :
create table public.class_members (
id uuid default uuid_generate_v4() primary key,
class_id uuid references public.classes(id) on delete cascade not null,
user_id uuid references auth.users(id) on delete cascade not null,
joined_at timestamp with time zone default timezone('utc'::text, now()) not null,
unique(class_id, user_id)
);
Bonne pratique cyber
- Validation des références : toujours s’assurer que les UUID utilisés existent réellement dans les tables
classes
etauth.users
. - Usage prudent de CASCADE : ne jamais utiliser
ON DELETE CASCADE
sans comprendre ses conséquences. - Auditabilité : le champ
joined_at
permet de tracer l’historique des inscriptions.
Exemple pratique
Créer la table class_members
dans Supabase
Il est possible de créer la table via le SQL Editor de Supabase avec le script suivant :
create table public.class_members (
id uuid default uuid_generate_v4() primary key,
class_id uuid references public.classes(id) on delete cascade not null,
user_id uuid references auth.users(id) on delete cascade not null,
joined_at timestamp with time zone default timezone('utc'::text, now()) not null,
unique(class_id, user_id)
);
Ce script :
- crée une clé primaire sur
id
, - ajoute deux clés étrangères avec suppression en cascade,
- empêche les doublons (même utilisateur dans la même classe),
- ajoute un champ
joined_at
renseigné automatiquement.
Insérer un membre dans une classe
Il est possible d’ajouter un utilisateur existant à une classe existante avec la requête suivante :
insert into public.class_members (class_id, user_id)
values ('<UUID_de_la_classe>', '<UUID_de_l_utilisateur>');
Il faut remplacer les deux UUID par des identifiants valides présents dans les tables classes
et auth.users
.
Vérifier les inscriptions
Aller dans Table Editor > class_members
pour vérifier que :
- Une ligne a bien été insérée,
joined_at
est rempli automatiquement,id
est un UUID généré automatiquement.
Tester la contrainte UNIQUE
Si on essaie d’insérer deux fois le même couple class_id
/ user_id
, une erreur SQL est levée :
insert into public.class_members (class_id, user_id)
values ('<UUID>', '<UUID>'); -- même couple qu'avant
Erreur attendue : duplicate key value violates unique constraint
.
Supprimer une classe et observer les effets
Si on supprime une classe :
delete from public.classes where id = '<UUID>';
Alors toutes les lignes associées dans class_members
sont automatiquement supprimées.
Test de mémorisation/compréhension
TP pour réfléchir et résoudre des problèmes
Objectif du TP
Mettre en place la table de relation class_members
entre les utilisateurs et les classes,
en respectant les bonnes pratiques de modélisation relationnelle et de cybersécurité.
Étape 1 — Créer la table class_members
via l’éditeur SQL de Supabase
- Se connecter à https://supabase.com et accéder à son projet.
- Ouvrir l’onglet SQL Editor.
- Coller et exécuter le script suivant :
create table public.class_members (
id uuid default uuid_generate_v4() primary key,
class_id uuid references public.classes(id) on delete cascade not null,
user_id uuid references auth.users(id) on delete cascade not null,
joined_at timestamp with time zone default timezone('utc'::text, now()) not null,
unique(class_id, user_id)
);
Une solution
Vous devez être connecté pour voir le contenu.
Étape 2 — Vérifier que la table a été créée correctement
- Aller dans l’onglet Table Editor.
- Vérifier que la table
class_members
existe. - Vérifier que les colonnes suivantes sont présentes :
id
,class_id
,user_id
,joined_at
. - Vérifier les contraintes : clés étrangères et contrainte
UNIQUE
.
Une solution
Vous devez être connecté pour voir le contenu.
Étape 3 — Insérer une classe et un utilisateur si besoin
Si vous n’avez pas encore de classe ou d’utilisateur, créez-les :
insert into public.classes (id, name, description)
values (uuid_generate_v4(), 'Classe Alpha', 'Introduction à PostgreSQL');
Pour un utilisateur, vous pouvez en créer un via l’interface Auth > Users de Supabase.
Une solution
Vous devez être connecté pour voir le contenu.
Étape 4 — Insérer une ligne dans class_members
- Récupérer l’
id
d’un utilisateur existant dansauth.users
. - Récupérer l’
id
d’une classe existante danspublic.classes
. - Exécuter la requête suivante :
insert into public.class_members (class_id, user_id)
values ('<id_classe>', '<id_utilisateur>');
Remplacer <id_classe>
et <id_utilisateur>
par les UUID réels.
Une solution
Vous devez être connecté pour voir le contenu.
Étape 5 — Vérifier que l’insertion a fonctionné
- Aller dans Table Editor > class_members.
- Vérifier que la ligne est bien présente.
- Vérifier que la colonne
joined_at
est remplie automatiquement. - Vérifier que l’UUID généré pour
id
est bien présent.
Une solution
Vous devez être connecté pour voir le contenu.
Étape 6 — Tester la contrainte UNIQUE
- Réexécuter la même requête d’insertion qu’à l’étape 4.
- Observer l’erreur retournée par Supabase.
Une solution
Vous devez être connecté pour voir le contenu.
Étape 7 — Tester la suppression en cascade
- Supprimer la classe utilisée avec la commande suivante :
delete from public.classes where id = '<id_classe>';
- Vérifier que l’entrée correspondante dans
class_members
a bien été supprimée.
Une solution
Vous devez être connecté pour voir le contenu.
Étape 8 — Refaire un test avec un nouvel utilisateur et une nouvelle classe
- Créer une nouvelle classe et un nouvel utilisateur.
- Insérer une nouvelle ligne dans
class_members
. - Supprimer l’utilisateur.
- Vérifier que la ligne dans
class_members
est bien supprimée.
Une solution
Vous devez être connecté pour voir le contenu.
Étape 9 — Écrire une requête SQL pour afficher tous les membres d’une classe
Écrire une requête SQL qui affiche tous les user_id
associés à une classe donnée.
select user_id from public.class_members
where class_id = '<id_classe>';
Une solution
Vous devez être connecté pour voir le contenu.
Étape 10 — Vérifier l’intégrité des données
- Tenter d’insérer un
class_id
ouuser_id
qui n’existe pas. - Observer le message d’erreur.
Une solution
Vous devez être connecté pour voir le contenu.