Insérer les questions (seed)
Remplir les tables avec les 3 thèmes, les 27 questions et les 108 réponses du quiz, puis vérifier le résultat.
Objectifs de la séance
- écrire des instructions
insert ... valuesqui ajoutent plusieurs lignes à la fois ; - doubler les apostrophes dans les textes SQL ;
- insérer les données dans le bon ordre (parents avant enfants) ;
- recaler les compteurs automatiques avec
setval; - vérifier le contenu de la base avec
select count(*).
Petite vérification
Avant de commencer, vérifiez si vous savez...
- dans Table Editor de Supabase, ouvrir la table
questionet compter ses colonnes - citer le nom de l'index qui garantit qu'une question n'a qu'une seule bonne réponse
- dire combien de caractères, au maximum, peut contenir le libellé d'un thème (colonne
libelle)
📌 Réponse attendue
TP pour réfléchir et résoudre des problèmes
Votre mission : écrire le script sql/02_seed.sql qui remplit les tables. On appelle ce type
de script un seed (« graine ») : il plante les données de départ. Ce sont exactement les
mêmes données que celles de src/data/questionsLocales.ts, pour que le quiz se comporte à
l'identique une fois connecté à Supabase.
Le script complet fait environ 180 lignes : le voici, à copier dans votre fichier
sql/02_seed.sql. Les étapes ci-dessous en expliquent chaque partie.
Le script complet 02_seed.sql à copier
-- =====================================================================
-- 02_seed.sql : jeu de données du Quiz Cyber
-- 3 thèmes, 27 questions, 108 réponses
-- (mêmes données que src/data/questionsLocales.ts)
-- À exécuter UNE fois, après 01_tables.sql
-- =====================================================================
insert into public.theme (code, libelle) values
('mots-de-passe', 'Mots de passe'),
('hameconnage', 'Hameçonnage'),
('reseaux', 'Réseaux et Wi-Fi');
-- Les identifiants sont fixés à la main pour que les réponses puissent
-- référencer leur question (réponse n de la question q : id = q*10 + n).
insert into public.question (id, theme_code, niveau, enonce, explication, image_nom) values
(1, 'mots-de-passe', 1, 'Quel est le mot de passe le plus robuste ?',
'Une longue phrase de passe, avec des mots sans lien entre eux, est bien plus difficile à deviner qu''un mot court.', 'cadenas.png'),
(2, 'mots-de-passe', 1, 'Pouvez-vous utiliser le même mot de passe pour tous vos comptes ?',
'Si un seul site se fait voler ses mots de passe, tous vos comptes deviennent accessibles : un mot de passe différent par compte est indispensable.', null),
(3, 'mots-de-passe', 1, 'Un collègue vous demande votre mot de passe pour dépanner. Que faites-vous ?',
'Un mot de passe est personnel : on ne le communique jamais, même à un collègue ou au service informatique.', null),
(4, 'mots-de-passe', 2, 'À quoi sert un gestionnaire de mots de passe ?',
'Un gestionnaire (comme Bitwarden ou KeePassXC) génère et retient des mots de passe uniques et robustes, protégés par un seul mot de passe maître.', null),
(5, 'mots-de-passe', 2, 'Que signifie « double authentification » (2FA) ?',
'La 2FA combine deux preuves différentes (ce que vous savez et ce que vous possédez) : un mot de passe volé ne suffit plus.', null),
(6, 'mots-de-passe', 2, 'Le site haveibeenpwned.com vous indique que votre e-mail a fuité. Que faites-vous en priorité ?',
'Il faut changer immédiatement le mot de passe du compte concerné, et partout où il était réutilisé, puis activer la 2FA.', null),
(7, 'mots-de-passe', 3, 'Pourquoi un site doit-il stocker les mots de passe « hachés » plutôt qu''en clair ?',
'Le hachage est à sens unique : en cas de vol de la base, l''attaquant ne lit pas directement les mots de passe.', null),
(8, 'mots-de-passe', 3, 'Qu''est-ce qu''une attaque par « bourrage d''identifiants » (credential stuffing) ?',
'L''attaquant teste automatiquement des couples e-mail/mot de passe volés sur un site sur de nombreux autres sites : d''où l''importance de ne jamais réutiliser un mot de passe.', null),
(9, 'mots-de-passe', 3, 'Quelle méthode de double authentification résiste le mieux à l''hameçonnage ?',
'Une clé de sécurité physique (FIDO2) ou une clé d''accès (passkey) vérifie l''adresse du site : elle ne fonctionne pas sur un faux site.', null),
(10, 'hameconnage', 1, 'Qu''est-ce que l''hameçonnage (phishing) ?',
'L''hameçonnage consiste à se faire passer pour un organisme de confiance afin de voler des informations (identifiants, coordonnées bancaires...).', 'hamecon.png'),
(11, 'hameconnage', 1, 'Vous recevez un SMS : « Votre colis est bloqué, payez 1,99 € ici ». Que faites-vous ?',
'C''est une arnaque classique : on ne clique pas, on vérifie directement sur le site officiel du transporteur.', null),
(12, 'hameconnage', 1, 'Quel indice doit vous alerter dans un e-mail ?',
'L''urgence (« votre compte sera fermé dans 24 h ») est une technique de manipulation très utilisée pour vous empêcher de réfléchir.', null),
(13, 'hameconnage', 2, 'Le lien affiché est « www.ma-banque.fr » mais pointe vers « ma-banque.secure-login.ru ». C''est :',
'Le vrai domaine est celui qui précède l''extension : ici « secure-login.ru ». Survolez toujours un lien avant de cliquer.', null),
(14, 'hameconnage', 2, 'Qu''est-ce que le « spear phishing » ?',
'C''est un hameçonnage ciblé : l''attaquant utilise des informations sur sa victime (nom, poste, collègues) pour rendre le message crédible.', null),
(15, 'hameconnage', 2, 'Vous avez cliqué sur un lien suspect et saisi votre mot de passe. Que faites-vous ?',
'Il faut agir vite : changer le mot de passe et prévenir le service informatique (ou le RSSI) pour limiter les dégâts.', null),
(16, 'hameconnage', 3, 'Le directeur vous demande par e-mail un virement urgent et confidentiel. De quelle arnaque s''agit-il probablement ?',
'C''est la « fraude au président » : on vérifie toujours une demande inhabituelle par un autre canal (téléphone connu, en personne).', null),
(17, 'hameconnage', 3, 'Pourquoi le cadenas (HTTPS) dans le navigateur ne prouve-t-il pas qu''un site est honnête ?',
'HTTPS chiffre la connexion, mais n''importe qui (y compris un escroc) peut obtenir un certificat pour son propre faux site.', null),
(18, 'hameconnage', 3, 'Quel enregistrement DNS aide un serveur de messagerie à détecter un expéditeur usurpé ?',
'SPF, DKIM et DMARC permettent de vérifier qu''un e-mail provient bien d''un serveur autorisé par le domaine de l''expéditeur.', null),
(19, 'reseaux', 1, 'Sur un Wi-Fi public gratuit (gare, café), que faut-il éviter ?',
'Un Wi-Fi public peut être espionné ou imité par un pirate : évitez les opérations sensibles (banque, achats) ou utilisez la 4G/5G.', 'wifi.png'),
(20, 'reseaux', 1, 'Pourquoi faut-il installer les mises à jour de son téléphone ?',
'Les mises à jour corrigent des failles de sécurité connues que les pirates exploitent activement.', null),
(21, 'reseaux', 1, 'Vous trouvez une clé USB sur le parking du lycée. Que faites-vous ?',
'Une clé USB inconnue peut contenir un logiciel malveillant : on ne la branche jamais, on la remet au service informatique.', null),
(22, 'reseaux', 2, 'Quel protocole de sécurité Wi-Fi est le plus récent et le plus sûr ?',
'WPA3 est le standard actuel. WEP est cassable en quelques minutes et WPA2 reste acceptable avec un mot de passe robuste.', null),
(23, 'reseaux', 2, 'À quoi sert un VPN sur un réseau public ?',
'Un VPN crée un tunnel chiffré entre votre appareil et le serveur VPN : les autres utilisateurs du réseau ne peuvent pas lire votre trafic.', null),
(24, 'reseaux', 2, 'Qu''est-ce qu''un pare-feu (firewall) ?',
'Un pare-feu filtre les communications réseau entrantes et sortantes selon des règles (ports, adresses, applications).', null),
(25, 'reseaux', 3, 'Qu''est-ce qu''une attaque de « l''homme du milieu » (man-in-the-middle) ?',
'L''attaquant s''intercale entre deux interlocuteurs pour lire ou modifier leurs échanges, par exemple via un faux point d''accès Wi-Fi.', null),
(26, 'reseaux', 3, 'Qu''est-ce qu''une attaque par déni de service distribué (DDoS) ?',
'Des milliers de machines (souvent un réseau de machines piratées, ou botnet) saturent un service de requêtes pour le rendre indisponible.', null),
(27, 'reseaux', 3, 'Pourquoi segmenter le réseau d''une entreprise en plusieurs VLAN ?',
'La segmentation limite la propagation d''une attaque : un poste compromis dans un VLAN n''accède pas directement aux serveurs d''un autre VLAN.', null);
insert into public.reponse (id, question_id, texte, est_correcte) values
(11, 1, '123456', false),
(12, 1, 'MonChienRex', false),
(13, 1, 'Velo-Rouge-Mange-7-Nuages!', true),
(14, 1, 'azerty', false),
(21, 2, 'Oui, c''est plus simple à retenir', false),
(22, 2, 'Non, il faut un mot de passe différent par compte', true),
(23, 2, 'Oui, s''il contient un chiffre', false),
(24, 2, 'Oui, pour les comptes sans importance', false),
(31, 3, 'Je le lui donne à l''oral', false),
(32, 3, 'Je l''écris sur un post-it', false),
(33, 3, 'Je le lui envoie par e-mail', false),
(34, 3, 'Je refuse : un mot de passe ne se partage pas', true),
(41, 4, 'À stocker et générer des mots de passe robustes', true),
(42, 4, 'À pirater les mots de passe des autres', false),
(43, 4, 'À supprimer les mots de passe oubliés', false),
(44, 4, 'À partager ses mots de passe sur les réseaux', false),
(51, 5, 'Taper deux fois le même mot de passe', false),
(52, 5, 'Avoir deux comptes sur le même site', false),
(53, 5, 'Prouver son identité avec deux facteurs différents', true),
(54, 5, 'Changer de mot de passe deux fois par an', false),
(61, 6, 'Rien, ce n''est pas grave', false),
(62, 6, 'Je change le mot de passe concerné et active la 2FA', true),
(63, 6, 'Je supprime mon adresse e-mail', false),
(64, 6, 'J''attends de recevoir un e-mail suspect', false),
(71, 7, 'Pour que la base de données prenne moins de place', false),
(72, 7, 'Pour pouvoir les envoyer par e-mail aux utilisateurs', false),
(73, 7, 'Pour accélérer la connexion des utilisateurs', false),
(74, 7, 'Pour qu''un vol de la base ne révèle pas les mots de passe', true),
(81, 8, 'Réutiliser des identifiants volés sur d''autres sites', true),
(82, 8, 'Remplir un formulaire avec du texte très long', false),
(83, 8, 'Deviner un mot de passe en lisant par-dessus l''épaule', false),
(84, 8, 'Créer de nombreux faux comptes', false),
(91, 9, 'Un code reçu par SMS', false),
(92, 9, 'Une question secrète', false),
(93, 9, 'Une clé de sécurité physique (FIDO2) ou une passkey', true),
(94, 9, 'Un code envoyé par e-mail', false),
(101, 10, 'Un message frauduleux pour voler des informations', true),
(102, 10, 'Un logiciel qui accélère l''ordinateur', false),
(103, 10, 'Une technique de pêche en mer', false),
(104, 10, 'Une mise à jour de sécurité', false),
(111, 11, 'Je paie, ce n''est pas cher', false),
(112, 11, 'Je réponds pour demander des détails', false),
(113, 11, 'Je ne clique pas et je vérifie sur le site officiel', true),
(114, 11, 'Je transfère le SMS à mes amis', false),
(121, 12, 'Il contient votre prénom', false),
(122, 12, 'Il vous presse d''agir dans l''urgence', true),
(123, 12, 'Il est écrit en français', false),
(124, 12, 'Il a été envoyé le matin', false),
(131, 13, 'Normal, c''est un sous-domaine de la banque', false),
(132, 13, 'Sans risque grâce au mot « secure »', false),
(133, 13, 'Un lien vers le site officiel de la banque', false),
(134, 13, 'Un lien piégé vers un autre domaine', true),
(141, 14, 'Un hameçonnage envoyé à des millions de personnes', false),
(142, 14, 'Un hameçonnage ciblé et personnalisé', true),
(143, 14, 'Un antivirus spécialisé', false),
(144, 14, 'Un message envoyé uniquement par SMS', false),
(151, 15, 'Je change mon mot de passe et je préviens le service informatique', true),
(152, 15, 'Je n''en parle à personne', false),
(153, 15, 'J''éteins l''écran et j''attends', false),
(154, 15, 'Je supprime l''e-mail, c''est suffisant', false),
(161, 16, 'Une arnaque au support technique', false),
(162, 16, 'Un rançongiciel', false),
(163, 16, 'La fraude au président', true),
(164, 16, 'Une attaque par déni de service', false),
(171, 17, 'Parce que le cadenas est souvent faux', false),
(172, 17, 'Parce qu''un escroc peut aussi obtenir un certificat HTTPS', true),
(173, 17, 'Parce que HTTPS est obsolète', false),
(174, 17, 'Parce que le cadenas ne s''affiche que sur mobile', false),
(181, 18, 'SPF / DKIM / DMARC', true),
(182, 18, 'HTTP / FTP / SSH', false),
(183, 18, 'MX / CNAME / AAAA', false),
(184, 18, 'DHCP / NAT / VLAN', false),
(191, 19, 'Lire la météo', false),
(192, 19, 'Consulter un plan de la ville', false),
(193, 19, 'Regarder les horaires de train', false),
(194, 19, 'Se connecter à sa banque en ligne', true),
(201, 20, 'Pour changer les couleurs de l''écran', false),
(202, 20, 'Pour corriger des failles de sécurité', true),
(203, 20, 'Pour libérer de l''espace de stockage', false),
(204, 20, 'Ce n''est pas utile', false),
(211, 21, 'Je la remets au service informatique sans la brancher', true),
(212, 21, 'Je la branche pour trouver son propriétaire', false),
(213, 21, 'Je la garde pour moi', false),
(214, 21, 'Je la branche sur un ordinateur du CDI', false),
(221, 22, 'WEP', false),
(222, 22, 'WPA', false),
(223, 22, 'WPA3', true),
(224, 22, 'Aucun, un réseau ouvert suffit', false),
(231, 23, 'À rendre la connexion plus rapide', false),
(232, 23, 'À supprimer les virus', false),
(233, 23, 'À obtenir un Wi-Fi gratuit', false),
(234, 23, 'À chiffrer le trafic dans un tunnel', true),
(241, 24, 'Un dispositif qui filtre le trafic réseau', true),
(242, 24, 'Un antivirus pour téléphone', false),
(243, 24, 'Un câble réseau résistant à la chaleur', false),
(244, 24, 'Un logiciel de sauvegarde', false),
(251, 25, 'Un pirate qui attaque au milieu de la nuit', false),
(252, 25, 'Un pirate qui intercepte les échanges entre deux parties', true),
(253, 25, 'Un virus qui se cache au milieu d''un fichier', false),
(254, 25, 'Une panne du routeur central', false),
(261, 26, 'Le vol d''un mot de passe administrateur', false),
(262, 26, 'Le chiffrement des fichiers contre une rançon', false),
(263, 26, 'La saturation d''un service par de nombreuses machines', true),
(264, 26, 'L''écoute d''un réseau Wi-Fi', false),
(271, 27, 'Pour augmenter le débit Internet', false),
(272, 27, 'Pour économiser des adresses IP publiques', false),
(273, 27, 'Pour éviter d''acheter un pare-feu', false),
(274, 27, 'Pour limiter la propagation d''une attaque', true);
-- Les identifiants ayant été fixés à la main, on recale les compteurs
-- automatiques (sinon la prochaine insertion tenterait id = 1 : doublon !).
select setval(pg_get_serial_sequence('public.question', 'id'), (select max(id) from public.question));
select setval(pg_get_serial_sequence('public.reponse', 'id'), (select max(id) from public.reponse));
Étape 1 — Insérer les thèmes
L'instruction insert into ajoute des lignes dans une table : on indique la table, la liste des
colonnes, puis values suivi d'une ligne entre parenthèses par thème. Les thèmes viennent en
premier, car les questions les référencent.
Écrire (code, libelle) après le nom de la table rend l'instruction lisible, et elle continue de
fonctionner si l'on ajoute plus tard une colonne à la table.
Étape 2 — Insérer les questions
Les 27 questions sont insérées en une seule instruction. Leur identifiant (id) est fixé à la
main, de 1 à 27, pour que les réponses puissent désigner leur question. Les valeurs sont dans
l'ordre des colonnes : id, theme_code, niveau, enonce, explication, image_nom.
Attention aux apostrophes : en SQL, un texte est entouré d'apostrophes. Pour écrire une
apostrophe dans le texte, on la double (''). Ainsi, « Qu'est-ce que » s'écrit
'Qu''est-ce que'. Quand une question n'a pas d'illustration, on écrit null à la place de
image_nom.
Dans une longue liste de values, une erreur d'ordre (niveau à la place de l'identifiant...) passe
inaperçue. Relisez toujours la liste de colonnes avant de saisir la première ligne.
Étape 3 — Insérer les réponses
Chaque question a quatre réponses. Pour que les identifiants restent lisibles, on suit une
convention : la réponse numéro n de la question q a pour identifiant q * 10 + n. La réponse 3
de la question 1 a donc l'identifiant 13. Les colonnes sont id, question_id, texte,
est_correcte.
Vérifiez que, pour chaque question, une seule réponse vaut true. Si vous en mettez deux, l'index
unique partiel créé à la séance précédente refusera la ligne, et le script s'arrêtera avec une erreur.
Étape 4 — Recaler les compteurs automatiques
Les colonnes id de question et reponse sont numérotées automatiquement par PostgreSQL, grâce à
un compteur (une séquence). Comme vous avez fixé les identifiants à la main, ce compteur n'a
jamais bougé : il vaut encore 1. La prochaine insertion d'une question tenterait donc id = 1 et
échouerait avec une erreur de doublon.
La fonction setval place le compteur sur la plus grande valeur existante :
Un seed qui fixe des identifiants doit toujours recaler les compteurs. Sans cela, le bug n'apparaît que bien plus tard (le jour où l'on ajoute une question), ce qui le rend difficile à comprendre.
Étape 5 — Exécuter le script et vérifier
Collez le script complet dans le SQL Editor, puis cliquez sur Run. Ne l'exécutez qu'une seule fois : un second passage provoquerait une erreur de doublon, car les identifiants existent déjà.
Vérifiez ensuite le contenu des tables avec des requêtes de comptage. Le SQL Editor n'affiche que le résultat de la dernière requête : exécutez-les une par une (en sélectionnant la requête voulue avant de cliquer sur Run).
select count(*) from public.theme;
select count(*) from public.question;
select count(*) from public.reponse;
select count(*) from public.reponse where est_correcte;
Vous devez obtenir 3, 27, 108 puis 27 : il y a bien exactement une bonne réponse par question.
Compter les lignes prend dix secondes et évite de découvrir, en pleine partie, qu'une question n'a que trois réponses. Les nombres attendus (3, 27, 108, 27) se calculent à l'avance : c'est un petit test.
Étape 6 — Enregistrer votre travail
Le seed est dans le dépôt : un coéquipier (ou vous, après une erreur) peut reconstruire la base
complète en rejouant 01_tables.sql puis 02_seed.sql.
📌 Une solution
Notions théoriques
L'instruction insert
insert into public.nom_de_la_table (colonne1, colonne2) values
(valeur1, valeur2),
(valeur3, valeur4);
- les colonnes listées et les valeurs fournies doivent être dans le même ordre ;
- on peut ajouter plusieurs lignes dans une seule instruction, séparées par des virgules ;
- les textes sont entourés d'apostrophes (
'Hameçonnage'), les nombres et les booléens (true,false) ne le sont pas ; nullreprésente une valeur absente (une question sans illustration) ;- l'instruction se termine par un point-virgule.
Les apostrophes dans les textes
Comme l'apostrophe sert de délimiteur, on la double à l'intérieur d'un texte :
'l''hameçonnage' donne l'hameçonnage. Oublier de la doubler provoque une erreur de syntaxe
(le texte semble se terminer trop tôt).
Identifiants fixés ou automatiques
Les colonnes id ont été déclarées generated by default as identity : PostgreSQL les numérote
si on ne lui donne pas de valeur, mais accepte aussi une valeur imposée. Dans un seed, on impose
les identifiants pour que les réponses puissent référencer leur question sans rechercher son numéro.
Il faut alors recaler le compteur avec setval : sans cela, la prochaine insertion automatique
réutiliserait un identifiant déjà pris.
L'ordre d'insertion
À cause des clés étrangères, la base refuse d'insérer une question dont le thème n'existe pas, ou
une réponse dont la question n'existe pas. On insère donc toujours les tables « parents » avant
les tables « enfants » : theme, puis question, puis reponse.
Pourquoi un seed ?
- il rend la base reproductible : mêmes données pour tous les étudiants ;
- il sert de source commune : ces données sont les mêmes que
questionsLocales.ts; - il se versionne avec Git comme n'importe quel fichier de code.
Le type TypeScript CodeTheme de l'application ne connaît que ces trois codes. Ajouter un thème dans
la base obligerait donc aussi à modifier l'application : c'est un choix volontaire, pour garder le
projet simple.
Test de mémorisation/compréhension
Exercices complémentaires
Exercice A : lire le contenu dans Table Editor
Dans Table Editor, ouvrez la table reponse, filtrez sur question_id = 13, et retrouvez les
quatre réponses de la question 13 ainsi que la bonne réponse.
Exercice B : repérer les questions illustrées
Combien de questions possèdent une illustration (image_nom non vide) ? Trouvez la réponse en
parcourant le script, puis vérifiez-la dans Table Editor.
Ce qu'il faut retenir
| Notion | Résumé |
|---|---|
insert into ... values | Ajoute une ou plusieurs lignes ; colonnes et valeurs dans le même ordre. |
| Apostrophe | À l'intérieur d'un texte SQL, elle se double (''). |
| Ordre d'insertion | Les tables parents (theme) avant les tables enfants (question, puis reponse). |
setval | Recale le compteur automatique après avoir fixé des identifiants à la main. |
select count(*) | Compte les lignes : indispensable pour vérifier un chargement de données. |
| Seed | Script de données de départ, reproductible et versionné avec Git. |
Aperçu de la prochaine séance
Vos données sont dans la base, mais pour l'instant personne ne peut les lire depuis une
application. Dans la prochaine séance, vous allez comprendre qui a le droit de faire quoi avec la
RLS (Row Level Security), et vous la testerez en interrogeant l'API de Supabase avec la commande
curl, comme le ferait un pirate.