skilling.maSkill. Scale. Soar.
Partie 1 — SI & Cadrage projet Systèmes d'information 4 composantes
⏱ 16 min

Systèmes d'information

Définition d'un SI, ses 4 composantes (Individus, Matériel, Logiciels/Procédures, Données), les fonctions d'un SI, la différence entre SI et système informatique, et exemples concrets d'entreprises marocaines.

✓ Ce que vous allez apprendre
  • Définir un Système d'Information et le distinguer d'un système informatique
  • Identifier les 4 composantes d'un SI : Individus, Matériel, Logiciels/Procédures, Données
  • Comprendre les 4 fonctions d'un SI : collecter, stocker, traiter, diffuser
  • Reconnaître les niveaux d'information dans une organisation (opérationnel, tactique, stratégique)

1
Définition d'un Système d'Information
SI · Organisation · Données · Décision
ℹ Définition formelle

Un Système d'Information (SI) est un ensemble organisé de ressources (humaines, matérielles, logicielles et données) permettant de collecter, stocker, traiter et diffuser de l'information au sein d'une organisation pour aider à la prise de décision.

SI vs Système Informatique — ne pas confondre

Le système informatique est uniquement la partie technique (ordinateurs, serveurs, réseaux). Il est une sous-composante du SI. Un SI existait avant les ordinateurs — les registres papier d'une administration marocaine des années 1960 constituaient déjà un SI.

Exemple : la Direction Régionale des Impôts de Casablanca possède un SI composé de : agents (individus), ordinateurs et serveurs (matériel), logiciel de gestion fiscale + procédures internes (logiciels), dossiers des contribuables (données). L'ensemble forme le SI, pas uniquement les ordinateurs.

CritèreSystème d'InformationSystème Informatique
PérimètreHumain + technique + organisationnelUniquement technique
ComposantesIndividus, matériel, logiciels, donnéesServeurs, réseaux, logiciels système
Existence sans ordinateurOui — systèmes papierNon par définition
ObjectifAider à la décisionAutomatiser des traitements

2
Les 4 composantes d'un SI
Individus · Matériel · Logiciels & Procédures · Données
ComposanteDéfinitionExemple SkolaBase (Centre de Formation)
1. IndividusPersonnes qui utilisent, font fonctionner ou décident grâce au SI : utilisateurs, informaticiens, managersFormateurs, étudiants, secrétaires, directeur pédagogique
2. MatérielTous les équipements physiques : ordinateurs, serveurs, imprimantes, réseaux, scannersPC de la salle informatique, serveur MySQL, imprimante convocations, réseau WiFi
3. Logiciels & ProcéduresProgrammes informatiques ET procédures humaines (règles, modes opératoires, formulaires)Application de gestion des inscriptions, procédure d'inscription, règlement intérieur
4. DonnéesToutes les informations traitées et stockées : fichiers, BDD, archives papier ou numériquesDossiers étudiants, notes, emplois du temps, contrats de formation
ℹ Moyen mémo-technique

Retenez IMLD : Individus — Matériel — Logiciels/procédures — Données. Ou l'image d'un restaurant : les serveurs (I), la cuisine et les ustensiles (M), les recettes et les règles d'hygiène (L), les commandes des clients (D).


3
Les 4 fonctions d'un SI
Collecter · Stocker · Traiter · Diffuser
textCycle de l'information dans un SI — SkolaBase
COLLECTER              STOCKER              TRAITER              DIFFUSER
    |                      |                    |                    |
Fiches d'inscription  Base de données      Calcul des notes     Bulletins de notes
Feuilles de présence  Fichiers Excel       Statistiques         Convocations examen
Résultats examens    Archives papier      Emplois du temps     Attestations
    ↓                      ↓                    ↓                    ↓
 Saisie/scan         MySQL / Cloud        Logiciel gestion      Email / Impression

Collecter : acquérir les informations depuis l'environnement (inscriptions, résultats, présences). Stocker : conserver les informations de façon organisée et durable (BDD, archives). Traiter : transformer les données brutes en informations utiles (calcul de moyenne, statistiques de réussite). Diffuser : distribuer les résultats aux bonnes personnes au bon moment (bulletins aux étudiants, rapports à la direction).


4
Niveaux d'information dans une organisation
Niveau opérationnel · Tactique · Stratégique
Agrégée, synthétique, périodique
NiveauUtilisateursType d'informationExemple SkolaBaseHorizon temporel
OpérationnelEmployés, techniciensDétaillée, précise, temps réelListe des présences du jour, notes d'un examenJournalier
TactiqueChefs de service, responsablesTaux de réussite par filiale, bilan mensuel inscriptionsMensuel/Trimestriel
StratégiqueDirection généraleRésumée, prospective, comparativeRentabilité des formations, ouverture nouvelles filièresAnnuel/Pluriannuel

✓
Vérification des acquis
Un centre de formation de Rabat utilise uniquement des registres papier pour gérer ses inscriptions, sans aucun ordinateur. Possède-t-il un Système d'Information ?
Dans le SI d'une école à Casablanca, la procédure d'inscription (formulaires + règles de validation) appartient à quelle composante ?
Le directeur général d'un groupe de formation veut analyser la rentabilité de chaque filiale sur 5 ans pour décider d'ouvrir de nouveaux sites. Quel niveau d'information utilise-t-il ?
Partie 1 — SI & Cadrage projet Projet informatique CDC · CDCF · CDCT
⏱ 18 min

Projet informatique & Cahier des Charges

Les 5 phases d'un projet informatique (schéma directeur, étude préalable, étude détaillée, réalisation, mise en œuvre), définition et structure du CDC, différence CDCF et CDCT.

✓ Ce que vous allez apprendre
  • Les 5 phases d'un projet informatique et leur ordre logique
  • Définir le Cahier des Charges (CDC) et ses 5 sections
  • Distinguer CDCF (Fonctionnel) et CDCT (Technique)
  • Comprendre pourquoi le CDC est le document fondateur de tout projet

1
Les 5 phases d'un projet informatique
Schéma directeur · Étude préalable · Étude détaillée · Réalisation · Mise en œuvre
textCycle de vie d'un projet informatique — SkolaBase
Phase 1              Phase 2              Phase 3              Phase 4              Phase 5
SCHEMA              ETUDE                ETUDE                REALISATION          MISE EN
DIRECTEUR           PREALABLE            DETAILLEE                                 OEUVRE
    |                   |                    |                    |                    |
Orientation         Faisabilité         Spécifications        Développement        Déploiement
stratégique        Analyse besoins      Techniques            Tests                Formation
Budget global       Etude exist.         MCD / MLD             BDD + appli          Maintenance
Plan 3-5 ans        Proposition           Maquettes            Recette              Evolution
PhaseObjectif principalLivrableSkolaBase — exemple
1. Schéma directeurDéfinir la vision stratégique SI à 3-5 ansPlan directeur SIDécision de numériser la gestion du centre
2. Étude préalableAnalyser la faisabilité, l'existant, les besoinsRapport de faisabilitéInventaire des registres papier, entretiens avec le personnel
3. Étude détailléeSpécifier précisément ce qui sera construitCDC + MCD + MLDDictionnaire de données, MCD, maquettes écrans
4. RéalisationDévelopper et tester l'applicationApplication testéeCréation BDD MySQL, développement, tests
5. Mise en œuvreDéployer, former, maintenirSystème en productionInstallation serveur, formation secrétaires, support
⚠ L'erreur classique — sauter l'étude détaillée

Beaucoup de projets échouent parce qu'ils sautent la Phase 3 pour coder directement. Résultat : on développe une application qui ne correspond pas aux besoins réels. La règle d'or : 1 heure d'analyse évite 10 heures de développement erroné.


2
Le Cahier des Charges (CDC)
Définition · Structure en 5 sections · CDCF vs CDCT
ℹ Définition du CDC

Le Cahier des Charges est un document contractuel qui décrit précisément les besoins du client (maîtrise d'ouvrage) et ce que le prestataire (maîtrise d'œuvre) doit réaliser. C'est le contrat technique et fonctionnel du projet — toute ambigüité dans le CDC engendrera des litiges et des surcoûts.

#Section du CDCContenuSkolaBase — exemple
1Présentation du projetContexte, objectifs, périmètre, acteursCentre de formation YY, 500 étudiants/an, 3 filières
2Description de l'existantSituation actuelle, problèmes à résoudreInscriptions sur registres papier, pertes de données, doublons
3Expression des besoinsFonctionnalités attendues, contraintesGérer inscriptions, planifier sessions, générer bulletins
4Contraintes techniquesTechnologies imposées, environnement, sécuritéMySQL 8, Windows Server, 3 postes simultanés
5Livrables et planningCe qui doit être livré, échéances, budgetBDD + application + documentation, livraison en 3 mois
CritèreCDCF — Cahier des Charges FonctionnelCDCT — Cahier des Charges Technique
Rédigé parLe client (maîtrise d'ouvrage)Le prestataire (maîtrise d'œuvre)
LangageMétier, fonctionnel — sans jargon techniqueTechnique — langages, architectures, BDD
Répond àQuoi faire ? Pour qui ? Pourquoi ?Comment le faire ? Avec quoi ?
Exemple SkolaBase« Le système doit permettre d'inscrire un étudiant »« Table Etudiant : numCIN VARCHAR(8) PK, nomEtu VARCHAR(50) NN »

✓
Vérification des acquis
Un client écrit dans son document : « L'application doit permettre de saisir les notes des étudiants et calculer leur moyenne ». Ce document est-il un CDCF ou un CDCT ?
Dans quelle phase d'un projet informatique réalise-t-on le MCD et le dictionnaire de données ?
Partie 1 — SI & Cadrage projet Périmètre Contraintes · Budget · Temps
⏱ 14 min

Périmètre & Contraintes du projet

Délimiter précisément le périmètre d'un projet SI — 4 étapes (buts, livrables, tâches, contraintes), le triangle Budget/Délai/Portée, et les 5 questions clés pour fixer les limites.

✓ Ce que vous allez apprendre
  • Définir le périmètre d'un projet et pourquoi il est critique
  • Appliquer les 4 étapes de délimitation : buts, livrables, tâches, contraintes
  • Comprendre le triangle Budget/Délai/Portée (trilemme du projet)
  • Poser les 5 questions clés pour fixer les limites du périmètre

1
Définition et importance du périmètre
Scope · Inclus vs Exclus · Risques
ℹ Définition du périmètre

Le périmètre du projet (ou scope) définit précisément ce qui est inclus et ce qui est exclu du projet. Un périmètre mal défini est la première cause d'échec des projets informatiques : le client demande plus que prévu, le prestataire dépasse son budget, et les délais explosent.

Exemple SkolaBase : le client dit « je veux gérer mon centre de formation ». Cela peut vouloir dire 50 choses différentes. Le périmètre doit préciser :

  • Inclus : gestion des inscriptions, planning des sessions, gestion des notes, génération des bulletins
  • Exclus : gestion de la paie des formateurs, comptabilité générale, site web public, application mobile

Ce qui n'est pas explicitement inclus est exclu. Cette règle protège les deux parties.


2
Les 4 étapes de délimitation du périmètre
Buts · Livrables · Tâches · Contraintes
ÉtapeQuestion cléSkolaBase — exemple
1. Définir les butsPourquoi fait-on ce projet ? Quel problème résout-on ?Eliminer les registres papier, réduire les erreurs de saisie, accélérer la génération des bulletins de 3 jours à 5 minutes
2. Définir les livrablesQu'est-ce qui sera remis à la fin ? Quels documents, logiciels ?Base de données MySQL, application de gestion, documentation technique, manuel utilisateur, formation du personnel
3. Définir les tâchesQuelles activités faut-il réaliser pour produire les livrables ?Analyse Merise, création BDD, développement interface, tests, déploiement, formation
4. Définir les contraintesQuelles sont les limites (budget, temps, technique) ?Budget : 50 000 MAD max, Délai : 3 mois, Technique : MySQL + Windows

3
Le triangle Budget / Délai / Portée
Trilemme · Qualité · Arbitrage
textTriangle des contraintes d'un projet
                    PORTÉE
                  (fonctionnalités)
                       /\
                      /  \
                     /    \
                    /  ★   \
                   / QUALITÉ \
                  /____________\
              BUDGET          DÉLAI
           (coût)            (temps)

Principe fondamental :
  Si PORTEE augmente → BUDGET ou DELAI doit augmenter
  Si DELAI est réduit  → BUDGET augmente ou PORTEE diminue
  Si BUDGET est réduit → DELAI augmente ou PORTEE diminue
  On ne peut pas optimiser les 3 simultanément

Exemple concret SkolaBase : le client veut toutes les fonctionnalités (portée élevée) en 1 mois (délai court) pour 10 000 MAD (budget faible). C'est impossible. Le chef de projet doit aider le client à arbitrer : soit réduire les fonctionnalités (Phase 1 sans bulletins PDF), soit augmenter le budget, soit allonger le délai.

#Question à poser pour fixer les limitesSkolaBase — réponse attendue
1Quelles sont les fonctionnalités absolument indispensables (Must Have) ?Inscriptions, sessions, notes, bulletins
2Quelles fonctionnalités peut-on reporter à une version 2 (Nice to Have) ?Application mobile, statistiques avancées
3Quels systèmes existants faut-il intégrer ou migrer ?Migrer les données des registres papier 2022-2024
4Qui sont les utilisateurs et quels sont leurs droits ?Admin (tout), secrétaire (inscriptions), formateur (notes)
5Quelles sont les contraintes légales ou réglementaires ?Protection des données personnelles, conservation 5 ans

✓
Vérification des acquis
Le client SkolaBase demande en cours de projet d'ajouter une fonctionnalité de gestion des paiements non prévue dans le CDC. Que doit faire le chef de projet ?
Partie 1 — SI & Cadrage projet Bases de données 4 phases de conception
⏱ 16 min

Introduction aux Bases de données

Définition d'une BDD, ses 4 objectifs, les 4 phases de conception (analyse, modélisation conceptuelle, modélisation logique, implémentation), et identification des entités et données candidates depuis le CDC.

✓ Ce que vous allez apprendre
  • Définir une base de données et la distinguer d'un fichier Excel ou d'un fichier texte
  • Identifier les 4 objectifs fondamentaux d'une BDD (intégrité, partage, sécurité, non-redondance)
  • Connaître les 4 phases de conception : Analyse → MCD → MLD → Implémentation
  • Lire un CDC et identifier les entités candidates et leurs données

1
Définition et objectifs d'une BDD
Définition · 4 objectifs · BDD vs fichiers
ℹ Définition d'une base de données

Une base de données est un ensemble structuré et persistant de données liées entre elles, géré par un Système de Gestion de Base de Données (SGBD), accessible par plusieurs utilisateurs simultanément, et conçu pour minimiser la redondance.

CritèreFichier Excel / CSVBase de données MySQL
Accès simultanéProblèmes de conflits si plusieurs utilisateursNatif — gestion des verrous, transactions
Intégrité des donnéesAucune contrainte — on peut mettre n'importe quoiClés primaires, étrangères, NOT NULL, CHECK
Volume de donnéesLimité (1 048 576 lignes Excel max)Milliards d'enregistrements
SécuritéMot de passe fichier uniquementUtilisateurs, rôles, privilèges granulaires
Relations entre donnéesManuelles — erreurs fréquentesClés étrangères — intégrité référentielle automatique
RedondanceÉlevée — même info dans plusieurs cellulesRéduite grâce à la normalisation
#Objectif d'une BDDExplicationExemple SkolaBase
1Non-redondanceChaque information est stockée une seule foisLe nom d'un étudiant n'est saisi qu'une fois, pas dans chaque note
2IntégritéLes données respectent des règles de validitéImpossible d'enregistrer une note > 20 ou un étudiant sans CIN
3PartagePlusieurs utilisateurs accèdent simultanémentLa secrétaire inscrit pendant que le formateur saisit les notes
4SécuritéContrôle d'accès selon les rôlesLe formateur voit seulement ses étudiants, pas les données financières

2
Les 4 phases de conception d'une BDD
Analyse · MCD · MLD · Implémentation
textPipeline de conception d'une BDD — SkolaBase
PHASE 1              PHASE 2              PHASE 3              PHASE 4
ANALYSE             MCD                  MLD                  IMPLEMENTATION
    |                   |                    |                    |
Lire le CDC         Entités              Tables SQL           CREATE TABLE
Identifier          Associations         Clés primaires       INSERT INTO
entités            Cardinalités         Clés étrangères      Requêtes
Dictionnaire        Formes norm.         Contraintes          Index
de données         Graphe DF            Types de données
    |                   |                    |                    |
Niveau              Niveau               Niveau               Niveau
conceptuel          conceptuel           logique              physique
(métier)           (indép. SGBD)        (dépend SGBD)        (MySQL 8)
PhaseNiveauOutil/MéthodeRésultat
1. AnalyseConceptuel métierLecture CDC, entretiens, RGDictionnaire de données, Graphe des DF
2. MCDConceptuel (indépendant du SGBD)Merise, entités-associationsModèle Conceptuel de Données
3. MLDLogique (dépend du type de SGBD)Règles de passage MCD→MLDModèle Logique de Données (tables)
4. ImplémentationPhysique (MySQL spécifique)SQL DDL : CREATE TABLEBase de données opérationnelle

3
Identifier les entités et données depuis le CDC
Lecture CDC · Entités candidates · Première analyse SkolaBase
ℹ Méthode de lecture du CDC

Lors de la lecture du CDC, on souligne les noms (substantifs) qui représentent des entités candidates (choses dont on veut stocker des informations) et les verbes qui représentent des associations entre ces entités.

textExtrait CDC SkolaBase — identification des entités
CDC SkolaBase — Centre de Formation (extrait)

« Le centre gère des ETUDIANTS qui s'inscrivent à des SESSIONS
  de FORMATION. Chaque session est animée par un FORMATEUR.
  Les étudiants reçoivent des notes à chaque session.
  Chaque formation appartient à une FILIERE. »

Entités candidates identifiées :
  ■ ETUDIANT    → numCIN, nomEtu, prenomEtu, dateNaiss, ville
  ■ FORMATION   → codeForm, titreForm, dureeForm, niveauForm
  ■ SESSION     → codeSess, dateDebut, dateFin, lieuSess
  ■ FORMATEUR   → numFormateur, nomForm, specialite
  ■ FILIERE     → codeFiliere, libelleFiliere

Associations identifiées :
  ■ ETUDIANT    ---[s'inscrit]---    SESSION
  ■ SESSION     ---[est animée par]--- FORMATEUR
  ■ SESSION     ---[porte sur]---     FORMATION
  ■ FORMATION   ---[appartient à]---  FILIERE

✓
Vérification des acquis
Le MCD est décrit comme « indépendant du SGBD ». Que signifie cette affirmation ?
Un étudiant inscrit dans plusieurs sessions, et chaque session a une note. Dans quel objet du CDC se trouve cette information ?
Partie 2 — Modélisation Merise Règles de gestion RG1 · RG2 · RGn
⏱ 16 min

Règles de gestion

Identifier les règles de gestion depuis un CDC, les traduire en tableau numéroté (RG1…RGn) qui relie les entités entre elles — fondement de toute la modélisation Merise — application complète sur SkolaBase.

✓ Ce que vous allez apprendre
  • Définir une règle de gestion et la distinguer d'une contrainte technique
  • Lire un CDC et extraire les RG de manière systématique
  • Traduire chaque RG en tableau numéroté : entité source → verbe → entité cible + quantité
  • Compléter le tableau des RG de SkolaBase (6 règles)

1
Définition et rôle des règles de gestion
RG · Cardinalités · CDC · Fondement Merise
ℹ Définition

Une règle de gestion (RG) est une contrainte métier qui décrit comment les entités du système se comportent et interagissent. Elle est exprimée en langage naturel (pas technique) et provient directement du CDC ou des entretiens avec les utilisateurs. Les RG sont le pont entre le CDC et le MCD.

Pourquoi les RG sont-elles critiques ?

Les RG déterminent directement les cardinalités du MCD. Une erreur dans les RG entraîne un MCD faux, un MLD faux, et donc une BDD qui ne correspond pas aux besoins réels. Reformuler les RG avec le client avant de modéliser est la pratique la plus importante de Merise.

CritèreRègle de gestionContrainte technique
LangageMétier, naturelTechnique (SQL, code)
SourceCDC, utilisateursInformaticien/DBA
Exemple« Un étudiant peut s'inscrire à plusieurs sessions »FOREIGN KEY (numEtu) REFERENCES Etudiant(numCIN)
ImpactCardinalités du MCDImplémentation BDD

2
Méthode d'extraction des RG depuis le CDC
Lire · Souligner · Reformuler · Numéroter
textExtrait CDC SkolaBase — identification des RG
Texte du CDC :
« Le centre gère des ETUDIANTS. Chaque étudiant possède un numéro de CIN unique.
  Les étudiants peuvent s'inscrire à plusieurs SESSIONS de FORMATION.
  Un étudiant ne peut s'inscrire qu'une seule fois à une même session.
  Chaque session est animée par un seul FORMATEUR.
  Un formateur peut animer plusieurs sessions au cours de l'année.
  Chaque session porte sur une seule FORMATION.
  Une formation peut donner lieu à plusieurs sessions différentes.
  Chaque formation appartient à une seule FILIERE.
  Une filière regroupe plusieurs formations. »

► Souligner les entités : ETUDIANT, SESSION, FORMATION, FORMATEUR, FILIERE
► Souligner les verbes : s'inscrire, animer, porter sur, appartenir à
► Extraire les quantités : « plusieurs » (N), « un seul » (1), « une seule fois » (1)

3
Tableau des règles de gestion — SkolaBase complet
Format : N° · Entité source · Verbe · Entité cible · Cardinalité
ℹ Format d'un tableau de RG

Chaque RG se lit dans les deux sens : « Un A peut avoir [0,1 ou N] B » ET « Un B peut avoir [0,1 ou N] A ». Les deux sens donnent les deux cardinalités de l'association dans le MCD.

N°Entité sourceVerbe (association)Entité cibleCard. sourceCard. cibleLecture
RG1ETUDIANTs'inscrit àSESSION0,N1,NUn étudiant peut s'inscrire à 0 ou plusieurs sessions. Une session a au moins 1 étudiant inscrit.
RG2FORMATEURanimeSESSION0,N1,1Un formateur anime 0 ou plusieurs sessions. Une session est animée par exactement 1 formateur.
RG3SESSIONporte surFORMATION1,N1,1Une session porte sur exactement 1 formation. Une formation peut avoir 1 ou plusieurs sessions.
RG4FORMATIONappartient àFILIERE1,11,NUne formation appartient à exactement 1 filière. Une filière regroupe 1 ou plusieurs formations.
RG5ETUDIANTobtientNOTE (sur SESSION)——L'inscription (RG1) porte une note — la note est un attribut de l'association INSCRIPTION
RG6FORMATEURspécialisé dansFILIERE0,N0,NUn formateur peut être spécialisé dans plusieurs filières. Une filière peut avoir plusieurs formateurs spécialisés.
⚠ RG5 — la note est un attribut d'association, pas une entité

La note n'est pas une entité indépendante — elle n'existe que dans le contexte d'une inscription d'un étudiant à une session. Elle sera donc placée comme attribut de l'association INSCRIPTION (entre ETUDIANT et SESSION) dans le MCD. C'est ce qu'on appelle une association porteuse de donnée.

Le CDC indique : « chaque session est animée par un seul formateur ». Quelle cardinalité cela implique-t-il du côté SESSION dans l'association ANIME ?
La note d'un étudiant à une session est-elle une entité indépendante dans le MCD ?
Partie 2 — Modélisation Merise Dictionnaire de données Types · Convention · Contrôles
⏱ 20 min

Dictionnaire de données

Construire le Dictionnaire de Données (DD) : structure (code/désignation/type/taille/observations), les 5 types, convention de nommage objetConcept, contrôles qualité (polysémies, synonymes, données calculées), DD complet SkolaBase.

✓ Ce que vous allez apprendre
  • Distinguer Concept, Donnée et Valeur
  • Construire la structure du DD : 5 colonnes obligatoires
  • Maîtriser les 5 types de données (A, N, AN, D, B)
  • Appliquer la convention de nommage objetConcept (ex : numCINEtu)
  • Détecter et corriger polysémies, synonymes et données calculées
  • Produire le DD complet de SkolaBase (16 données)

1
Concept, Donnée et Valeur
3 niveaux d'abstraction · Exemples concrets
NiveauDéfinitionExemple SkolaBaseContre-exemple
ConceptCatégorie abstraite dont on veut stocker des informations — c'est l'entitéETUDIANT, SESSION, FORMATEUR« personne » est trop vague sans contexte
DonnéePropriété d'un concept — une colonne dans la future tablenom de l'étudiant, date de début de session« âge » est calculé (pas une donnée brute)
ValeurContenu concret d'une donnée pour une occurrence« Alaoui », « 2024-09-01 »Une valeur seule sans contexte n'a pas de sens

2
Structure du Dictionnaire de Données
5 colonnes · Types ANDB · Convention objetConcept
ColonneContenuExemple
CodeNom technique de la donnée — convention objetConceptnumCINEtu, nomEtu, dateDebutSess
DésignationLibellé clair en français pour l'utilisateurNuméro CIN de l'étudiant, Nom de l'étudiant
TypeNature de la donnée (voir tableau types)AN, A, D, N, B
TailleLongueur maximale ou précision8, 50, —, 4,2
ObservationsContraintes, remarques, valeurs possiblesUnique, PK, entre 0 et 20, format JJ/MM/AAAA
TypeNom completDescriptionExemplesSQL correspondant
AAlphabétiqueLettres uniquement (pas de chiffres)nomEtu, prenomEtu, libelleFiliereCHAR, VARCHAR (lettres)
NNumériqueChiffres, virgule, signenoteEtu, dureeForm, nbrePlacesINT, DECIMAL, FLOAT
ANAlphanumériqueLettres ET chiffres mélangésnumCINEtu, codeForm, codeSessVARCHAR, CHAR
DDateDate, heure ou date+heuredateNaissEtu, dateDebutSess, dateFinDATE, DATETIME, TIMESTAMP
BBooléenVrai/Faux, Oui/Non, 0/1actifFormateur, certifiantFormBOOLEAN, TINYINT(1)
ℹ Convention de nommage objetConcept

La convention Merise : abréviation de la propriété + abréviation de l'entité, en camelCase. Exemples : numCINEtu = numéro CIN + Etudiant, titreForm = titre + Formation, dateDebutSess = date de début + Session. Cette convention évite les ambigüités quand plusieurs entités ont des propriétés au même nom (ex : nomEtu vs nomForm).


3
Contrôles qualité du DD
Polysémies · Synonymes · Données calculées · Imprécisions
ProblèmeDéfinitionExemple à corrigerSolution
PolysémieUn même mot désigne des choses différentes selon le contexte« nom » peut être nom étudiant, nom formateur ou nom formationRenommer : nomEtu, nomFormateur, titreForm
SynonymesDeux mots différents désignent la même chose« élève » et « apprenant » et « étudiant » dans le même CDCChoisir un seul terme : nomEtu partout
Donnée calculéeValeur déductible depuis d'autres données — à exclure du DD« âge étudiant » = YEAR(NOW()) - YEAR(dateNaissEtu)Conserver dateNaissEtu, calculer l'âge à la demande avec SQL
ImprécisionDonnée trop vague pour être modélisée« coordonnées » — téléphone ? email ? adresse ?Décomposer : telEtu, emailEtu, adresseEtu

4
DD complet SkolaBase — 16 données
Toutes les entités · Convention respectée · Types et tailles
CodeDésignationTypeTailleObservationsEntité
numCINEtuNuméro CIN de l'étudiantAN8Identifiant unique, format : lettre+7 chiffresETUDIANT
nomEtuNom de famille de l'étudiantA50Obligatoire, majusculesETUDIANT
prenomEtuPrénom de l'étudiantA50ObligatoireETUDIANT
dateNaissEtuDate de naissance de l'étudiantD—Format JJ/MM/AAAA, âge calculé à la demandeETUDIANT
villeEtuVille de résidence de l'étudiantA50Villes marocainesETUDIANT
telEtuTéléphone de l'étudiantAN15Format marocain 06/07XXXXXXXX, nullableETUDIANT
numFormateurIdentifiant du formateurN4Clé primaire auto-incrémentéeFORMATEUR
nomFormateurNom du formateurA50ObligatoireFORMATEUR
specialiteFormSpécialité principale du formateurA80NullableFORMATEUR
codeSessCode de la sessionAN10Format : SESS-AAAA-NN (ex: SESS-2024-01)SESSION
dateDebutSessDate de début de la sessionD—ObligatoireSESSION
dateFinSessDate de fin de la sessionD—Doit être > dateDebutSessSESSION
lieuSessLieu de déroulement de la sessionAN100Salle + villeSESSION
codeFormCode de la formationAN10Clé primaire, uniqueFORMATION
titreFormIntitulé de la formationAN100ObligatoireFORMATION
dureeFormDurée de la formation en heuresN3Entier positif, ex: 120FORMATION
niveauFormNiveau requis pour la formationA20Valeurs : Bac, Bac+2, Bac+3, TechnicienFORMATION
codeFiliereCode de la filièreAN6Clé primaire, ex: INF, GES, ELEFILIERE
libelleFiliereLibellé complet de la filièreA80Ex: Informatique, Gestion, ÉlectroniqueFILIERE
noteInscriptionNote obtenue à la sessionN4,2Entre 0 et 20 — attribut de l'association INSCRIPTIONINSCRIPTION
Un stagiaire propose d'ajouter agEtu (âge de l'étudiant) dans le DD. Que lui répondre ?
Le CDC utilise « apprenant » dans une section et « étudiant » dans une autre pour désigner la même personne. Quel problème cela pose-t-il dans le DD ?
Partie 2 — Modélisation Merise Dépendances fonctionnelles Directes · Transitives · Composées
⏱ 18 min

Dépendances fonctionnelles

Définition d'une DF (A→B), DF directes vs transitives vs composées (A+B→C), méthode de construction du graphe des DF, et graphe complet de SkolaBase prét pour dériver le MCD.

✓ Ce que vous allez apprendre
  • Définir une DF : A→B signifie « connaissant A, on connaît un seul B »
  • Distinguer DF directe, DF transitive (à éliminer) et DF composée
  • Construire le graphe des DF à partir du DD et des RG
  • Identifier les sources des DF — elles deviendront les identifiants des entités

1
Définition d'une Dépendance Fonctionnelle
A→B · Déterminant · Dépendant · Exemples et contre-exemples
ℹ Définition formelle

On dit que la donnée A détermine fonctionnellement B (noté A→B) si, pour toute valeur de A, il existe au plus une valeur de B. A est le déterminant, B est le dépendant. En clair : connaissant A, on peut retrouver exactement un B — jamais plusieurs.

DFLectureValide ?Justification
numCINEtu → nomEtuConnaissant le CIN, on connaît un seul nomOuiChaque CIN est unique — un étudiant = un seul nom
numCINEtu → dateNaissEtuConnaissant le CIN, on connaît une seule date de naissanceOuiUn étudiant a une seule date de naissance
nomEtu → numCINEtuConnaissant le nom, on connaît un seul CINNonPlusieurs étudiants peuvent avoir le même nom (Alaoui)
codeSess → dateDebutSessConnaissant le code session, on connaît une seule date de débutOuiUne session a une seule date de début
codeForm → codeFiliereConnaissant le code formation, on connaît une seule filièreOuiUne formation appartient à une seule filière (RG4)

2
Types de DF — directes, transitives et composées
DF directe · Transitivité à éliminer · DF composée A+B→C
⚠ DF transitive — à éliminer du graphe

Si D1→D2 et D2→D3, alors D1→D3 est une DF transitive (elle est déductible, pas directe). On ne la conserve pas dans le graphe des DF — elle serait redondante et fausserait le MCD. Exemple : codeForm→codeFiliere et codeFiliere→libelleFiliere → donc codeForm→libelleFiliere est transitive et ne figure pas dans le graphe.

TypeDéfinitionExemple SkolaBaseGarder dans graphe ?
DF directeA détermine B sans intermédiairenumCINEtu → nomEtuOui
DF transitiveA→B→C : A détermine C via BcodeForm → libelleFiliere (via codeFiliere)Non — redondante
DF composéeA+B détermine C (deux déterminants)numCINEtu + codeSess → noteInscriptionOui — clé composée
ℹ Signification de la DF composée numCINEtu + codeSess → noteInscription

Connaissant à la fois le CIN de l'étudiant ET le code de la session, on peut retrouver une seule note. En effet, un même étudiant peut avoir plusieurs notes (une par session) et une même session a plusieurs notes (une par étudiant inscrit). Seule la combinaison des deux détermine une note unique.


3
Graphe des DF — SkolaBase complet
Lecture du graphe · Sources = futurs identifiants · Prêt pour MCD
textGraphe des DF SkolaBase — DF directes uniquement
                      ┌─────── nomEtu
                      ├─────── prenomEtu
numCINEtu ─────────┼─────── dateNaissEtu
                      ├─────── villeEtu
                      └─────── telEtu

                      ┌─────── nomFormateur
numFormateur ──────┼─────── specialiteForm
                      └─────── numFormateur ──────→ codeSess (via RG2)

                      ┌─────── dateDebutSess
                      ├─────── dateFinSess
codeSess ───────────┼─────── lieuSess
                      ├─────── codeForm (via RG3)
                      └─────── numFormateur (via RG2)

                      ┌─────── titreForm
                      ├─────── dureeForm
codeForm ───────────┼─────── niveauForm
                      └─────── codeFiliere (via RG4)

codeFiliere ────────────→ libelleFiliere

DF composée :
numCINEtu + codeSess ────────→ noteInscription

Sources identifiées (futurs identifiants des entités) :
  numCINEtu    → entité ETUDIANT
  numFormateur → entité FORMATEUR
  codeSess     → entité SESSION
  codeForm     → entité FORMATION
  codeFiliere  → entité FILIERE
codeForm → libelleFiliere : est-ce une DF directe à inclure dans le graphe ?
Partie 2 — Modélisation Merise MCD — Entités & Merise 3 niveaux · 5 règles
⏱ 20 min

MCD — Entités & méthode Merise

Présentation de Merise et ses 3 niveaux (MCD/MLD/MPD), définition d'une entité (identifiant, attributs, occurrences, formalisation), et les 5 règles de passage Graphe DF→MCD avec application des règles R1 et R2 sur SkolaBase.

✓ Ce que vous allez apprendre
  • Merise : historique, 3 niveaux (MCD, MLD, MPD) et leur rôle respectif
  • Entité : définition, identifiant, attributs, occurrences, formalisme graphique
  • Les 5 règles de passage Graphe DF → MCD
  • Application de R1 (donnée = propriété) et R2 (source DF = identifiant) sur SkolaBase

1
Merise — présentation et 3 niveaux
MCD · MLD · MPD · Indépendance · Historique
ℹ Merise — origine et principe

Merise est une méthode française de conception des systèmes d'information, développée dans les années 1970 par le ministère de l'Industrie et Hubert Tardieu. Très utilisée en France et dans les pays francophones (dont le Maroc). Son principe central : séparer la démarche (quoi concevoir) de la technologie (comment implémenter).

NiveauModèleQuestionDépendance SGBDSkolaBase
ConceptuelMCD — Modèle Conceptuel de DonnéesQuoi représenter ?Non — universelEntités + associations + cardinalités
LogiqueMLD — Modèle Logique de DonnéesComment organiser ?Type SGBDR uniquementTables + clés primaires + clés étrangères
PhysiqueMPD — Modèle Physique de DonnéesComment stocker ?Oui — MySQL spécifiqueSQL CREATE TABLE, types MySQL, index

2
Entité — définition et formalisme graphique
Identifiant · Attributs · Occurrences · Rectangle
ℹ Définition d'une entité

Une entité est un objet réel ou abstrait du domaine étudié, sur lequel on souhaite stocker des informations, et qui peut être identifié de manière unique. Elle correspond à une future table SQL.

textFormalisme graphique d'une entité Merise — ETUDIANT
┌───────────────────┐
│     ETUDIANT         │  ←  Nom de l'entité (en majuscules)
├───────────────────┤
│ #numCINEtu          │  ←  Identifiant (souligné, précédé de #)
├───────────────────┤
│  nomEtu             │
│  prenomEtu          │  ←  Attributs (propriétés)
│  dateNaissEtu       │
│  villeEtu           │
└───────────────────┘

Occurrence (instance) : une ligne dans la future table
  Ex : { numCINEtu:'A123456', nomEtu:'Alaoui', prenomEtu:'Karim', ... }
ÉlémentDéfinitionPropriétés
IdentifiantAttribut(s) qui distingue une occurrence de toutes les autresUnique, obligatoire, stable, non NULL — deviendra la clé primaire (PK)
AttributsPropriétés qui décrivent l'entitéAtomiques (une seule valeur), non calculés, du DD
OccurrenceValeurs concrètes pour une instance de l'entitéUne occurrence = une ligne dans la table SQL

3
Les 5 règles de passage Graphe DF → MCD
R1 · R2 · R3 · R4 · R5
RègleÉnoncéApplication SkolaBase
R1Toute donnée du graphe (non source) devient une propriété d'entiténomEtu, prenomEtu, dateNaissEtu → attributs de ETUDIANT
R2Toute source d'une DF devient l'identifiant d'une entiténumCINEtu → identifiant de ETUDIANT ; codeSess → identifiant de SESSION
R3Une DF entre deux sources (A→B avec A et B sources) devient une association non porteuse (CIF — Contrainte d'Intégrité Fonctionnelle)codeSess→codeForm (SESSION porte sur FORMATION) → association non porteuse
R4Une source issue d'une DF composée (A+B→C) devient une association porteuse (CIM — Contrainte d'Intégrité Multiple)numCINEtu+codeSess→noteInscription → association INSCRIPTION porteuse de note
R5Une association entre entités qui n'apparaît pas dans le graphe DF (trouvée dans les RG) devient une association hors graphe (CIM ou CIF)RG2 : FORMATEUR anime SESSION → association hors graphe (non déductible du graphe DF seul)
textApplication R1+R2 — SkolaBase : dériver les entités depuis le graphe DF
Depuis le graphe DF, on identifie les sources (R2) :
  numCINEtu   → Entité ETUDIANT
     Attributs (R1) : nomEtu, prenomEtu, dateNaissEtu, villeEtu, telEtu

  numFormateur → Entité FORMATEUR
     Attributs (R1) : nomFormateur, specialiteForm

  codeSess    → Entité SESSION
     Attributs (R1) : dateDebutSess, dateFinSess, lieuSess

  codeForm    → Entité FORMATION
     Attributs (R1) : titreForm, dureeForm, niveauForm

  codeFiliere → Entité FILIERE
     Attributs (R1) : libelleFiliere

  Donnée composée (R4) :
  numCINEtu + codeSess → noteInscription
     → Association INSCRIPTION porteuse de noteInscription
Dans le graphe DF, codeSess → codeForm — quelle règle Merise s'applique et quel élément du MCD cela génère ?
Partie 2 — Modélisation Merise MCD — Associations Cardinalités · R3 R4 R5 · MCD complet
⏱ 22 min

MCD — Associations & Cardinalités

Définir et représenter les associations (binaires, ternaires, porteuses), maîtriser les 4 types de cardinalités (0,1 / 1,1 / 0,N / 1,N), les déduire des RG, appliquer R3/R4/R5, et construire le MCD complet de SkolaBase.

✓ Ce que vous allez apprendre
  • Définir une association et ses types (binaire, ternaire, porteuse)
  • Lire et déduire les cardinalités depuis les RG
  • Comprendre les 4 types : (0,1) / (1,1) / (0,N) / (1,N)
  • Appliquer R3 (association non porteuse), R4 (porteuse), R5 (hors graphe)
  • Dessiner et lire le MCD complet de SkolaBase

1
Définition et types d'associations
Binaire · Ternaire · Porteuse · Formalisme graphique
ℹ Définition d'une association

Une association (ou relation en Merise) représente un lien sémantique entre deux ou plusieurs entités. Elle traduit une RG du CDC. Dans le formalisme graphique, elle est représentée par un losange avec le nom du verbe qui la décrit.

textFormalisme graphique des associations Merise
Association binaire (entre 2 entités) :
  ETUDIANT ─(0,N)─◆ s'inscrit ◆─(1,N)─ SESSION

Association porteuse (avec attribut) :
  ETUDIANT ─(0,N)─◆ INSCRIPTION ◆─(1,N)─ SESSION
                     noteInscription  ← attribut de l'association

Association ternaire (entre 3 entités) :
                  SALLE
                    |
  FORMATEUR ─◆ TIENT ◆─ SESSION
  (rare — éviter si possible)
TypeDéfinitionExemple SkolaBase
BinaireRelie exactement 2 entitésFORMATION appartient à FILIERE
TernaireRelie 3 entités simultanémentRare dans SkolaBase — à éviter
PorteuseAssociation avec au moins un attribut propre (CIM)INSCRIPTION entre ETUDIANT et SESSION, porte noteInscription
Non porteuseAssociation sans attribut propre (CIF)SESSION porte sur FORMATION (pas d'attribut sur le lien)

2
Cardinalités — lecture et déduction depuis les RG
Min / Max · 0,1 / 1,1 / 0,N / 1,N · Questions à poser
ℹ Comment lire une cardinalité (x,y)

La cardinalité (min, max) se lit : « une occurrence de cette entité est liée à minimum min et maximum max occurrences de l'autre entité ». Pour la déduire : poser deux questions à partir de la RG.

CardinalitéMinMaxSignificationExemple SkolaBase
(0,1)Facultatif1 seulAu plus un lien, pas obligéUn formateur peut être affecté à 0 ou 1 service
(1,1)Obligatoire1 seulExactement un lien, ni plus ni moinsUne session est animée par exactement 1 formateur
(0,N)FacultatifPlusieursZéro ou plusieurs liens possiblesUn étudiant peut s'inscrire à 0 ou plusieurs sessions
(1,N)ObligatoirePlusieursAu moins un lien, plusieurs possiblesUne formation a au moins 1 session
textMéthode — déduire les cardinalités depuis RG1
RG1 : « Un étudiant peut s'inscrire à plusieurs sessions.
       Un étudiant ne s'inscrit pas forcément à une session (nouveau inscrit). »

Question 1 (du côté ETUDIANT) :
  « Un ETUDIANT est lié à COMBIEN de SESSION ? »
  Réponse : minimum 0 (pas obligé), maximum N (plusieurs) → cardinalité ETUDIANT = (0,N)

Question 2 (du côté SESSION) :
  « Une SESSION est liée à COMBIEN d'ETUDIANT ? »
  Réponse : minimum 1 (une session a au moins 1 étudiant), maximum N → cardinalité SESSION = (1,N)

Représentation :
  ETUDIANT (0,N) ◆ INSCRIPTION ◆ (1,N) SESSION

3
MCD complet SkolaBase
5 entités · 4 associations · Toutes les cardinalités
textMCD complet SkolaBase — Merise
┌──────────────┐                           ┌───────────────┐
│   ETUDIANT    │                           │   FORMATEUR   │
├──────────────┤                           ├───────────────┤
│ #numCINEtu    │                           │ #numFormateur │
│  nomEtu       │                           │  nomFormateur │
│  prenomEtu    │                           │  specialite   │
│  dateNaissEtu │                           └───────────────┘
│  villeEtu     │                                    |
└──────────────┘                               (0,N)
       |                                          |
     (0,N)                              ◆──── ANIME ────◆
       |                                          |
◆─ INSCRIPTION ─◆                             (1,1)
  noteInscription                                 |
       |                           ┌──────────────┐
     (1,N)                         │   SESSION    │
       |                           ├──────────────┤
       └─────────────────────────┤ #codeSess    │
                                   │  dateDebut   │
                                   │  dateFin     │
                                   │  lieu        │
                                   └──────────────┘
                                           |
                                         (1,N)
                                           |
                              ◆── PORTE SUR ──◆
                                           |
                                         (1,1)
                                           |
                           ┌──────────────┐
                           │  FORMATION  │
                           ├──────────────┤
                           │ #codeForm   │
                           │  titreForm  │
                           │  dureeForm  │
                           │  niveauForm │
                           └──────────────┘
                                   |
                                 (1,N)
                                   |
                      ◆── APPARTIENT A ──◆
                                   |
                                 (1,1)
                                   |
                       ┌──────────────┐
                       │   FILIERE    │
                       ├──────────────┤
                       │ #codeFiliere │
                       │  libelleFiliere│
                       └──────────────┘
Dans le MCD SkolaBase, l'association INSCRIPTION est « porteuse ». Que signifie cette qualification ?
Partie 2 — Modélisation Merise Formes normales 1FN · 2FN · 3FN · FNBC
⏱ 18 min

Formes normales

Rôle de la normalisation, 1FN (atomicité), 2FN (dépendance à la totalité de la clé), 3FN (dépendance directe à la clé), FNBC et 4FN — avec contre-exemples et corrections sur le cas SkolaBase.

✓ Ce que vous allez apprendre
  • Pourquoi normaliser : éviter redondances, anomalies de mise à jour et incohérences
  • 1FN : tout attribut doit être atomique et mono-valué
  • 2FN : chaque attribut non-clé dépend de la totalité de la clé primaire
  • 3FN : chaque attribut non-clé dépend directement de la clé (pas transitivement)
  • FNBC : seules les DF dont le déterminant est une clé candidate

1
Pourquoi normaliser ?
Redondance · Anomalies · Cohérence
ℹ Problèmes sans normalisation

Une table non normalisée entraîne trois types d'anomalies : anomalie d'insertion (impossible d'insérer une formation sans session), anomalie de mise à jour (changer le titre d'une formation oblige à modifier N lignes), anomalie de suppression (supprimer la dernière session supprime aussi la formation). La normalisation élimine ces problèmes.

textTable non normalisée — problèmes visibles
Table INSCRIPTION_BRUTE (non normalisée) :
numCINEtu | nomEtu  | codeSess | titreForm        | libelleFiliere | note
----------|---------|----------|------------------|----------------|-----
A123456   | Alaoui  | SESS-01  | Dév. Web        | Informatique   | 14
A123456   | Alaoui  | SESS-02  | Comptabilité    | Gestion        | 16
B789012   | Bennani | SESS-01  | Dév. Web        | Informatique   | 12

Problèmes :
✕ nomEtu répété pour chaque session → redondance
✕ Si "Dév. Web" change en "Développement Web" → modifier 2 lignes
✕ Si Alaoui se désinscrit de SESS-01 → on perd que SESS-01 existe
✕ Si SESS-01 a 0 inscrits → impossible de stocker la session

2
1FN — Première Forme Normale
Atomicité · Mono-valué · Pas de groupes répétitifs
ℹ Règle 1FN

Une table est en 1FN si et seulement si tous ses attributs sont atomiques (une seule valeur par cellule) et mono-valués (pas de liste de valeurs dans une cellule).

SituationExemple non-1FNCorrection en 1FN
Plusieurs prénoms dans une celluleprenomEtu = "Karim, Mohamed"Un seul prénom par ligne, ou table séparée PRENOM
Groupe répétitif dans une lignenote1, note2, note3 dans la même tableChaque note sur une ligne distincte avec codeSess
Donnée compositeadresse = "14 Rue Hassan II, Casablanca"Deux attributs : rueEtu + villeEtu
⚠ SkolaBase — vérification 1FN

Notre DD est en 1FN : chaque attribut est atomique (nomEtu = un seul nom, dateDebutSess = une seule date...). Si le CDC avait dit « liste des prénoms », il aurait fallu créer une table PRENOM séparée.


3
2FN — Deuxième Forme Normale
Dépendance totale · Clé composée · Violation typique
ℹ Règle 2FN

Une table en 1FN est en 2FN si tout attribut non-clé dépend de la totalité de la clé primaire. La 2FN ne concerne que les tables à clé composée — une table avec une clé simple et en 1FN est automatiquement en 2FN.

textViolation 2FN — table INSCRIPTION avec dépendance partielle
Table INSCRIPTION (CLÉ : numCINEtu + codeSess) — non 2FN :
numCINEtu | codeSess | noteInscription | nomEtu  | dateDebutSess
A123456   | SESS-01  | 14              | Alaoui  | 2024-09-01

Problème :
  numCINEtu → nomEtu      (dépend de PARTIE de la clé → violation 2FN)
  codeSess  → dateDebutSess (dépend de PARTIE de la clé → violation 2FN)
  numCINEtu + codeSess → noteInscription (dépend de TOUTE la clé → OK)

Correction — décomposer en 3 tables :
  ETUDIANT(numCINEtu, nomEtu, ...)
  SESSION(codeSess, dateDebutSess, ...)
  INSCRIPTION(numCINEtu, codeSess, noteInscription)

4
3FN & FNBC — Troisième Forme Normale
Dépendance directe · Pas de transitivité · FNBC
ℹ Règle 3FN

Une table en 2FN est en 3FN si aucun attribut non-clé ne dépend transitivement de la clé primaire. En clair : un attribut non-clé ne doit pas déterminer un autre attribut non-clé.

textViolation 3FN — table FORMATION avec transitivité
Table FORMATION (non 3FN) :
codeForm | titreForm   | dureeForm | codeFiliere | libelleFiliere
DEV01    | Dév. Web   | 120       | INF         | Informatique
CPT01    | Comptabilité| 80        | GES         | Gestion

Problème :
  codeForm → codeFiliere     (OK — codeFiliere dépend de la clé)
  codeFiliere → libelleFiliere (VIOLATION — un non-clé détermine un autre non-clé)
  Donc : codeForm → codeFiliere → libelleFiliere (transitivité)

Correction — décomposer en 2 tables :
  FORMATION(codeForm, titreForm, dureeForm, codeFiliere)
  FILIERE(codeFiliere, libelleFiliere)
Forme normaleConditionProblème évité
1FNAttributs atomiques et mono-valuésValeurs multiples dans une cellule
2FN1FN + dépendance totale à la cléDépendance partielle (clé composée)
3FN2FN + pas de transitivitéNon-clé détermine non-clé
FNBC3FN + tout déterminant est une clé candidateDF élémentaires seules
4FNFNBC + pas de dépendances multivaluées indépendantesAttributs multivalués indépendants
La table SESSION(codeSess, dateDebut, dateFin, codeForm, titreForm) viole quelle forme normale ?
Partie 2 — Modélisation Merise MLD 4 règles · Clés étrangères · Tables
⏱ 20 min

MLD — Passage MCD→MLD

Les 4 règles de passage MCD→MLD : R1 (entité → table), R2 (cardinalité 1,1 : clé migrée), R3 (cardinalité N,N : table pivot), R4 (ternaire), entité forte/faible, cas particuliers, MLD complet SkolaBase.

✓ Ce que vous allez apprendre
  • R1 : toute entité devient une table, l'identifiant devient la clé primaire (PK)
  • R2 : association avec cardinalité maximale 1 d'un côté → clé étrangère (FK) migre vers la table « côté 1 »
  • R3 : association avec cardinalités N,N des deux côtés → nouvelle table pivot à clé composée
  • R4 : association ternaire → table avec les clés étrangères comme clé primaire
  • Appliquer les 4 règles sur le MCD SkolaBase → MLD complet

1
R1 — Entité → Table
Entité → Table · Identifiant → PK · Attributs → Colonnes
ℹ Règle R1

Toute entité du MCD devient une table dans le MLD. Son identifiant devient la clé primaire (PK). Ses attributs deviennent les colonnes. Notation MLD : NOM_TABLE(cle_primaire, col1, col2, ...)

textApplication R1 — SkolaBase : 5 entités → 5 tables
ETUDIANT  (#numCINEtu, nomEtu, prenomEtu, dateNaissEtu, villeEtu, telEtu)
FORMATEUR (#numFormateur, nomFormateur, specialiteForm)
SESSION   (#codeSess, dateDebutSess, dateFinSess, lieuSess)
FORMATION (#codeForm, titreForm, dureeForm, niveauForm)
FILIERE   (#codeFiliere, libelleFiliere)

2
R2 — Association avec cardinalité max = 1
Côté (x,1) → reçoit la FK · Entité forte/faible
ℹ Règle R2

Quand une association possède une cardinalité maximale 1 d'un côté — notation (x,1) — la table du côté «1» reçoit la clé primaire de l'autre table comme clé étrangère (FK). Pas de nouvelle table créée.

textApplication R2 — SkolaBase
Association ANIME : FORMATEUR (0,N) ◆────◆ (1,1) SESSION
  → Côté SESSION a cardinalité max = 1
  → SESSION reçoit la FK de FORMATEUR : numFormateur
  SESSION (#codeSess, dateDebutSess, dateFinSess, lieuSess, #numFormateur FK)

Association PORTE SUR : SESSION (1,N) ◆────◆ (1,1) FORMATION
  → Côté FORMATION a cardinalité max = 1 ? Non !
  Attention : la SESSION a cardinalité (1,1) du côté FORMATION
  → C'est SESSION qui a max=1 vis-à-vis de FORMATION
  → SESSION reçoit la FK de FORMATION : codeForm
  SESSION (#codeSess, dateDebutSess, dateFinSess, lieuSess, #numFormateur FK, #codeForm FK)

Association APPARTIENT A : FORMATION (1,N) ◆────◆ (1,1) FILIERE
  → FORMATION a cardinalité max = 1 vis-à-vis de FILIERE
  → FORMATION reçoit la FK de FILIERE : codeFiliere
  FORMATION (#codeForm, titreForm, dureeForm, niveauForm, #codeFiliere FK)

3
R3 — Association N,N → table pivot
Clé composée · Table pivot · Attributs portés
ℹ Règle R3

Quand les deux côtés d'une association ont une cardinalité maximale N — (x,N) des deux côtés — l'association devient une nouvelle table (table pivot) dont la clé primaire est composée des clés primaires des deux entités. Les attributs portés de l'association deviennent des colonnes de cette table pivot.

textApplication R3 — Association INSCRIPTION (N,N porteuse)
Association INSCRIPTION : ETUDIANT (0,N) ◆ INSCRIPTION ◆ (1,N) SESSION
  → Les deux côtés ont cardinalité max = N
  → Créer une table pivot INSCRIPTION
  → Clé composée : (numCINEtu + codeSess)
  → Attribut porté noteInscription devient colonne

  INSCRIPTION (#numCINEtu FK, #codeSess FK, noteInscription)

4
MLD complet SkolaBase
6 tables · FK · Notation standard
textMLD complet SkolaBase — notation Merise
Notation : #champ = clé primaire (PK) | *champ = clé étrangère (FK)

FILIERE   (#codeFiliere, libelleFiliere)

FORMATION (#codeForm, titreForm, dureeForm, niveauForm,
           *codeFiliere → FILIERE.codeFiliere)

FORMATEUR (#numFormateur, nomFormateur, specialiteForm)

SESSION   (#codeSess, dateDebutSess, dateFinSess, lieuSess,
           *numFormateur → FORMATEUR.numFormateur,
           *codeForm     → FORMATION.codeForm)

ETUDIANT  (#numCINEtu, nomEtu, prenomEtu, dateNaissEtu,
           villeEtu, telEtu)

INSCRIPTION (#numCINEtu → ETUDIANT.numCINEtu,
             #codeSess  → SESSION.codeSess,
             noteInscription)
             CLÉ PRIMAIRE : (numCINEtu, codeSess)
textSchéma des dépendances entre tables
FILIERE ───────▶ FORMATION ──────▶ SESSION ◄────── FORMATEUR
                                       ┃
                                  INSCRIPTION
                                       ┃
                                   ETUDIANT
Dans le MLD SkolaBase, pourquoi la table INSCRIPTION a-t-elle une clé primaire composée de (numCINEtu, codeSess) plutôt qu'un identifiant simple ?
Partie 2 — Modélisation Merise Synthèse Merise CDC → MCD → MLD · Cas complet
⏱ 20 min

Synthèse Merise

Récapitulatif visuel de la démarche complète CDC → RG → DD → Graphe DF → MCD → MLD, exercice de synthèse sur un cas inédit (bibliothèque), et tableau récapitulatif de tous les outils Merise.

✓ Ce que vous allez consolider
  • La démarche complète en 6 étapes : CDC → RG → DD → Graphe DF → MCD → MLD
  • Les outils de chaque étape et leurs résultats
  • Les pièges à éviter à chaque étape
  • Application sur un cas inédit — bibliothèque municipale

1
Démarche complète en 6 étapes
CDC → RG → DD → DF → MCD → MLD
textPipeline Merise complet — SkolaBase
┌──────────────────────────────────────────────────────────────────────────────┐
│ ① CDC           │ ② RG           │ ③ DD           │ ④ GRAPHE DF    │
├────────────────────┤ ├────────────────────┤ ├────────────────────┤ ├────────────────────┤
│ Périmètre        │ RG1, RG2...   │ Code/Type/   │ Sources =    │
│ Entités cand.   │ Verbes+quant.│ Taille/Obs.  │ identifiants │
│ Limites         │ Cardinalités │ objetConcept │ DF directes  │
│                 │ initiales     │ Contrôles    │ pas transitiv│
└────────────────────┘ └────────────────────┘ └────────────────────┘ └────────────────────┘
        │                     │                     │                     │
        ▼                     ▼                     ▼                     ▼
┌────────────────────────────────────────────┐
│ ⑤ MCD                          │ ⑥ MLD                          │
├────────────────────────────────────────────┤
│ Entités + attributs (R1+R2)  │ Tables + clés PK (R1)         │
│ Associations + cardinalités   │ FK migrées (R2, cardmax=1)    │
│ R3 (porteuse), R4 (non-port.) │ Tables pivot (R3, N,N)         │
│ R5 (hors graphe)              │ Normalisation vérifiée         │
└────────────────────────────────────────────┘
ÉtapeOutilInputOutputPiège principal
1. CDCEntretiens, analyseBesoins clientDocument texte structuréOublier de fixer le périmètre
2. RGLecture CDC, soulignageCDCTableau RGnConfondre RG métier et contrainte technique
3. DDStructure 5 colonnesCDC + RGDictionnaire de donnéesInclure des données calculées ou des synonymes
4. Graphe DFAnalyse DF directesDD + RGGraphe orientéGarder les DF transitives
5. MCDRègles R1→R5Graphe DF + RGEntités + AssociationsOublier les cardinalités ou les attributs portés
6. MLDRègles MLD R1→R4MCDTables + FKConfondre R2 (card max=1) et R3 (N,N)

2
Exercice de synthèse — Bibliothèque municipale
Cas inédit · CDC → MLD complet
textCDC Bibliothèque — énoncé complet
CDC — Bibliothèque Municipale de Rabat

« La bibliothèque gère des ADHERENTS identifiés par un numéro unique.
   Elle possède un catalogue de LIVRES, chaque livre identifié par son ISBN.
   Un livre peut exister en plusieurs EXEMPLAIRES physiques (un numéro par exemplaire).
   Un adhérent peut emprunter plusieurs exemplaires simultanément.
   Un exemplaire ne peut être emprunté que par un seul adhérent à la fois.
   Chaque emprunt a une date de début et une date de retour prévue.
   Chaque livre appartient à une seule CATEGORIE (Roman, Sciences, Histoire...).
   Un auteur peut avoir écrit plusieurs livres, et un livre peut avoir plusieurs AUTEURS. »

Travail demandé :
  1. Identifier les entités candidates
  2. Rédiger les RG (RG1 à RG5)
  3. Construire le DD (colonnes essentielles)
  4. Dessiner le graphe des DF
  5. Dessiner le MCD avec les cardinalités
  6. Déduire le MLD
textCorrigé — Bibliothèque : RG + MLD
ENTITES : ADHERENT, LIVRE, EXEMPLAIRE, CATEGORIE, AUTEUR

REGLES DE GESTION :
  RG1 : Un adhérent peut emprunter 0 ou plusieurs exemplaires. Un exemplaire est
        emprunté par 0 ou 1 adhérent à la fois.
  RG2 : Un livre possède 1 ou plusieurs exemplaires. Un exemplaire appartient à 1 seul livre.
  RG3 : Un livre appartient à 1 seule catégorie. Une catégorie regroupe 0 ou plusieurs livres.
  RG4 : Un livre a 1 ou plusieurs auteurs. Un auteur a écrit 0 ou plusieurs livres.

MCD :
  ADHERENT (0,N) ◆ EMPRUNT (date_debut, date_retour_prevue) ◆ (0,1) EXEMPLAIRE
  EXEMPLAIRE (1,N) ◆ POSSEDE ◆ (1,1) LIVRE
  LIVRE (1,N) ◆ APPARTIENT ◆ (1,1) CATEGORIE
  LIVRE (0,N) ◆ REDIGE ◆ (1,N) AUTEUR

MLD (6 tables) :
  CATEGORIE(#codeCateg, libelleCateg)
  AUTEUR(#idAuteur, nomAuteur, prenomAuteur)
  LIVRE(#isbn, titreL, anneePubli, *codeCateg FK)
  LIVRE_AUTEUR(#isbn FK, #idAuteur FK)           ← R3 (N,N)
  EXEMPLAIRE(#numExemp, etat, *isbn FK)
  EMPRUNT(#idAdherent FK, #numExemp FK, dateDebut, dateRetourPrevue)
  ADHERENT(#idAdherent, nomAdh, prenomAdh, emailAdh)
Dans la bibliothèque, l'association REDIGE entre LIVRE et AUTEUR est (0,N)─(1,N). Comment se traduit-elle dans le MLD ?
L'association EMPRUNT est porteuse (date_debut, date_retour_prevue). ADHERENT (0,N) ◆ EMPRUNT ◆ (0,1) EXEMPLAIRE. Quelle règle MLD s'applique ?
Partie 3 — Workbench & Modélisation graphique MySQL Workbench Installation · Interface · Fonctionnalités
⏱ 14 min

MySQL Workbench — Installation & Interface

Présentation de MySQL Workbench, ses 6 fonctionnalités principales, installation en 6 étapes sur Windows, découverte de l'interface d'accueil (3 modules) et configuration d'une connexion locale vers MySQL Server.

✓ Ce que vous allez apprendre
  • Définir MySQL Workbench et le distinguer de MySQL Server
  • Connaître les 6 fonctionnalités : connexion, modélisation EER, SQL, migration, reverse engineering, administration
  • Installer Workbench en 6 étapes sur Windows
  • Naviguer dans les 3 modules de l'interface d'accueil
  • Configurer et tester une connexion locale (localhost:3306)

1
MySQL Workbench — définition et fonctionnalités
GUI · EER · SQL Editor · Reverse Engineering
ℹ Workbench vs MySQL Server — ne pas confondre

MySQL Server est le moteur de base de données — il stocke, traite et répond aux requêtes SQL. C'est un service qui tourne en arrière-plan. MySQL Workbench est l'interface graphique (GUI) qui permet d'interagir avec MySQL Server sans ligne de commande — dessiner des modèles, écrire des requêtes, gérer les utilisateurs. Workbench sans Server = voiture sans moteur.

#FonctionnalitéDescriptionUsage SkolaBase
1SQL EditorÉcrire, exécuter et analyser des requêtes SQLCréer les tables, insérer les données, lancer les requêtes
2Modélisation EERDessiner le schéma graphique des tables et relationsTraduire le MLD SkolaBase en diagramme visuel
3Reverse EngineeringGénérer le diagramme EER depuis une BDD existanteVisualiser une BDD importée automatiquement
4Forward EngineeringGénérer le script SQL CREATE TABLE depuis le modèle EERExporter le diagramme SkolaBase en SQL prêt à exécuter
5AdministrationGérer utilisateurs, privilèges, sauvegardesCréer l'utilisateur skolabase_user
6Import/ExportImporter un fichier SQL ou exporter une BDDImporter un dump .sql, exporter un CSV

2
Installation de MySQL Workbench — 6 étapes
mysql.com · MySQL Installer · Windows · Configuration
textProcédure d'installation MySQL Workbench — Windows
① Télécharger MySQL Installer
     URL : https://dev.mysql.com/downloads/installer/
     Choisir : "MySQL Installer for Windows" (mysql-installer-community-x.x.x.msi)
     Taille : ~450 Mo (community = version gratuite)

② Lancer l'installeur en tant qu'Administrateur
     Clic droit sur le .msi → "Exécuter en tant qu'administrateur"

③ Choisir le type d'installation
     Sélectionner "Custom" pour choisir les composants
     Cocher : MySQL Server 8.0 + MySQL Workbench 8.0
     (Éviter "Full" — installe des composants inutiles)

④ Configurer MySQL Server
     Port : 3306 (laisser par défaut)
     Root password : choisir un mot de passe FORT (noter le !)
     Windows Service : cocher "Start at system startup"

⑤ Exécuter l'installation
     Cliquer "Execute" → attendre la fin de l'installation des deux composants

⑥ Vérifier l'installation
     Démarrer MySQL Workbench → l'interface d'accueil doit s'ouvrir
     Dans la liste des connexions : "Local instance MySQL80" doit apparaître
⚠ Pièges courants à l'installation

Oublier le mot de passe root : impossible de se connecter. Solution : noter le mot de passe dans un endroit sûr immédiatement. Port 3306 déjà utilisé : une autre instance MySQL tourne déjà. Vérifier dans Services Windows (services.msc) et arrêter l'ancienne instance. Antivirus bloquant : désactiver temporairement l'antivirus pendant l'installation.


3
Interface d'accueil — 3 modules
Connexions · Modèles · Migration · Barre de menus
textStructure de l'interface d'accueil MySQL Workbench
┌──────────────────────────────────────────────────────────┐
│  MySQL Workbench — Home Screen                          │
├──────────────────────────────────────────────────────────┤
│  MODULE 1 : MySQL Connections                             │
│  ┌─────────────────┐  ┌─────────────┐                          │
│  │ Local MySQL80  │  │  + New conn. │                          │
│  │ localhost:3306 │  └─────────────┘                          │
│  └─────────────────┘                                         │
├──────────────────────────────────────────────────────────┤
│  MODULE 2 : Models (EER Diagrams)                        │
│  ┌────────────────┐                                       │
│  │ + New Model    │  Ouvrir un modèle .mwb existant              │
│  └────────────────┘                                       │
├──────────────────────────────────────────────────────────┤
│  MODULE 3 : MySQL Migration Wizard                       │
│  Migrer depuis SQL Server, Access, PostgreSQL vers MySQL  │
└──────────────────────────────────────────────────────────┘

Configurer une nouvelle connexion

Home Screen → + (MySQL Connections) → remplir :

  • Connection Name : SkolaBase_Local
  • Hostname : 127.0.0.1 ou localhost
  • Port : 3306
  • Username : root
  • Cliquer Test Connection → saisir le mot de passe root → « Connection parameters are correct »
  • Cliquer OK → la connexion apparaît sur le Home Screen
MySQL Workbench est installé mais MySQL Server ne tourne pas. Que se passe-t-il quand on double-clique sur une connexion ?
Quelle fonctionnalité Workbench permet de générer automatiquement un diagramme EER depuis une BDD existante déjà créée en SQL ?
Partie 3 — Workbench & Modélisation graphique Modèle EER Tables · Colonnes · PK · NN · AI
⏱ 16 min

Créer un modèle EER dans Workbench

Créer un nouveau modèle EER, configurer le schéma, ajouter des tables avec leurs colonnes (nom, datatype, PK, NN, UQ, AI), créer les tables SkolaBase graphiquement et préparer le Forward Engineering.

✓ Ce que vous allez apprendre
  • Créer un nouveau modèle via File → New Model
  • Configurer le nom du schéma (skolabase)
  • Ajouter une table et configurer ses colonnes dans l'éditeur
  • Maîtriser les cases à cocher : PK, NN, UQ, BIN, UN, ZF, AI, G
  • Placer les tables sur le diagramme EER
  • Générer le script SQL via Forward Engineering

1
Créer un nouveau modèle et configurer le schéma
File → New Model · Schema Name · Default Charset
textÉtapes — créer le modèle SkolaBase
① File → New Model  (ou Ctrl+N depuis le module Models)

② Configurer le schéma :
   Onglet "EER Diagram" → Double-clic sur "mydb" dans le panneau de gauche
   → Name : skolabase
   → Default Charset : utf8mb4
   → Default Collation : utf8mb4_unicode_ci

③ Ouvrir le diagramme EER :
   Double-clic sur "Add Diagram" (icône diagramme) dans le panneau gauche
   → Un canvas blanc s'ouvre — c'est ici qu'on dessine

④ Sauvegarder le modèle :
   File → Save Model  (Ctrl+S)
   → Nom du fichier : SkolaBase.mwb  (format propriétaire Workbench)
   → Sauvegarder régulièrement !

2
Ajouter des tables et configurer les colonnes
PK · NN · UQ · AI · Datatypes · Default Value
textÉtapes — ajouter la table ETUDIANT dans Workbench
① Dans la barre d'outils du diagramme EER :
   Cliquer l'icône "Table" (rectangle avec colonnes)
   → Cliquer sur le canvas pour placer la table

② Nommer la table :
   Double-clic sur la table placée → onglet "Table"
   → Name : Etudiant
   → Engine : InnoDB  (toujours InnoDB pour les FK)
   → Charset/Collation : utf8mb4 / utf8mb4_unicode_ci

③ Ajouter les colonnes (onglet "Columns") :
   Cliquer dans la zone vide sous les en-têtes pour ajouter une ligne

   Column Name      | Datatype    | PK | NN | UQ | AI | Default
   numCINEtu        | VARCHAR(8)  | ✓  | ✓  |    |    |
   nomEtu           | VARCHAR(50) |    | ✓  |    |    |
   prenomEtu        | VARCHAR(50) |    | ✓  |    |    |
   dateNaissEtu     | DATE        |    |    |    |    | NULL
   villeEtu         | VARCHAR(50) |    | ✓  |    |    |
   telEtu           | VARCHAR(15) |    |    |    |    | NULL
CaseSigleSignificationEffet SQL généré
PKPrimary KeyClé primaire — identifiant unique de la lignePRIMARY KEY, implique NN automatiquement
NNNot NullLa colonne ne peut pas être videNOT NULL
UQUniqueToutes les valeurs doivent être différentesUNIQUE
BINBinaryStockage binaire (sensible à la casse)BINARY
UNUnsignedEntier positif uniquement (pas de négatif)UNSIGNED
ZFZero FillCompléter avec des zéros à gaucheZEROFILL
AIAuto IncrementIncrémentation automatique à chaque INSERTAUTO_INCREMENT
GGeneratedColonne calculée automatiquementGENERATED ALWAYS AS
ℹ Quand utiliser AI (Auto Increment) ?

AI est utile quand la clé primaire est un entier généré automatiquement par MySQL (numFormateur, numAdhérent...). Pour les clés métier (numCINEtu = donnée réelle fournie par l'utilisateur), on n'utilise pas AI — la valeur est saisie manuellement.


3
Toutes les tables SkolaBase dans Workbench
6 tables · Config complète · Forward Engineering
textConfiguration des tables SkolaBase — récapitulatif
TABLE : Filiere
  codeFiliere     VARCHAR(6)    PK NN
  libelleFiliere  VARCHAR(80)   NN

TABLE : Formation
  codeForm        VARCHAR(10)   PK NN
  titreForm       VARCHAR(100)  NN
  dureeForm       SMALLINT      NN
  niveauForm      VARCHAR(20)
  codeFiliere     VARCHAR(6)    NN  ← FK vers Filiere (à configurer en section suivante)

TABLE : Formateur
  numFormateur    INT           PK NN AI
  nomFormateur    VARCHAR(50)   NN
  specialiteForm  VARCHAR(80)

TABLE : Session
  codeSess        VARCHAR(10)   PK NN
  dateDebutSess   DATE          NN
  dateFinSess     DATE
  lieuSess        VARCHAR(100)
  numFormateur    INT           NN  ← FK vers Formateur
  codeForm        VARCHAR(10)   NN  ← FK vers Formation

TABLE : Etudiant
  numCINEtu       VARCHAR(8)    PK NN
  nomEtu          VARCHAR(50)   NN
  prenomEtu       VARCHAR(50)   NN
  dateNaissEtu    DATE
  villeEtu        VARCHAR(50)   NN
  telEtu          VARCHAR(15)

TABLE : Inscription
  numCINEtu       VARCHAR(8)    PK NN  ← FK vers Etudiant
  codeSess        VARCHAR(10)   PK NN  ← FK vers Session
  noteInscription DECIMAL(4,2)         ← entre 0.00 et 20.00
textForward Engineering — générer le SQL depuis le modèle
① Database → Forward Engineer...
② Connexion : choisir SkolaBase_Local → Next
③ Options : cocher "DROP objects before each CREATE" → Next
④ Objets : sélectionner toutes les tables → Next
⑤ Prévisualiser le SQL généré → Next → Execute
⑥ Résultat : toutes les tables créées dans MySQL !
La table Inscription a deux colonnes cochées PK : numCINEtu et codeSess. Quel type de clé primaire Workbench génère-t-il ?
Partie 3 — Workbench & Modélisation graphique Relations & associations graphiques Identifying · Non-Identifying · FK
⏱ 16 min

Relations & associations graphiques dans Workbench

Créer des relations entre tables dans le diagramme EER — types de relations (Identifying vs Non-Identifying), cardinalités Workbench, clés étrangères générées automatiquement, notation graphique et diagramme complet SkolaBase.

✓ Ce que vous allez apprendre
  • Distinguer Identifying Relationship et Non-Identifying Relationship
  • Utiliser les 6 outils de relation de la barre d'outils EER
  • Lire la notation Workbench (patte de corbeau, tiret, cercle)
  • Vérifier les FK générées automatiquement dans l'onglet Foreign Keys
  • Configurer ON DELETE et ON UPDATE sur chaque FK
  • Obtenir le diagramme EER complet SkolaBase

1
Identifying vs Non-Identifying Relationship
Entité forte · Entité faible · Ligne pleine vs pointillée
ℹ La différence essentielle

Une Identifying Relationship (ligne pleine) : l'entité enfant ne peut pas exister sans l'entité parent. La FK fait partie de la clé primaire de l'enfant. Exemple : une INSCRIPTION ne peut pas exister sans un ETUDIANT.
Une Non-Identifying Relationship (ligne pointillée) : l'entité enfant peut exister indépendamment. La FK n'est pas dans la PK. Exemple : une SESSION peut exister sans FORMATION (si on retarde l'affectation).

CritèreIdentifying RelationshipNon-Identifying Relationship
ReprésentationLigne pleineLigne pointillée
FK dans la PKOui — la FK fait partie de la clé primaireNon — la FK est une colonne ordinaire
Existence enfantImpossible sans le parentPossible indépendamment du parent
Exemples SkolaBaseINSCRIPTION (contient PK de ETUDIANT + SESSION)SESSION → FORMATEUR, FORMATION → FILIERE
Cardinalités typiquesAssociation N:M (table pivot)1:N (FK dans la table « côté N »)

2
Outils de relation Workbench et notation graphique
Barre d'outils EER · Patte de corbeau · Cardinalités
OutilTypeUsageSkolaBase
—1:1 (Identifying)Un-à-un, identifyingRare — entité faible 1:1Non utilisé
—1:N (Identifying)Un-à-plusieurs, identifyingFK dans PK de la table enfantINSCRIPTION → ETUDIANT et SESSION
──1:1 (Non-Id)Un-à-un, non-identifyingEntités indépendantes 1:1Non utilisé
──1:N (Non-Id)Un-à-plusieurs, non-identifyingFK ordinaire dans la table enfantSESSION → FORMATEUR, SESSION → FORMATION
──N:M (Non-Id)Plusieurs-à-plusieursGénère une table pivot automatiquementAlternative à créer INSCRIPTION manuellement
──N:M (Identifying)Plusieurs-à-plusieurs, identifyingTable pivot avec FK dans la PKINSCRIPTION (méthode recommandée)
textNotation graphique Workbench — patte de corbeau
Symboles en bout de ligne (notation Crow's Foot) :

  │   = exactement 1 (obligatoire, maximum 1)
  o   = 0 (facultatif)
  <   = N (plusieurs, patte de corbeau)

Combinaisons :
  ││ = (1,1) exactement un        Formateur ─││─ Session : 1 formateur/session
  o│ = (0,1) zéro ou un           Session ─│o── Formateur : un formateur peut avoir 0 session
  │< = (1,N) au moins un          Filiere ─<│── Formation : une formation/une filière
  o< = (0,N) zéro ou plusieurs    Etudiant ─<o─ Inscription : 0 ou N inscriptions/étudiant

3
Créer les relations SkolaBase et configurer ON DELETE
Étapes · FK onglet · ON DELETE CASCADE / RESTRICT · Diagramme final
textÉtapes — créer la relation Formation → Filiere
① Sélectionner l'outil "1:N Non-Identifying Relationship" dans la barre d'outils

② Cliquer sur la table Formation (côté N — plusieurs formations/filière)
   puis cliquer sur la table Filiere (côté 1 — une filière par formation)

③ Workbench ajoute automatiquement dans Formation :
   → Colonne codeFiliere VARCHAR(6) NN
   → Contrainte FK : Formation_ibfk_1 REFERENCES Filiere(codeFiliere)

④ Configurer la FK (double-clic sur la ligne de relation) :
   Onglet "Foreign Key"
   → Renommer : fk_Formation_Filiere (plus lisible)
   → ON DELETE : RESTRICT  (impossible de supprimer une filière si des formations y sont rattachées)
   → ON UPDATE : CASCADE   (si codeFiliere change, répercuter automatiquement)

Toutes les relations SkolaBase :
  Filiere  (1) ─── (N) Formation   → Non-Identifying 1:N  ON DELETE RESTRICT
  Formation(1) ─── (N) Session      → Non-Identifying 1:N  ON DELETE RESTRICT
  Formateur(1) ─── (N) Session      → Non-Identifying 1:N  ON DELETE RESTRICT
  Etudiant (N) ─── (N) Session via Inscription → Identifying 1:N sur les deux côtés
ON DELETEComportementUsage SkolaBase
RESTRICTInterdit la suppression du parent si des enfants existentFiliere → Formation : impossible de supprimer INF s'il y a des formations
CASCADESupprime automatiquement les enfants quand le parent est suppriméEtudiant → Inscription : supprimer un étudiant supprime ses inscriptions
SET NULLMet la FK à NULL dans les enfantsFormateur → Session : si formateur supprimé, session sans formateur (NULL)
NO ACTIONIdentique à RESTRICT sous MySQL/InnoDBSynonyme de RESTRICT en pratique
Pour créer la relation entre SESSION et FORMATEUR dans Workbench (un formateur anime plusieurs sessions), quel outil choisir et dans quel ordre cliquer ?
Dans le diagramme SkolaBase, ON DELETE CASCADE est configuré sur la FK Inscription.numCINEtu → Etudiant.numCINEtu. Que se passe-t-il si on supprime l'étudiant A123456 ?
Partie 4 — MySQL Server & Fondements SQL MySQL Server 8.0 Installation · Services · Port 3306
⏱ 16 min

MySQL Server — Installation & Gestion

MySQL 8.0 — types d'installation, configuration du port 3306, gestion des services Windows et Linux, vérification avec SHOW VARIABLES, comptes initiaux et bonnes pratiques de sécurité.

✓ Ce que vous allez apprendre
  • Comprendre le rôle de MySQL Server comme moteur SGBDR
  • Choisir entre les types d'installation (Developer Default, Server Only, Custom)
  • Configurer le port 3306, le mode d'authentification et le mot de passe root
  • Démarrer, arrêter et vérifier MySQL Server sous Windows et Linux
  • Exécuter les premières commandes : SHOW VARIABLES, SHOW DATABASES, STATUS

1
MySQL Server — présentation et types d'installation
MySQL 8.0 · Community · Developer Default · Server Only
ℹ MySQL Server — qu'est-ce que c'est ?

MySQL Server est le moteur de base de données relationnelle qui stocke, gère et répond aux requêtes SQL. C'est un processus système (service) qui tourne en arrière-plan et écoute sur le port 3306. Sans MySQL Server actif, aucune application (Workbench, PHP, Python...) ne peut accéder aux données.

Type d'installationComposants installésUsage recommandé
Developer DefaultServer + Workbench + Shell + Connecteurs (Python, Java, .NET...)Développeur full-stack — tout en un
Server OnlyMySQL Server uniquementServeur de production — sans interface graphique
Client OnlyOutils clients (Workbench, Shell) sans le serveurPoste qui se connecte à un serveur distant
CustomChoisir précisément les composantsContrôle total — recommandé pour les TP
FullTout — Server + Workbench + tous les connecteursÉviter — installe des composants inutiles

2
Configuration MySQL Server lors de l'installation
Port 3306 · Authentication Plugin · Root Password · Windows Service
textOptions de configuration — MySQL Server 8.0
① Type and Networking
   Config Type     : Development Computer (réserve moins de mémoire)
   Port            : 3306  (ne pas changer sauf conflit)
   Named Pipe      : désactiver (inutile pour notre usage)
   Open Windows Firewall port : cocher (accès réseau local)

② Authentication Method
   Choisir : "Use Strong Password Encryption" (caching_sha2_password)
   → MySQL 8.0 par défaut — plus sécurisé que l'ancien mysql_native_password
   Attention : certains vieux pilotes PHP/Python ne supportent pas encore ce mode
   → Si problèmes de connexion PHP : choisir "Use Legacy Authentication Method"

③ Accounts and Roles
   Root Password   : choisir un mot de passe FORT (minimum 12 caractères)
                     Exemple : SkolaBase_2024!  ← à noter impérativement
   Ajouter un compte  : optionnel — on créera les utilisateurs après (Partie 9)

④ Windows Service
   Service Name    : MySQL80  (défaut)
   Start at Startup: cocher  → MySQL démarre automatiquement avec Windows
   Run as System Account : garder par défaut
⚠ Sécurité — le compte root

Le compte root a tous les droits sur toutes les bases de données. En production, il ne faut jamais utiliser root pour les applications — créer un utilisateur dédié avec les droits minimaux nécessaires (Partie 9). En développement local, root est acceptable pour les TP.


3
Gérer le service MySQL — Windows et Linux
services.msc · net start/stop · systemctl · mysqladmin
bashGestion service MySQL — Windows (Invite de commandes Administrateur)
# Démarrer MySQL
net start MySQL80

# Arrêter MySQL
net stop MySQL80

# Vérifier le statut
sc query MySQL80
# Résultat attendu : STATE : 4 RUNNING

# Méthode graphique : services.msc
# Chercher MySQL80 → Clic droit → Démarrer/Arrêter/Redémarrer
bashGestion service MySQL — Linux (Ubuntu/Debian)
# Démarrer MySQL
sudo systemctl start mysql

# Arrêter MySQL
sudo systemctl stop mysql

# Redémarrer (après modification my.cnf)
sudo systemctl restart mysql

# Vérifier le statut
sudo systemctl status mysql
# Résultat attendu : Active: active (running)

# Activer le démarrage automatique
sudo systemctl enable mysql
sqlPremières commandes de vérification dans MySQL Shell ou Workbench
-- Vérifier la version et l'état
STATUS;
-- Affiche : Server version: 8.0.xx, Connection id, Uptime...

-- Variables de configuration importantes
SHOW VARIABLES LIKE 'version';
SHOW VARIABLES LIKE 'port';
SHOW VARIABLES LIKE 'character_set%';
SHOW VARIABLES LIKE 'max_connections';

-- Bases de données présentes par défaut
SHOW DATABASES;
-- information_schema  : métadonnées sur toutes les BDD
-- mysql               : comptes utilisateurs, privilèges
-- performance_schema  : métriques de performance
-- sys                 : vues simplifiées de performance_schema
Après l'installation, SHOW DATABASES affiche 4 bases de données (information_schema, mysql, performance_schema, sys). Peut-on supprimer la base mysql pour libérer de l'espace ?
Un étudiant installe MySQL avec l'option « Use Strong Password Encryption » (caching_sha2_password) et essaie de se connecter depuis une ancienne application PHP 5. La connexion échoue. Pourquoi ?
Partie 4 — MySQL Server & Fondements SQL SGBD & SQL Architecture · LDD · LMD · LQD · LCD
⏱ 18 min

SGBD & SQL — Panorama

Définition d'un SGBD et ses fonctions, architecture ANSI/SPARC 3 niveaux, catégories SQL (LDD/LMD/LQD/LCD), moteurs MySQL (InnoDB/MyISAM/Memory), et gestion des bases de données (CREATE/USE/DROP DATABASE).

✓ Ce que vous allez apprendre
  • Définir un SGBD et ses 5 fonctions fondamentales
  • Architecture ANSI/SPARC — 3 niveaux d'abstraction
  • Les 4 catégories SQL : LDD, LMD, LQD, LCD
  • Moteurs de stockage MySQL : InnoDB vs MyISAM vs Memory
  • Commandes BDD : CREATE DATABASE, USE, DROP DATABASE, SHOW DATABASES

1
SGBD — définition et 5 fonctions
SGBDR · Indépendance · Intégrité · Partage · Sécurité
ℹ Définition d'un SGBD

Un Système de Gestion de Base de Données (SGBD) est un logiciel qui assure la définition, la manipulation, la sécurisation et le partage des données. MySQL est un SGBDR (Relationnel) — il organise les données en tables liées par des clés. Autres exemples : PostgreSQL, Oracle, SQL Server (SGBDR), MongoDB, Cassandra (NoSQL).

#FonctionDescriptionExemple MySQL
1DéfinitionDécrire la structure des données (schéma)CREATE TABLE, ALTER TABLE
2ManipulationInsérer, modifier, supprimer, interrogerINSERT, UPDATE, DELETE, SELECT
3SécuritéContrôler les accès selon les rôlesGRANT, REVOKE, CREATE USER
4IntégritéGarantir la cohérence et la validité des donnéesClés étrangères, NOT NULL, CHECK
5PartagePermettre l'accès simultané et gérer les conflitsTransactions, verrous, ACID

2
Architecture ANSI/SPARC — 3 niveaux
Niveau externe · Conceptuel · Interne · Indépendance
textArchitecture ANSI/SPARC — 3 niveaux d'abstraction
  NIVEAU 1 — EXTERNE (Vues utilisateurs)
  ┌───────────┐  ┌───────────┐  ┌───────────┐
  │ Vue Etudiant │  │ Vue Admin   │  │ Vue Rapport │
  └───────────┘  └───────────┘  └───────────┘
          │                    │                   │
          └──────────────────────┴──────────────────────┘
                          │
  NIVEAU 2 — CONCEPTUEL (Schéma logique global)
  ┌─────────────────────────────────────────────┐
  │ Tables : Etudiant, Session, Inscription... │
  │ Relations, contraintes, types de données  │
  └─────────────────────────────────────────────┘
                          │
  NIVEAU 3 — INTERNE (Stockage physique)
  ┌─────────────────────────────────────────────┐
  │ Fichiers .ibd, index B-Tree, pages 16Ko    │
  │ Géré par MySQL InnoDB — transparent        │
  └─────────────────────────────────────────────┘

Indépendance logique : changer le schéma ne modifie pas les vues utilisateurs
Indépendance physique : changer le stockage ne modifie pas le schéma

3
Les 4 catégories SQL
LDD · LMD · LQD · LCD · Commandes
CatégorieNom completCommandesAction
LDDLangage de Définition de Données (DDL)CREATE, ALTER, DROP, TRUNCATE, RENAMEDéfinir et modifier la structure (tables, colonnes, index)
LMDLangage de Manipulation de Données (DML)INSERT, UPDATE, DELETEInsérer, modifier, supprimer des données
LQDLangage de Quête de Données (DQL)SELECTInterroger et extraire les données
LCDLangage de Contrôle de Données (DCL)GRANT, REVOKE, CREATE USERGérer les accès et les permissions
ℹ Les transactions (TCL)

Certains auteurs ajoutent le TCL (Transaction Control Language) : COMMIT, ROLLBACK, SAVEPOINT. Ces commandes valident ou annulent des groupes d'opérations LMD pour garantir la cohérence ACID.


4
Moteurs MySQL et gestion des bases de données
InnoDB · MyISAM · Memory · CREATE DATABASE · USE · DROP
MoteurTransactionsClés étrangèresPerformancesUsage recommandé
InnoDBOui — ACIDOui — intégrité référentielleÉquilibréesPar défaut — toujours utiliser pour les tables avec FK
MyISAMNonNonLecture rapideTables en lecture seule, archives (déprécié)
MemoryNonNonTrès rapide (RAM)Tables temporaires, caches — données perdues au redémarrage
sqlGestion des bases de données — SkolaBase
-- Créer la base de données SkolaBase
CREATE DATABASE skolabase
    CHARACTER SET utf8mb4
    COLLATE utf8mb4_unicode_ci;
-- utf8mb4 : supporte les caractères arabes, accents, emojis
-- utf8mb4_unicode_ci : comparaisons insensibles à la casse

-- Sélectionner la base active (toutes les commandes suivantes s'y appliquent)
USE skolabase;

-- Vérifier la base active
SELECT DATABASE();
-- Résultat : skolabase

-- Lister toutes les bases disponibles
SHOW DATABASES;

-- Lister les tables de la base active
SHOW TABLES;

-- Supprimer une base (ATTENTION : irréversible, supprime toutes les tables)
DROP DATABASE IF EXISTS skolabase_test;
-- IF EXISTS évite une erreur si la base n'existe pas

-- Afficher la structure de création d'une base
SHOW CREATE DATABASE skolabase;
Un étudiant crée ses tables SkolaBase avec le moteur MyISAM au lieu de InnoDB. Que se passe-t-il quand il ajoute une clé étrangère avec FOREIGN KEY REFERENCES ?
CREATE DATABASE skolabase CHARACTER SET utf8mb4 vs CREATE DATABASE skolabase CHARACTER SET utf8 — quelle est la différence pratique pour SkolaBase ?
Partie 4 — MySQL Server & Fondements SQL CREATE TABLE Types numériques · Chaînes · Dates
⏱ 20 min

CREATE TABLE & Types de données MySQL

Syntaxe complète de CREATE TABLE, panorama des types de données (numériques, chaînes de caractères, date/heure), choisir le bon type pour chaque attribut de SkolaBase, et créer les 6 tables en SQL pur.

✓ Ce que vous allez apprendre
  • Syntaxe complète CREATE TABLE avec tous les éléments
  • Types numériques : TINYINT, SMALLINT, INT, BIGINT, DECIMAL, FLOAT
  • Types chaînes : CHAR, VARCHAR, TEXT, ENUM
  • Types date/heure : DATE, DATETIME, TIMESTAMP, TIME, YEAR
  • Choisir le bon type : critères de taille, performance et sémantique
  • Créer les 6 tables SkolaBase avec les bons types

1
Syntaxe complète de CREATE TABLE
Structure · IF NOT EXISTS · ENGINE · CHARSET · COMMENT
sqlSyntaxe générale CREATE TABLE
CREATE TABLE [IF NOT EXISTS] nom_table (
    nom_colonne  type_donnee  [contraintes_colonne],
    nom_colonne  type_donnee  [contraintes_colonne],
    ...
    [contraintes_table]
)
ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4
COLLATE = utf8mb4_unicode_ci
COMMENT = 'Description de la table';

-- Contraintes colonne : NOT NULL, DEFAULT valeur, UNIQUE, AUTO_INCREMENT
-- Contraintes table   : PRIMARY KEY(...), FOREIGN KEY(...) REFERENCES ...,
--                       INDEX, UNIQUE KEY, CHECK
sqlExemple — CREATE TABLE Formateur
CREATE TABLE IF NOT EXISTS Formateur (
    numFormateur    INT             NOT NULL AUTO_INCREMENT,
    nomFormateur    VARCHAR(50)     NOT NULL,
    prenomFormateur VARCHAR(50)     NOT NULL,
    specialiteForm  VARCHAR(80)     NULL,
    emailFormateur  VARCHAR(100)    NULL,
    actifFormateur  BOOLEAN         NOT NULL DEFAULT TRUE,
    PRIMARY KEY (numFormateur)
) ENGINE = InnoDB
  DEFAULT CHARSET = utf8mb4
  COMMENT = 'Formateurs du centre SkolaBase';

2
Types numériques
TINYINT · SMALLINT · INT · BIGINT · DECIMAL · FLOAT · DOUBLE
TypeOctetsPlage (signé)Usage SkolaBaseConseil
TINYINT1-128 à 127actifFormateur (0/1)BOOLEAN = alias TINYINT(1)
SMALLINT2-32 768 à 32 767dureeForm (0—9999h)Durées courtes, compteurs
INT4-2,1 Md à 2,1 MdnumFormateur, clés PK AIPK auto-incrément par défaut
BIGINT8±9,2 × 1018ID très grande tableSeulement si > 2 milliards de lignes
DECIMAL(p,s)Variablep chiffres, s décimalesnoteInscription DECIMAL(4,2)Précision exacte — finances, notes
FLOAT4±3,4 × 1038Statistiques, moyennesApproximatif — jamais pour les finances
DOUBLE8±1,8 × 10308Calculs scientifiquesTrès approximatif — préférer DECIMAL
⚠ DECIMAL vs FLOAT pour les notes

FLOAT est approximatif : SELECT 14.50 + 5.50 peut donner 19.9999999.... DECIMAL(4,2) est exact : 14.50 + 5.50 = 20.00 garanti. Pour les notes, montants financiers et toute valeur qui doit être exacte, toujours utiliser DECIMAL.


3
Types chaînes de caractères
CHAR · VARCHAR · TEXT · ENUM · SET
TypeTailleStockageUsage SkolaBaseConseil
CHAR(n)n caractères fixesn octets (complété d'espaces)codeFiliere CHAR(6)Codes fixes (INSEE, CIN, codes postaux)
VARCHAR(n)1 à n caractèreslongueur réelle + 1–2 octetsnomEtu VARCHAR(50)Noms, titres, textes courts variables
TEXT65 535 caractèresHors ligne (lent)description longueÉviter pour les colonnes indexées
MEDIUMTEXT16 MoHors ligneContenu long (articles)Rarement nécessaire pour SkolaBase
ENUM('v1','v2')Liste de valeurs1–2 octetsniveauForm ENUM('Bac','Bac+2','Bac+3')Valeurs prédéfinies et limitées
ℹ CHAR vs VARCHAR — choisir le bon type

CHAR(8) stocke toujours 8 caractères (complète avec des espaces). Parfait pour des codes de longueur fixe comme les numéros CIN marocains (lettre + 7 chiffres, ex : A1234567). VARCHAR(50) stocke la longueur réelle. Parfait pour les noms : Alaoui (6 caractères) vs Bensouda-Korachi (16 caractères) — pas de gaspillage d'espace.


4
Types date et heure
DATE · DATETIME · TIMESTAMP · TIME · YEAR
TypeFormatPlageUsage SkolaBase
DATEAAAA-MM-JJ1000-01-01 à 9999-12-31dateNaissEtu, dateDebutSess, dateFinSess
DATETIMEAAAA-MM-JJ HH:MM:SS1000-01-01 à 9999-12-31création/modification enregistrements
TIMESTAMPAAAA-MM-JJ HH:MM:SS1970-01-01 à 2038-01-19created_at, updated_at (mis à jour auto)
TIMEHHH:MM:SS-838:59:59 à 838:59:59heureDebut, heureFin (horaires)
YEARAAAA1901 à 2155annéeScolaire
ℹ TIMESTAMP — mise à jour automatique

Le type TIMESTAMP avec l'option DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP se met à jour automatiquement à chaque modification de la ligne. Très utile pour tracer les changements sans code applicatif supplémentaire.

sqlTables SkolaBase complètes — tous les bons types
USE skolabase;

CREATE TABLE IF NOT EXISTS Filiere (
    codeFiliere     CHAR(6)         NOT NULL,
    libelleFiliere  VARCHAR(80)     NOT NULL,
    PRIMARY KEY (codeFiliere)
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4;

CREATE TABLE IF NOT EXISTS Formation (
    codeForm        VARCHAR(10)     NOT NULL,
    titreForm       VARCHAR(100)    NOT NULL,
    dureeForm       SMALLINT        NOT NULL COMMENT 'Durée en heures',
    niveauForm      ENUM('Technicien','Bac','Bac+2','Bac+3') NULL,
    codeFiliere     CHAR(6)         NOT NULL,
    PRIMARY KEY (codeForm),
    CONSTRAINT fk_Form_Filiere
        FOREIGN KEY (codeFiliere) REFERENCES Filiere(codeFiliere)
        ON DELETE RESTRICT ON UPDATE CASCADE
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4;

CREATE TABLE IF NOT EXISTS Formateur (
    numFormateur    INT             NOT NULL AUTO_INCREMENT,
    nomFormateur    VARCHAR(50)     NOT NULL,
    prenomFormateur VARCHAR(50)     NOT NULL,
    specialiteForm  VARCHAR(80)     NULL,
    PRIMARY KEY (numFormateur)
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4;

CREATE TABLE IF NOT EXISTS Session (
    codeSess        VARCHAR(10)     NOT NULL,
    dateDebutSess   DATE            NOT NULL,
    dateFinSess     DATE            NULL,
    lieuSess        VARCHAR(100)    NULL,
    numFormateur    INT             NOT NULL,
    codeForm        VARCHAR(10)     NOT NULL,
    PRIMARY KEY (codeSess),
    CONSTRAINT fk_Sess_Formateur
        FOREIGN KEY (numFormateur) REFERENCES Formateur(numFormateur)
        ON DELETE RESTRICT ON UPDATE CASCADE,
    CONSTRAINT fk_Sess_Formation
        FOREIGN KEY (codeForm) REFERENCES Formation(codeForm)
        ON DELETE RESTRICT ON UPDATE CASCADE
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4;

CREATE TABLE IF NOT EXISTS Etudiant (
    numCINEtu       CHAR(8)         NOT NULL COMMENT 'Lettre + 7 chiffres ex: A1234567',
    nomEtu          VARCHAR(50)     NOT NULL,
    prenomEtu       VARCHAR(50)     NOT NULL,
    dateNaissEtu    DATE            NULL,
    villeEtu        VARCHAR(50)     NOT NULL DEFAULT 'Casablanca',
    telEtu          VARCHAR(15)     NULL,
    PRIMARY KEY (numCINEtu)
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4;

CREATE TABLE IF NOT EXISTS Inscription (
    numCINEtu       CHAR(8)         NOT NULL,
    codeSess        VARCHAR(10)     NOT NULL,
    noteInscription DECIMAL(4,2)    NULL COMMENT 'Note sur 20, ex: 14.50',
    PRIMARY KEY (numCINEtu, codeSess),
    CONSTRAINT fk_Insc_Etudiant
        FOREIGN KEY (numCINEtu) REFERENCES Etudiant(numCINEtu)
        ON DELETE CASCADE ON UPDATE CASCADE,
    CONSTRAINT fk_Insc_Session
        FOREIGN KEY (codeSess) REFERENCES Session(codeSess)
        ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4;
Pour stocker les notes des étudiants (entre 0,00 et 20,00), un étudiant propose FLOAT et un autre propose DECIMAL(4,2). Lequel choisir et pourquoi ?
CHAR(8) est utilisé pour numCINEtu. Que stocke MySQL si on insère la valeur 'A123456' (7 caractères au lieu de 8) ?
Partie 5 — LDD : Contraintes & Modifications Contraintes d'intégrité PK · FK · NOT NULL · CHECK · UNIQUE
⏱ 22 min

Contraintes d'intégrité

Les 3 types de contraintes (domaine, entité, référentielle), syntaxe complète de PRIMARY KEY, FOREIGN KEY (ON DELETE/UPDATE), NOT NULL, DEFAULT, UNIQUE, CHECK (ENFORCED), et ajout de contraintes via ALTER TABLE.

✓ Ce que vous allez apprendre
  • Les 3 types de contraintes : domaine, entité, référentielle
  • PRIMARY KEY — simple et composée
  • FOREIGN KEY — ON DELETE et ON UPDATE (CASCADE, RESTRICT, SET NULL, NO ACTION)
  • NOT NULL, DEFAULT, UNIQUE
  • CHECK avec ENFORCED — vérifier les plages de valeurs
  • Ajouter des contraintes sur une table existante avec ALTER TABLE

1
Les 3 types de contraintes d'intégrité
Domaine · Entité · Référentielle
ℹ Pourquoi les contraintes ?

Sans contraintes, rien n'empêche d'insérer une note de 150, un étudiant sans nom, ou une inscription pour un étudiant inexistant. Les contraintes garantissent que les données restent cohérentes et valides — elles implémentent les règles de gestion directement dans la BDD, indépendamment des applications.

TypeDéfinitionContraintes SQLExemple SkolaBase
Contrainte de domaineLimite les valeurs autorisées pour un attributNOT NULL, DEFAULT, CHECK, ENUMnoteInscription entre 0 et 20, niveauForm dans une liste
Contrainte d'entitéGarantit l'unicité et l'identification de chaque lignePRIMARY KEY, UNIQUE, NOT NULLnumCINEtu unique par étudiant, codeSess unique par session
Contrainte référentielleGarantit la cohérence des liens entre tablesFOREIGN KEY ... REFERENCESnumFormateur dans Session doit exister dans Formateur

2
PRIMARY KEY — simple et composée
Définition inline · Définition en fin · Clé composée · CONSTRAINT
sqlPRIMARY KEY — 3 façons de déclarer
-- Façon 1 : inline (colonne unique, syntaxe courte)
CREATE TABLE Filiere (
    codeFiliere     CHAR(6)  NOT NULL  PRIMARY KEY,
    libelleFiliere  VARCHAR(80) NOT NULL
);

-- Façon 2 : en fin de table (recommandé — plus lisible)
CREATE TABLE Formation (
    codeForm    VARCHAR(10) NOT NULL,
    titreForm   VARCHAR(100) NOT NULL,
    codeFiliere CHAR(6)     NOT NULL,
    PRIMARY KEY (codeForm)                  -- PK simple
);

-- Façon 3 : avec nom de contrainte (bonne pratique)
CREATE TABLE Inscription (
    numCINEtu   CHAR(8)     NOT NULL,
    codeSess    VARCHAR(10) NOT NULL,
    note        DECIMAL(4,2),
    CONSTRAINT pk_Inscription PRIMARY KEY (numCINEtu, codeSess)  -- PK composée nommée
);

-- Vérifier les clés d'une table
SHOW KEYS FROM Inscription;
-- ou :
SHOW CREATE TABLE Inscription;
ℹ Propriétés de la PRIMARY KEY

Une PRIMARY KEY implique automatiquement : NOT NULL (pas de valeur nulle), UNIQUE (pas de doublon), et création d'un index B-Tree (accès rapide). Une table ne peut avoir qu'une seule PRIMARY KEY, mais elle peut porter sur plusieurs colonnes (clé composée).


3
FOREIGN KEY — intégrité référentielle
REFERENCES · ON DELETE · ON UPDATE · CASCADE · RESTRICT · SET NULL
sqlFOREIGN KEY — syntaxe complète SkolaBase
CREATE TABLE Session (
    codeSess        VARCHAR(10)  NOT NULL,
    dateDebutSess   DATE         NOT NULL,
    dateFinSess     DATE         NULL,
    lieuSess        VARCHAR(100) NULL,
    numFormateur    INT          NOT NULL,
    codeForm        VARCHAR(10)  NOT NULL,

    PRIMARY KEY (codeSess),

    -- FK nommée explicitement (bonne pratique)
    CONSTRAINT fk_Sess_Formateur
        FOREIGN KEY (numFormateur)
        REFERENCES Formateur(numFormateur)
        ON DELETE RESTRICT    -- Interdit supprimer un formateur avec des sessions
        ON UPDATE CASCADE,    -- Si numFormateur change, répercuter dans Session

    CONSTRAINT fk_Sess_Formation
        FOREIGN KEY (codeForm)
        REFERENCES Formation(codeForm)
        ON DELETE RESTRICT
        ON UPDATE CASCADE

) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4;

-- Vérifier les FK d'une table
SELECT
    CONSTRAINT_NAME,
    COLUMN_NAME,
    REFERENCED_TABLE_NAME,
    REFERENCED_COLUMN_NAME
FROM information_schema.KEY_COLUMN_USAGE
WHERE TABLE_NAME = 'Session'
  AND TABLE_SCHEMA = 'skolabase'
  AND REFERENCED_TABLE_NAME IS NOT NULL;
OptionON DELETEON UPDATEUsage SkolaBase
RESTRICTBloque la suppression du parent si des enfants existentBloque la modification de la PK parentFiliere→Formation : ne pas supprimer une filière si des formations y sont rattachées
CASCADESupprime automatiquement les enfantsPropage la modification aux enfantsEtudiant→Inscription : supprimer un étudiant supprime ses inscriptions
SET NULLMet la FK à NULL dans les enfantsMet la FK à NULLSi un formateur est supprimé, ses sessions gardent NULL comme formateur (la colonne doit accepter NULL)
NO ACTIONIdentique à RESTRICT sous InnoDBIdentique à RESTRICT sous InnoDBValeur par défaut si non spécifiée
⚠ Ordre de création des tables avec FK

On ne peut pas créer une FK vers une table qui n'existe pas encore. Dans SkolaBase, l'ordre obligatoire est : Filiere → Formation → Formateur → Session → Etudiant → Inscription. Toujours créer les tables référencées avant celles qui les référencent.


4
NOT NULL, DEFAULT, UNIQUE et CHECK
Contraintes de domaine · CHECK ENFORCED · UNIQUE INDEX
sqlContraintes de domaine — exemples SkolaBase
CREATE TABLE Etudiant (
    numCINEtu    CHAR(8)      NOT NULL,                -- Obligatoire
    nomEtu       VARCHAR(50)  NOT NULL,                -- Obligatoire
    prenomEtu    VARCHAR(50)  NOT NULL,                -- Obligatoire
    dateNaissEtu DATE         NULL,                    -- Optionnel
    villeEtu     VARCHAR(50)  NOT NULL DEFAULT 'Casablanca', -- Valeur par défaut
    telEtu       VARCHAR(15)  NULL,
    emailEtu     VARCHAR(100) NULL UNIQUE,             -- Unique (index automatique)

    PRIMARY KEY (numCINEtu),

    -- CHECK : vérifier le format CIN marocain (lettre + 7 chiffres)
    CONSTRAINT chk_CIN
        CHECK (numCINEtu REGEXP '^[A-Z][0-9]{7}$') ENFORCED,

    -- CHECK : date de naissance réaliste
    CONSTRAINT chk_DateNaiss
        CHECK (dateNaissEtu IS NULL OR dateNaissEtu < CURDATE()) ENFORCED

) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4;

-- CHECK sur la note dans Inscription
ALTER TABLE Inscription
    ADD CONSTRAINT chk_Note
        CHECK (noteInscription IS NULL
               OR (noteInscription >= 0 AND noteInscription <= 20)) ENFORCED;

-- UNIQUE sur plusieurs colonnes (unicité composite)
ALTER TABLE Session
    ADD CONSTRAINT uq_Sess_FormDate
        UNIQUE (codeForm, dateDebutSess);
-- Un même formation ne peut pas avoir deux sessions au même jour
ContrainteComportement si violéeExemple
NOT NULLErreur : Column 'nomEtu' cannot be nullINSERT sans nomEtu
DEFAULTPas d'erreur — valeur par défaut utiliséeINSERT sans villeEtu → 'Casablanca'
UNIQUEErreur : Duplicate entry 'x' for key 'emailEtu'Deux étudiants même email
CHECKErreur : Check constraint 'chk_Note' is violatedINSERT note = 25
FOREIGN KEYErreur : Cannot add or update a child rowINSERT inscription étudiant inexistant
La contrainte CHECK (noteInscription >= 0 AND noteInscription <= 20) est définie. On exécute INSERT INTO Inscription VALUES ('A1234567', 'SESS-01', NULL). Que se passe-t-il ?
On tente de supprimer la filière INF alors que 3 formations y sont rattachées. La FK est configurée ON DELETE RESTRICT. Que retourne MySQL ?
Partie 5 — LDD : Contraintes & Modifications ALTER TABLE & DROP ADD · MODIFY · CHANGE · DROP · RENAME
⏱ 18 min

ALTER TABLE & DROP TABLE

Modifier la structure d'une table existante avec ALTER TABLE (ADD, MODIFY, CHANGE, DROP, RENAME TO), gérer les index et clés étrangères, et supprimer tables et bases avec DROP TABLE et DROP DATABASE.

✓ Ce que vous allez apprendre
  • ALTER TABLE ... ADD COLUMN — ajouter une colonne avec position (AFTER/FIRST)
  • ALTER TABLE ... MODIFY COLUMN — changer le type ou les contraintes
  • ALTER TABLE ... CHANGE COLUMN — renommer ET modifier une colonne
  • ALTER TABLE ... DROP COLUMN — supprimer une colonne
  • ALTER TABLE ... RENAME TO — renommer une table
  • DROP TABLE IF EXISTS — supprimer une table en toute sécurité
  • Ajouter et supprimer des index et des FK sur une table existante

1
ALTER TABLE — ajouter et modifier des colonnes
ADD COLUMN · MODIFY · CHANGE · AFTER · FIRST
sqlALTER TABLE — ADD, MODIFY, CHANGE — exemples SkolaBase
-- ADD COLUMN : ajouter une colonne
ALTER TABLE Etudiant
    ADD COLUMN emailEtu VARCHAR(100) NULL
    AFTER telEtu;                          -- Positionner après telEtu
-- AFTER col  : insérer après une colonne précise
-- FIRST      : insérer en première position
-- (sans AFTER/FIRST : ajoutée en dernière position par défaut)

-- Ajouter plusieurs colonnes en une commande
ALTER TABLE Formateur
    ADD COLUMN emailFormateur  VARCHAR(100) NULL AFTER nomFormateur,
    ADD COLUMN telFormateur    VARCHAR(15)  NULL AFTER emailFormateur,
    ADD COLUMN actif           BOOLEAN      NOT NULL DEFAULT TRUE;

-- MODIFY COLUMN : changer le type ou les contraintes (garde le nom)
ALTER TABLE Formation
    MODIFY COLUMN titreForm VARCHAR(150) NOT NULL;  -- Agrandir la taille
-- Attention : peut échouer si les données existantes ne sont pas compatibles

ALTER TABLE Inscription
    MODIFY COLUMN noteInscription DECIMAL(4,2) NOT NULL DEFAULT 0.00;
-- Ajouter NOT NULL sur une colonne existante (toutes les lignes doivent avoir une valeur)

-- CHANGE COLUMN : renommer ET modifier (deux noms requis)
ALTER TABLE Etudiant
    CHANGE COLUMN villeEtu communeEtu VARCHAR(80) NOT NULL DEFAULT 'Casablanca';
-- Ancien nom : villeEtu | Nouveau nom : communeEtu | Nouveau type
CommandeRenommer ?Changer type ?Usage
ADD COLUMN— (nouvelle)—Ajouter une nouvelle colonne
MODIFY COLUMNNonOuiChanger type/contraintes sans renommer
CHANGE COLUMNOuiOuiRenommer et/ou changer type
DROP COLUMN——Supprimer une colonne (irréversible)
RENAME COLUMNOui (MySQL 8+)NonRenommer uniquement (plus simple que CHANGE)

2
Supprimer colonnes, index, FK et tables
DROP COLUMN · DROP INDEX · DROP FOREIGN KEY · DROP TABLE
sqlDROP — colonnes, index, FK, tables
-- DROP COLUMN : supprimer une colonne (irréversible !)
ALTER TABLE Etudiant
    DROP COLUMN emailEtu;

-- Supprimer plusieurs colonnes
ALTER TABLE Formateur
    DROP COLUMN telFormateur,
    DROP COLUMN actif;

-- DROP INDEX : supprimer un index (sauf PK)
ALTER TABLE Etudiant
    DROP INDEX emailEtu;     -- Supprime l'index UNIQUE sur emailEtu
-- ou : DROP INDEX nom_index ON table;

-- DROP FOREIGN KEY : supprimer une contrainte FK
-- D'abord trouver le nom de la contrainte :
SHOW CREATE TABLE Session;
-- Puis supprimer :
ALTER TABLE Session
    DROP FOREIGN KEY fk_Sess_Formateur;
-- Note : supprimer la FK ne supprime pas la colonne numFormateur

-- RENAME TABLE / RENAME TO
ALTER TABLE Session RENAME TO SessionFormation;
-- ou : RENAME TABLE Session TO SessionFormation;

-- DROP TABLE : supprimer une table et toutes ses données (irréversible)
DROP TABLE IF EXISTS SessionFormation;
-- IF EXISTS : pas d'erreur si la table n'existe pas

-- Supprimer plusieurs tables
DROP TABLE IF EXISTS Inscription, Session, Formation, Filiere;
-- Attention : respecter l'ordre inverse des FK (enfants avant parents)

-- DROP DATABASE : supprimer toute la base (EXTRÊMEMENT dangereux)
DROP DATABASE IF EXISTS skolabase_test;
⚠ Ordre de suppression avec FK — règle critique

Si une table A a une FK vers B, on ne peut pas supprimer B sans avoir supprimé A d'abord. Pour SkolaBase, l'ordre de suppression inverse l'ordre de création : Inscription → Session → Formation → Filiere & Formateur → Etudiant. Ou utiliser SET FOREIGN_KEY_CHECKS = 0 avant (à faire avec précaution en développement uniquement).


3
Ajouter et gérer les index
CREATE INDEX · ADD INDEX · UNIQUE INDEX · SHOW INDEX
ℹ Pourquoi créer des index ?

Un index accélère les recherches sur une colonne. Sans index, MySQL lit toutes les lignes (full table scan). Avec index, il utilise une structure B-Tree pour trouver les lignes en quelques accès. Créer des index sur les colonnes fréquemment utilisées dans WHERE, JOIN et ORDER BY. Inconvénient : ralentit les INSERT/UPDATE.

sqlINDEX — création et gestion SkolaBase
-- Créer un index simple (recherches fréquentes sur villeEtu)
CREATE INDEX idx_Etu_Ville ON Etudiant(villeEtu);

-- Créer un index unique (valeurs distinctes obligatoires)
CREATE UNIQUE INDEX idx_Etu_Email ON Etudiant(emailEtu);

-- Ajouter un index via ALTER TABLE
ALTER TABLE Formation
    ADD INDEX idx_Form_Filiere (codeFiliere),    -- Accélérer les JOIN avec Filiere
    ADD INDEX idx_Form_Niveau (niveauForm);      -- Filtrer par niveau fréquemment

-- Index composite (colonne 1 + colonne 2)
CREATE INDEX idx_Sess_FormDate ON Session(codeForm, dateDebutSess);
-- Utilisé quand WHERE codeForm = ? AND dateDebutSess > ?

-- Lister les index d'une table
SHOW INDEX FROM Session;

-- Lister les index avec leur utilisation (MySQL 8+)
SELECT INDEX_NAME, COLUMN_NAME, NON_UNIQUE, SEQ_IN_INDEX
FROM information_schema.STATISTICS
WHERE TABLE_NAME = 'Session' AND TABLE_SCHEMA = 'skolabase';
On veut renommer la colonne lieuSess en salleFormation dans la table Session sans changer son type. Quelle commande est la plus adaptée sous MySQL 8 ?
On tente DROP TABLE Formation mais la table Session a une FK vers Formation. Que se passe-t-il ?
Partie 6 — LMD : Manipuler les données INSERT INTO Multi-lignes · AUTO_INCREMENT · Dates
⏱ 16 min

INSERT INTO

Insérer des données dans les tables SkolaBase — syntaxe complète, insertion multi-lignes, colonnes optionnelles et valeurs par défaut, AUTO_INCREMENT, fonctions de date (CURDATE(), NOW()), et INSERT ... ON DUPLICATE KEY UPDATE.

✓ Ce que vous allez apprendre
  • Syntaxe INSERT INTO ... VALUES et INSERT INTO ... SET
  • Insérer plusieurs lignes en une seule commande
  • Omettre les colonnes avec DEFAULT ou NULL
  • Récupérer l'id généré par AUTO_INCREMENT avec LAST_INSERT_ID()
  • Insérer des dates avec CURDATE(), NOW() et les littéraux de date
  • INSERT ... ON DUPLICATE KEY UPDATE — insérer ou mettre à jour

1
Syntaxes de base de INSERT INTO
VALUES · SET · Colonnes optionnelles · Ordre des colonnes
sqlINSERT INTO — syntaxes SkolaBase
-- Syntaxe 1 : lister les colonnes (recommandée)
INSERT INTO Filiere (codeFiliere, libelleFiliere)
VALUES ('INF', 'Informatique');

-- Syntaxe 2 : sans liste de colonnes (ordre strict !)
-- RISQUÉ : si la structure change, la requête peut échouer silencieusement
INSERT INTO Filiere
VALUES ('GES', 'Gestion'), ('ELE', 'Électronique');

-- Syntaxe 3 : SET (style objet, lisible)
INSERT INTO Formateur SET
    nomFormateur    = 'Alaoui',
    prenomFormateur = 'Karim',
    specialiteForm  = 'Développement Web';

-- Colonnes avec DEFAULT : omettre la colonne ou utiliser DEFAULT
INSERT INTO Etudiant (numCINEtu, nomEtu, prenomEtu, dateNaissEtu)
VALUES ('A1234567', 'Bennani', 'Sara', '2001-03-15');
-- villeEtu prend la valeur DEFAULT 'Casablanca'
-- telEtu prend NULL (accepte NULL)

-- Utiliser explicitement DEFAULT et NULL
INSERT INTO Etudiant
VALUES ('B7654321', 'Idrissi', 'Youssef', '1999-07-22', DEFAULT, NULL);
--                                                        ^ville   ^tel
⚠ Toujours lister les colonnes !

Sans liste de colonnes, l'ordre doit correspondre exactement à la définition de la table. Si une colonne est ajoutàe plus tard via ALTER TABLE, toutes les requêtes INSERT sans liste de colonnes décalent et insèrent des valeurs dans les mauvaises colonnes. Toujours préférer la syntaxe avec liste de colonnes explicite.


2
Insertion multi-lignes et AUTO_INCREMENT
Multi-VALUES · LAST_INSERT_ID() · Peuplement SkolaBase
sqlPeuplement complet SkolaBase — données marocaines
USE skolabase;

-- 1. Filières (pas de FK, insérer en premier)
INSERT INTO Filiere (codeFiliere, libelleFiliere) VALUES
    ('INF', 'Informatique'),
    ('GES', 'Gestion et Commerce'),
    ('ELE', 'Électronique et Électrotechnique'),
    ('BTP', 'Bâtiment et Travaux Publics');

-- 2. Formations
INSERT INTO Formation (codeForm, titreForm, dureeForm, niveauForm, codeFiliere) VALUES
    ('DEV-WEB', 'Développement Web Full Stack',    120, 'Bac+2', 'INF'),
    ('DEV-MOB', 'Développement Mobile Android',    80,  'Bac+2', 'INF'),
    ('BDD-ADM', 'Administration des Bases de Données', 100, 'Bac+3', 'INF'),
    ('CPT-GEN', 'Comptabilité Générale',           90,  'Bac',   'GES'),
    ('MKT-DIG', 'Marketing Digital',               60,  'Bac+2', 'GES');

-- 3. Formateurs (numFormateur = AUTO_INCREMENT, ne pas le spécifier)
INSERT INTO Formateur (nomFormateur, prenomFormateur, specialiteForm) VALUES
    ('Alaoui',   'Karim',   'Développement Web, PHP, Laravel'),
    ('Bennani',  'Nadia',   'Bases de données, MySQL, Oracle'),
    ('Chraibi',  'Hassan',  'Réseaux, Administration système'),
    ('Idrissi',  'Leila',   'Marketing digital, SEO');

-- Récupérer le dernier ID généré
SELECT LAST_INSERT_ID();
-- Résultat : 4 (dernier numFormateur inséré)

-- 4. Sessions
INSERT INTO Session (codeSess, dateDebutSess, dateFinSess, lieuSess, numFormateur, codeForm) VALUES
    ('SESS-2024-01', '2024-09-02', '2024-12-20', 'Salle A101 - Casablanca', 1, 'DEV-WEB'),
    ('SESS-2024-02', '2024-09-09', '2024-11-29', 'Salle B205 - Rabat',      2, 'BDD-ADM'),
    ('SESS-2024-03', '2024-10-07', '2024-12-13', 'Salle A102 - Casablanca', 1, 'DEV-MOB'),
    ('SESS-2025-01', '2025-01-13', '2025-04-04', 'Salle A101 - Casablanca', 1, 'DEV-WEB');

-- 5. Étudiants (données marocaines)
INSERT INTO Etudiant (numCINEtu, nomEtu, prenomEtu, dateNaissEtu, villeEtu, telEtu) VALUES
    ('A1234567', 'Alaoui',   'Karim',    '2002-05-15', 'Casablanca', '0612345678'),
    ('B7654321', 'Bennani',  'Sara',     '2001-11-22', 'Rabat',      '0698765432'),
    ('C2468135', 'Chraibi',  'Youssef',  '2003-01-08', 'Marrakech',  '0635791246'),
    ('D1357924', 'Idrissi',  'Fatima',   '2002-08-30', 'Fès',        '0674513892'),
    ('E9876543', 'Mansouri', 'Amine',    '2001-03-17', 'Casablanca', '0656789012'),
    ('F3692581', 'Tazi',     'Zineb',    '2003-06-25', 'Tanger',     '0678901234');

-- 6. Inscriptions (FK vers Etudiant et Session)
INSERT INTO Inscription (numCINEtu, codeSess, noteInscription) VALUES
    ('A1234567', 'SESS-2024-01', 14.50),
    ('B7654321', 'SESS-2024-01', 16.00),
    ('C2468135', 'SESS-2024-01', 11.75),
    ('A1234567', 'SESS-2024-02', 13.25),
    ('D1357924', 'SESS-2024-02', 17.50),
    ('E9876543', 'SESS-2024-01', NULL),   -- Note pas encore saisie
    ('F3692581', 'SESS-2024-03', 15.00);

3
Dates, INSERT ... SELECT et ON DUPLICATE KEY
CURDATE() · NOW() · INSERT SELECT · ON DUPLICATE KEY UPDATE
sqlFonctions de date et techniques avancées
-- Fonctions de date utiles dans INSERT
INSERT INTO Session (codeSess, dateDebutSess, dateFinSess, lieuSess, numFormateur, codeForm)
VALUES (
    'SESS-2025-02',
    CURDATE(),                              -- Date du jour
    DATE_ADD(CURDATE(), INTERVAL 3 MONTH), -- Dans 3 mois
    'Salle C301 - Casablanca',
    2,
    'CPT-GEN'
);

-- Littéraux de date (format ISO 8601 recommandé)
INSERT INTO Etudiant (numCINEtu, nomEtu, prenomEtu, dateNaissEtu, villeEtu)
VALUES ('G1593570', 'Guessous', 'Imane', '2004-02-14', 'Agadir');
-- Format : 'AAAA-MM-JJ' pour DATE
-- Format : 'AAAA-MM-JJ HH:MM:SS' pour DATETIME

-- INSERT ... SELECT : copier des données depuis une autre table
INSERT INTO Formation (codeForm, titreForm, dureeForm, niveauForm, codeFiliere)
SELECT
    CONCAT('CPY-', codeForm),   -- Nouveau code préfixé
    CONCAT('[Archivé] ', titreForm),
    dureeForm,
    niveauForm,
    codeFiliere
FROM Formation
WHERE codeFiliere = 'INF';     -- Copier toutes les formations informatique

-- INSERT ... ON DUPLICATE KEY UPDATE : insérer ou mettre à jour
INSERT INTO Inscription (numCINEtu, codeSess, noteInscription)
VALUES ('A1234567', 'SESS-2024-01', 15.00)
ON DUPLICATE KEY UPDATE noteInscription = 15.00;
-- Si la PK (A1234567, SESS-2024-01) existe déjà : met à jour la note
-- Si elle n'existe pas : insère la nouvelle ligne

-- Compter les lignes affectées
-- INSERT normal    : 1 (insertion)
-- ON DUPLICATE KEY : 2 (mise à jour) ou 1 (insertion)
SELECT ROW_COUNT();
On insère un formateur sans spécifier numFormateur (AUTO_INCREMENT). Que retourne LAST_INSERT_ID() si 3 formateurs avaient déjà été insérés ?
On exécute INSERT INTO Inscription VALUES ('Z9999999', 'SESS-2024-01', 12.00). L'étudiant Z9999999 n'existe pas dans la table Etudiant. Que se passe-t-il ?
Partie 6 — LMD : Manipuler les données UPDATE · DELETE · TRUNCATE WHERE · CASCADE · Sécurité
⏱ 18 min

UPDATE, DELETE & TRUNCATE

Modifier les données avec UPDATE SET WHERE, supprimer avec DELETE FROM WHERE, différence entre DELETE et TRUNCATE, effets de ON DELETE CASCADE, et bonnes pratiques pour éviter les destructions accidentelles.

✓ Ce que vous allez apprendre
  • UPDATE table SET col = val WHERE condition — modifier des lignes ciblées
  • Mettre à jour plusieurs colonnes simultanément
  • Mettre à jour avec des expressions et des sous-requêtes
  • DELETE FROM table WHERE condition — supprimer des lignes ciblées
  • Différence fondamentale DELETE vs TRUNCATE
  • Sécuriser les UPDATE/DELETE — tester avec SELECT d'abord

1
UPDATE — modifier les données
SET · WHERE · Expressions · Multi-colonnes · UPDATE JOIN
⚠ Règle d'or — toujours tester avec SELECT avant UPDATE

Avant chaque UPDATE : exécuter d'abord SELECT * FROM table WHERE <même condition> pour vérifier quelles lignes seront affectées. Un UPDATE sans WHERE modifie toutes les lignes de la table — irréversible sans sauvegarde.

sqlUPDATE — exemples complets SkolaBase
-- Vérifier d'abord ce qui sera modifié
SELECT * FROM Etudiant WHERE numCINEtu = 'A1234567';

-- UPDATE simple : corriger le téléphone d'un étudiant
UPDATE Etudiant
SET telEtu = '0612000001'
WHERE numCINEtu = 'A1234567';

-- UPDATE multi-colonnes : corriger plusieurs champs
UPDATE Etudiant
SET
    villeEtu  = 'Rabat',
    telEtu    = '0698001122'
WHERE numCINEtu = 'B7654321';

-- UPDATE avec expression : ajouter 1 point bonus à toutes les notes > 10
UPDATE Inscription
SET noteInscription = LEAST(noteInscription + 1, 20)
-- LEAST(x, 20) garantit que la note ne dépasse pas 20
WHERE noteInscription > 10 AND noteInscription IS NOT NULL;

-- UPDATE toutes les lignes (intentionnel : sans WHERE)
-- Désactiver tous les formateurs (mise en maintenance)
UPDATE Formateur SET actif = FALSE;
-- ROW_COUNT() donne le nombre de lignes modifiées
SELECT ROW_COUNT();

-- UPDATE avec JOIN : mettre à jour en se basant sur une autre table
UPDATE Inscription i
    JOIN Session s ON i.codeSess = s.codeSess
SET i.noteInscription = 0
WHERE s.dateFinSess < CURDATE()
  AND i.noteInscription IS NULL;
-- Mettre 0 pour les inscriptions sans note des sessions terminées
sqlUPDATE avec transaction — sécuriser les modifications
-- Utiliser une transaction pour annuler si erreur
START TRANSACTION;

UPDATE Inscription
SET noteInscription = 18.00
WHERE numCINEtu = 'D1357924' AND codeSess = 'SESS-2024-02';

-- Vérifier le résultat avant de valider
SELECT * FROM Inscription WHERE numCINEtu = 'D1357924';

-- Si correct : valider
COMMIT;
-- Si erreur : annuler
-- ROLLBACK;

2
DELETE — supprimer des lignes
DELETE FROM · WHERE · CASCADE · DELETE JOIN · Limite
sqlDELETE — exemples SkolaBase
-- Tester d'abord avec SELECT
SELECT * FROM Inscription WHERE codeSess = 'SESS-2024-03';

-- DELETE ciblé : supprimer les inscriptions d'une session
DELETE FROM Inscription
WHERE codeSess = 'SESS-2024-03';

-- DELETE avec LIMIT : supprimer au maximum N lignes (sécurité)
DELETE FROM Inscription
WHERE noteInscription IS NULL
LIMIT 10;   -- Ne supprime pas plus de 10 lignes même si plus correspondent

-- DELETE avec condition sur date
DELETE FROM Session
WHERE dateFinSess < '2023-01-01';  -- Sessions terminées avant 2023

-- Vérifier l'effet ON DELETE CASCADE
-- Si ON DELETE CASCADE est défini sur Inscription → Etudiant :
DELETE FROM Etudiant WHERE numCINEtu = 'A1234567';
-- → Supprime automatiquement toutes les inscriptions de A1234567

-- DELETE avec JOIN : supprimer en se basant sur une autre table
DELETE i
FROM Inscription i
    JOIN Session s ON i.codeSess = s.codeSess
WHERE s.codeForm = 'DEV-WEB'
  AND s.dateFinSess < '2024-01-01';
-- Supprimer toutes les inscriptions aux sessions DEV-WEB terminées avant 2024

-- Confirmer le nombre de lignes supprimées
SELECT ROW_COUNT();

3
DELETE vs TRUNCATE — différence fondamentale
Transaction · AUTO_INCREMENT · FK · Performance · WHERE
CritèreDELETETRUNCATE
Type SQLLMD (DML) — ManipulationLDD (DDL) — Définition
Clause WHEREOui — suppression cibléeNon — supprime TOUT
TransactionOui — peut être annulé avec ROLLBACKNon — auto-commit, irréversible
AUTO_INCREMENTPas réinitialisé (continue depuis le max)Réinitialisé à 1
TriggersDéclenche les triggers DELETENe déclenche PAS les triggers
Clés étrangèresRespectées (CASCADE, RESTRICT)Échoue si des FK pointent vers la table
PerformanceLigne par ligne — plus lent sur grandes tablesRecrée la table — très rapide
UsageSupprimer des lignes spécifiquesVider complètement une table de test
sqlDELETE vs TRUNCATE — comparaison pratique
-- DELETE tout (lent, annulable, garde AUTO_INCREMENT)
START TRANSACTION;
DELETE FROM Inscription;   -- Supprime toutes les lignes ligne par ligne
ROLLBACK;                  -- Annulation possible !
-- La table Inscription retrouve toutes ses lignes

-- TRUNCATE (rapide, irréversible, remet AUTO_INCREMENT à 1)
TRUNCATE TABLE Formateur;
-- Équivalent à DROP TABLE + CREATE TABLE mais plus rapide
-- ROLLBACK impossible après TRUNCATE
-- Échoue si une autre table a une FK vers Formateur

-- Stratégie pour vider toutes les tables (développement)
SET FOREIGN_KEY_CHECKS = 0;   -- Désactiver temporairement les FK
TRUNCATE TABLE Inscription;
TRUNCATE TABLE Session;
TRUNCATE TABLE Etudiant;
TRUNCATE TABLE Formation;
TRUNCATE TABLE Formateur;
TRUNCATE TABLE Filiere;
SET FOREIGN_KEY_CHECKS = 1;   -- Réactiver les FK
-- ⚠ UNIQUEMENT en développement pour réinitialiser les données de test
Un étudiant exécute UPDATE Etudiant SET villeEtu = 'Fès' sans clause WHERE. Que se passe-t-il ?
Après avoir inséré 5 formateurs (IDs 1–5), on supprime tous les formateurs avec DELETE FROM Formateur puis on en insère un nouveau. Quel sera son numFormateur ?
Partie 7 — DQL : Interroger les données SELECT WHERE · ORDER BY · LIMIT · DISTINCT
⏱ 20 min

SELECT — Fondamentaux

Maîtriser la requête SELECT de A à Z : colonnes et alias, DISTINCT, ordre d'évaluation MySQL, clause WHERE avec tous ses opérateurs (AND/OR/NOT/BETWEEN/IN/LIKE), ORDER BY multi-colonnes et LIMIT/OFFSET pour la pagination.

✓ Ce que vous allez apprendre
  • Structure complète d'un SELECT et ordre d'évaluation MySQL
  • Sélectionner des colonnes, utiliser des alias (AS)
  • DISTINCT — éliminer les doublons
  • Clause WHERE : AND, OR, NOT, BETWEEN, IN, LIKE, IS NULL
  • ORDER BY multi-colonnes (ASC/DESC), LIMIT et OFFSET

1
Structure d'un SELECT et ordre d'évaluation
Ordre d'écriture vs ordre d'évaluation · Alias · DISTINCT
sqlStructure complète d'un SELECT
-- Structure complète (l'ordre d'écriture est OBLIGATOIRE)
SELECT   [DISTINCT] colonnes | expressions | *      -- 5. Quoi retourner
FROM     table                                       -- 1. Depuis quelle table
[WHERE   condition]                                  -- 2. Filtrer les lignes
[GROUP BY colonnes]                                  -- 3. Regrouper
[HAVING  condition_groupe]                           -- 4. Filtrer les groupes
[ORDER BY colonnes [ASC|DESC]]                       -- 6. Trier
[LIMIT   n [OFFSET m]];                             -- 7. Limiter

-- Ordre d'ÉVALUATION MySQL (différent de l'ordre d'écriture !)
-- FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY → LIMIT
-- Important : on ne peut pas utiliser un alias défini dans SELECT dans WHERE
-- (WHERE est évalué avant SELECT)
sqlSELECT — colonnes, alias et DISTINCT — SkolaBase
USE skolabase;

-- Toutes les colonnes (déconseillé en production)
SELECT * FROM Etudiant;

-- Colonnes spécifiques
SELECT numCINEtu, nomEtu, prenomEtu FROM Etudiant;

-- Alias avec AS (renommer le résultat)
SELECT
    numCINEtu           AS cin,
    nomEtu              AS nom,
    prenomEtu           AS prenom,
    villeEtu            AS ville
FROM Etudiant;

-- Alias sans AS (syntaxe courte)
SELECT nomEtu nom, prenomEtu prenom FROM Etudiant;

-- Colonne calculée avec alias
SELECT
    numCINEtu,
    CONCAT(prenomEtu, ' ', nomEtu) AS nom_complet,
    YEAR(CURDATE()) - YEAR(dateNaissEtu) AS age_approx
FROM Etudiant;

-- DISTINCT : éliminer les doublons
SELECT DISTINCT villeEtu FROM Etudiant;
-- Retourne chaque ville une seule fois

SELECT DISTINCT codeFiliere FROM Formation;
-- Toutes les filières utilisées

-- DISTINCT sur plusieurs colonnes (combinaison unique)
SELECT DISTINCT villeEtu, nomEtu FROM Etudiant;
-- Lignes uniques (ville + nom)

2
Clause WHERE — tous les opérateurs
AND · OR · NOT · BETWEEN · IN · LIKE · IS NULL · Priorités
sqlOpérateurs WHERE — exemples SkolaBase
-- Comparaison simple
SELECT * FROM Etudiant WHERE villeEtu = 'Casablanca';
SELECT * FROM Inscription WHERE noteInscription >= 14;
SELECT * FROM Formation WHERE dureeForm != 120;   -- != ou <>

-- AND / OR (AND a priorité sur OR)
SELECT * FROM Etudiant
WHERE villeEtu = 'Casablanca' AND nomEtu = 'Alaoui';

SELECT * FROM Etudiant
WHERE villeEtu = 'Casablanca' OR villeEtu = 'Rabat';

-- Parenthèses pour forcer la priorité
SELECT * FROM Etudiant
WHERE (villeEtu = 'Casablanca' OR villeEtu = 'Rabat')
  AND nomEtu LIKE 'A%';

-- NOT : inverser une condition
SELECT * FROM Inscription WHERE NOT noteInscription >= 14;
-- Équivalent à : WHERE noteInscription < 14

-- BETWEEN : plage inclusive (inclut les bornes)
SELECT * FROM Inscription
WHERE noteInscription BETWEEN 10 AND 15;
-- Équivalent à : noteInscription >= 10 AND noteInscription <= 15

SELECT * FROM Session
WHERE dateDebutSess BETWEEN '2024-01-01' AND '2024-12-31';

-- IN : liste de valeurs
SELECT * FROM Etudiant
WHERE villeEtu IN ('Casablanca', 'Rabat', 'Marrakech');
-- Plus lisible que OR multiples

SELECT * FROM Formation
WHERE niveauForm IN ('Bac+2', 'Bac+3');

-- NOT IN : exclure une liste
SELECT * FROM Formation
WHERE codeFiliere NOT IN ('GES', 'ELE');

-- LIKE : recherche par motif
-- % = n'importe quelle suite de caractères (0 ou plus)
-- _ = exactement 1 caractère
SELECT * FROM Etudiant WHERE nomEtu LIKE 'A%';       -- Commence par A
SELECT * FROM Etudiant WHERE nomEtu LIKE '%ani';     -- Finit par ani
SELECT * FROM Etudiant WHERE nomEtu LIKE '%ala%';    -- Contient ala
SELECT * FROM Etudiant WHERE numCINEtu LIKE 'A______'; -- A + 6 chars
SELECT * FROM Formation WHERE titreForm LIKE '%Web%';

-- IS NULL / IS NOT NULL (JAMAIS = NULL)
SELECT * FROM Inscription WHERE noteInscription IS NULL;
SELECT * FROM Etudiant WHERE telEtu IS NOT NULL;
-- Erreur classique : WHERE noteInscription = NULL (ne retourne RIEN)
⚠ Piège NULL — ne jamais utiliser = NULL

En SQL, NULL = NULL retourne UNKNOWN (pas TRUE). Toute comparaison avec NULL via =, !=, <, etc. retourne UNKNOWN et la ligne est exclue. Utiliser toujours IS NULL ou IS NOT NULL.


3
ORDER BY, LIMIT et OFFSET
ASC · DESC · Multi-colonnes · Pagination · FIELD()
sqlORDER BY, LIMIT, OFFSET — SkolaBase
-- ORDER BY simple (ASC par défaut)
SELECT * FROM Etudiant ORDER BY nomEtu ASC;
SELECT * FROM Etudiant ORDER BY nomEtu;       -- ASC implicite

-- ORDER BY décroissant
SELECT * FROM Inscription ORDER BY noteInscription DESC;

-- ORDER BY multi-colonnes (1ère colonne prioritaire)
SELECT * FROM Etudiant
ORDER BY villeEtu ASC, nomEtu ASC;
-- Trier par ville, puis par nom dans chaque ville

SELECT * FROM Inscription
ORDER BY noteInscription DESC, numCINEtu ASC;

-- ORDER BY sur alias (ORDER BY est évalué après SELECT)
SELECT nomEtu, prenomEtu,
       CONCAT(prenomEtu, ' ', nomEtu) AS nom_complet
FROM Etudiant
ORDER BY nom_complet ASC;   -- L'alias est utilisable dans ORDER BY

-- LIMIT : retourner seulement N lignes
SELECT * FROM Etudiant LIMIT 3;            -- Les 3 premières lignes
SELECT * FROM Inscription
ORDER BY noteInscription DESC LIMIT 5;     -- Top 5 notes

-- LIMIT + OFFSET : pagination
-- Page 1 : LIMIT 3 OFFSET 0  (lignes 1-3)
-- Page 2 : LIMIT 3 OFFSET 3  (lignes 4-6)
-- Page 3 : LIMIT 3 OFFSET 6  (lignes 7-9)
SELECT * FROM Etudiant
ORDER BY nomEtu
LIMIT 3 OFFSET 0;    -- Page 1

SELECT * FROM Etudiant
ORDER BY nomEtu
LIMIT 3 OFFSET 3;    -- Page 2

-- Syntaxe alternative : LIMIT offset, count
SELECT * FROM Etudiant ORDER BY nomEtu LIMIT 3, 3;  -- Offset 3, count 3

-- ORDER BY personnalisé avec FIELD()
SELECT * FROM Formation
ORDER BY FIELD(niveauForm, 'Technicien', 'Bac', 'Bac+2', 'Bac+3');
-- Trie dans l'ordre spécifié (pas alphabétique)
SELECT * FROM Inscription WHERE noteInscription = NULL — combien de lignes retourne cette requête si 2 inscriptions ont une note NULL ?
On veut les étudiants de Casablanca OU de Rabat dont le nom commence par «A». Quelle requête est correcte ?
Partie 7 — DQL : Interroger les données GROUP BY & HAVING Agrégation · Filtrage groupes
⏱ 18 min

GROUP BY & HAVING

Regrouper les données avec GROUP BY, ordre d'exécution MySQL, différence fondamentale HAVING vs WHERE, combinaison complète SELECT/FROM/WHERE/GROUP BY/HAVING/ORDER BY appliquée aux statistiques SkolaBase.

✓ Ce que vous allez apprendre
  • Comprendre le regroupement : GROUP BY crée des groupes de lignes
  • Ordre d'évaluation : FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY
  • HAVING filtre les groupes (après GROUP BY) vs WHERE filtre les lignes (avant)
  • Combiner WHERE + GROUP BY + HAVING dans une même requête
  • GROUP BY avec ROLLUP pour les sous-totaux

1
GROUP BY — principe et syntaxe
Groupes · Fonctions d'agrégation · Règle de groupement
ℹ Règle fondamentale de GROUP BY

Dans un SELECT avec GROUP BY, chaque colonne du SELECT doit soit faire partie du GROUP BY, soit être encapsulée dans une fonction d'agrégation (COUNT, SUM, AVG, MAX, MIN). Sinon MySQL retourne une erreur (en mode strict) ou une valeur arbitraire.

sqlGROUP BY — statistiques SkolaBase
-- Nombre d'étudiants par ville
SELECT villeEtu, COUNT(*) AS nb_etudiants
FROM Etudiant
GROUP BY villeEtu;
-- Résultat :
-- villeEtu    | nb_etudiants
-- Casablanca  | 2
-- Rabat       | 1
-- Marrakech   | 1

-- Moyenne des notes par session
SELECT
    codeSess,
    COUNT(*)                                AS nb_inscrits,
    COUNT(noteInscription)                  AS nb_notes_saisies,
    AVG(noteInscription)                    AS moyenne,
    MIN(noteInscription)                    AS note_min,
    MAX(noteInscription)                    AS note_max
FROM Inscription
GROUP BY codeSess;

-- Nombre de formations par filière
SELECT
    f.libelleFiliere,
    COUNT(fm.codeForm)  AS nb_formations,
    SUM(fm.dureeForm)   AS heures_totales
FROM Filiere f
    LEFT JOIN Formation fm ON f.codeFiliere = fm.codeFiliere
GROUP BY f.codeFiliere, f.libelleFiliere
ORDER BY nb_formations DESC;

-- GROUP BY avec expression (regrouper par année de début)
SELECT
    YEAR(dateDebutSess)  AS annee,
    COUNT(*)             AS nb_sessions
FROM Session
GROUP BY YEAR(dateDebutSess)
ORDER BY annee;

2
HAVING — filtrer les groupes
HAVING vs WHERE · Fonctions agrégation dans HAVING · Combinaison
CritèreWHEREHAVING
Étape d'évaluationAvant GROUP BY (sur les lignes)Après GROUP BY (sur les groupes)
Peut utiliserColonnes brutes de la tableColonnes brutes ET fonctions d'agrégation
Peut utiliser les alias SELECTNon (SELECT pas encore évalué)Oui dans MySQL (extension)
Exemple SkolaBaseWHERE villeEtu = 'Casablanca'HAVING COUNT(*) > 2
sqlHAVING — filtrer les groupes — SkolaBase
-- Sessions avec plus de 2 inscrits
SELECT codeSess, COUNT(*) AS nb_inscrits
FROM Inscription
GROUP BY codeSess
HAVING COUNT(*) > 2;

-- Étudiants inscrits à plus d'une session
SELECT numCINEtu, COUNT(*) AS nb_sessions
FROM Inscription
GROUP BY numCINEtu
HAVING COUNT(*) > 1;

-- Combinaison WHERE + GROUP BY + HAVING
-- Sessions de 2024 avec moyenne > 13
SELECT
    codeSess,
    AVG(noteInscription) AS moyenne
FROM Inscription
WHERE noteInscription IS NOT NULL      -- WHERE : exclure les notes NULL d'abord
GROUP BY codeSess                      -- GROUP BY : regrouper par session
HAVING AVG(noteInscription) > 13       -- HAVING : garder seulement moyenne > 13
ORDER BY moyenne DESC;

-- WRONG : ne pas mettre une fonction d'agrégation dans WHERE
-- SELECT codeSess FROM Inscription WHERE AVG(noteInscription) > 13;  -- ERREUR
-- La bonne version : utiliser HAVING

-- Filières avec plus de 2 formations de niveau Bac+2
SELECT
    codeFiliere,
    COUNT(*)    AS nb_formations_bac2
FROM Formation
WHERE niveauForm = 'Bac+2'             -- WHERE filtre les lignes individuelles
GROUP BY codeFiliere
HAVING COUNT(*) >= 2;                  -- HAVING filtre les groupes résultants

-- WITH ROLLUP : sous-totaux et total général
SELECT
    COALESCE(villeEtu, 'TOTAL')  AS ville,
    COUNT(*)                      AS nb_etudiants
FROM Etudiant
GROUP BY villeEtu WITH ROLLUP;
-- Ajoute une ligne TOTAL à la fin
Pourquoi SELECT codeSess FROM Inscription WHERE AVG(noteInscription) > 13 GROUP BY codeSess retourne-t-il une erreur ?
La requête suivante veut les villes avec plus de 1 étudiant ne venant PAS de Fès. Laquelle est correcte ?
Partie 7 — DQL : Interroger les données Fonctions SQL Math · Chaînes · Dates
⏱ 22 min

Fonctions SQL

Fonctions mathématiques (ABS, CEIL, FLOOR, ROUND, MOD), fonctions chaînes (CONCAT, LEFT, RIGHT, SUBSTRING, UPPER, LOWER, TRIM, REPLACE, LENGTH), fonctions de dates (CURDATE, NOW, DATEDIFF, DATE_FORMAT, DATE_ADD, TIMESTAMPDIFF) — toutes appliquées à SkolaBase.

✓ Ce que vous allez apprendre
  • Fonctions mathématiques : ABS, CEIL, FLOOR, ROUND, TRUNCATE, MOD, POWER
  • Fonctions chaînes : CONCAT, LENGTH, UPPER/LOWER, TRIM, LEFT/RIGHT, SUBSTRING, REPLACE, LPAD/RPAD
  • Fonctions de dates : CURDATE, NOW, YEAR/MONTH/DAY, DATEDIFF, DATE_ADD, DATE_FORMAT, TIMESTAMPDIFF

1
Fonctions mathématiques
ABS · CEIL · FLOOR · ROUND · TRUNCATE · MOD · POWER · SQRT
sqlFonctions mathématiques — SkolaBase
-- ABS : valeur absolue
SELECT ABS(-14.5);          -- 14.5
SELECT ABS(noteInscription - 10) AS ecart_au_seuil
FROM Inscription;

-- CEIL / CEILING : arrondir vers le haut (entier supérieur)
SELECT CEIL(13.1);          -- 14
SELECT CEIL(13.0);          -- 13

-- FLOOR : arrondir vers le bas (entier inférieur)
SELECT FLOOR(13.9);         -- 13

-- ROUND : arrondir au plus proche (n décimales)
SELECT ROUND(13.456, 2);    -- 13.46
SELECT ROUND(13.454, 2);    -- 13.45
SELECT ROUND(13.5);         -- 14  (0 décimales)

-- TRUNCATE : tronquer sans arrondir
SELECT TRUNCATE(13.999, 2); -- 13.99  (pas d'arrondi)
SELECT TRUNCATE(13.999, 0); -- 13

-- MOD : modulo (reste de la division)
SELECT MOD(17, 5);          -- 2
SELECT MOD(numFormateur, 2) AS parite FROM Formateur;
-- 0 = pair, 1 = impair

-- POWER / POW : puissance
SELECT POWER(2, 10);        -- 1024
-- SQRT : racine carrée
SELECT SQRT(144);           -- 12

-- Exemple concret : arrondir les moyennes à 2 décimales
SELECT
    codeSess,
    ROUND(AVG(noteInscription), 2) AS moyenne_arrondie
FROM Inscription
WHERE noteInscription IS NOT NULL
GROUP BY codeSess;

2
Fonctions sur les chaînes de caractères
CONCAT · LENGTH · UPPER/LOWER · TRIM · SUBSTRING · REPLACE · LPAD
sqlFonctions chaînes — SkolaBase
-- CONCAT : concaténer des chaînes
SELECT CONCAT(prenomEtu, ' ', nomEtu) AS nom_complet FROM Etudiant;
SELECT CONCAT('ETU-', numCINEtu) AS code_etudiant FROM Etudiant;

-- CONCAT_WS : concaténer avec séparateur (WS = With Separator)
SELECT CONCAT_WS(' - ', nomEtu, prenomEtu, villeEtu) AS fiche FROM Etudiant;
-- Alaoui - Karim - Casablanca

-- LENGTH : longueur en octets (CHAR_LENGTH pour les caractères)
SELECT nomEtu, LENGTH(nomEtu) AS longueur FROM Etudiant;
SELECT nomEtu, CHAR_LENGTH(nomEtu) AS nb_chars FROM Etudiant;
-- LENGTH != CHAR_LENGTH pour les caractères UTF-8 multi-octets (ç, é, ب...)

-- UPPER / LOWER : majuscules / minuscules
SELECT UPPER(nomEtu) AS nom_maj FROM Etudiant;   -- ALAOUI
SELECT LOWER(nomEtu) AS nom_min FROM Etudiant;   -- alaoui

-- TRIM / LTRIM / RTRIM : supprimer les espaces
SELECT TRIM('  Karim  ');        -- 'Karim'
SELECT LTRIM('  Karim');         -- 'Karim' (espaces gauche)
SELECT RTRIM('Karim  ');         -- 'Karim' (espaces droite)

-- LEFT / RIGHT : extraire N caractères à gauche/droite
SELECT LEFT(numCINEtu, 1)  AS lettre_cin FROM Etudiant;    -- 'A', 'B', 'C'...
SELECT RIGHT(numCINEtu, 7) AS chiffres_cin FROM Etudiant;  -- '1234567'

-- SUBSTRING / SUBSTR : extraire une sous-chaîne
SELECT SUBSTRING(numCINEtu, 2, 7) AS chiffres FROM Etudiant;
-- Depuis position 2, 7 caractères

SELECT SUBSTRING(codeSess, 6, 4) AS annee_sess FROM Session;
-- 'SESS-2024-01' → '2024'

-- REPLACE : remplacer une sous-chaîne
SELECT REPLACE(titreForm, 'Développement', 'Dev') FROM Formation;
SELECT REPLACE(nomEtu, 'El ', '') AS nom_court FROM Etudiant;

-- LPAD / RPAD : compléter avec un caractère
SELECT LPAD(numFormateur, 4, '0') AS code_form FROM Formateur;
-- 1 → '0001',  12 → '0012'

-- LOCATE / POSITION : trouver la position d'une sous-chaîne
SELECT LOCATE('Web', titreForm) AS pos_web FROM Formation;
-- 0 = non trouvé, > 0 = position

-- INSTR : similaire à LOCATE
SELECT titreForm FROM Formation WHERE INSTR(titreForm, 'Web') > 0;

3
Fonctions de dates et heures
CURDATE · NOW · YEAR/MONTH/DAY · DATEDIFF · DATE_ADD · DATE_FORMAT · TIMESTAMPDIFF
sqlFonctions de dates — SkolaBase
-- Date et heure actuelles
SELECT CURDATE();               -- '2024-11-15'  (date seule)
SELECT CURTIME();               -- '14:23:05'    (heure seule)
SELECT NOW();                   -- '2024-11-15 14:23:05'
SELECT SYSDATE();               -- Similaire à NOW()

-- Extraire des parties de date
SELECT
    dateNaissEtu,
    YEAR(dateNaissEtu)   AS annee,
    MONTH(dateNaissEtu)  AS mois,
    DAY(dateNaissEtu)    AS jour,
    DAYNAME(dateNaissEtu) AS jour_semaine,   -- 'Monday', 'Tuesday'...
    MONTHNAME(dateNaissEtu) AS nom_mois      -- 'January', 'February'...
FROM Etudiant;

-- DATEDIFF : différence en jours
SELECT
    codeSess,
    dateDebutSess,
    dateFinSess,
    DATEDIFF(dateFinSess, dateDebutSess) AS duree_jours
FROM Session;

-- Âge en années avec TIMESTAMPDIFF
SELECT
    numCINEtu,
    CONCAT(prenomEtu, ' ', nomEtu) AS nom_complet,
    TIMESTAMPDIFF(YEAR, dateNaissEtu, CURDATE()) AS age
FROM Etudiant
ORDER BY age;

-- DATE_ADD / DATE_SUB : ajouter/soustraire un intervalle
SELECT DATE_ADD(CURDATE(), INTERVAL 30 DAY)  AS dans_30_jours;
SELECT DATE_ADD(CURDATE(), INTERVAL 3 MONTH) AS dans_3_mois;
SELECT DATE_SUB(CURDATE(), INTERVAL 1 YEAR)  AS il_y_a_1_an;

-- Intervalles disponibles : SECOND, MINUTE, HOUR, DAY, WEEK, MONTH, YEAR

-- DATE_FORMAT : formater une date
SELECT DATE_FORMAT(dateDebutSess, '%d/%m/%Y') AS date_fr
FROM Session;
-- '02/09/2024'

SELECT DATE_FORMAT(dateDebutSess, '%W %d %M %Y') AS date_longue
FROM Session;
-- 'Monday 02 September 2024'

SELECT DATE_FORMAT(dateDebutSess, '%Y-%m') AS annee_mois
FROM Session
GROUP BY DATE_FORMAT(dateDebutSess, '%Y-%m');
-- Grouper par mois : '2024-09', '2024-10'...

-- WEEK / WEEKOFYEAR : numéro de semaine
SELECT codeSess, WEEK(dateDebutSess) AS semaine FROM Session;

-- Sessions dont la date de fin est dépassée
SELECT codeSess, dateFinSess
FROM Session
WHERE dateFinSess < CURDATE();

-- Sessions en cours aujourd'hui
SELECT codeSess, dateDebutSess, dateFinSess
FROM Session
WHERE CURDATE() BETWEEN dateDebutSess AND dateFinSess;
FormatSignificationExemple
%YAnnée 4 chiffres2024
%yAnnée 2 chiffres24
%mMois 2 chiffres (01–12)09
%MNom du moisSeptember
%dJour 2 chiffres (01–31)02
%DJour avec suffixe2nd
%WNom du jourMonday
%HHeure (00–23)14
%iMinutes (00–59)23
%sSecondes (00–59)05
SELECT LENGTH('Casablanca') vs SELECT CHAR_LENGTH('Casablanca') — même résultat ? Et pour 'Fès' ?
Partie 7 — DQL : Interroger les données Fonctions d'agrégation COUNT · SUM · AVG · MIN · MAX
⏱ 16 min

Fonctions d'agrégation

Maîtriser les 5 fonctions d'agrégation — COUNT(*) vs COUNT(col), SUM, AVG, MIN, MAX — comportement avec NULL, COUNT(DISTINCT), et application aux statistiques complètes de SkolaBase.

✓ Ce que vous allez apprendre
  • COUNT(*) vs COUNT(colonne) — différence avec les valeurs NULL
  • SUM, AVG — comportement avec NULL (ignoré automatiquement)
  • MIN, MAX — sur numériques, chaînes et dates
  • COUNT(DISTINCT col) — compter les valeurs uniques
  • Combiner plusieurs fonctions d'agrégation dans un même SELECT

1
COUNT — COUNT(*) vs COUNT(colonne)
NULL ignoré · COUNT DISTINCT · Compter les valeurs
ℹ COUNT(*) vs COUNT(col) — différence critique

COUNT(*) compte toutes les lignes du groupe, y compris celles avec des NULL. COUNT(colonne) compte uniquement les lignes où la colonne n'est pas NULL. Exemple : si 7 inscriptions dont 1 avec noteInscription = NULL, alors COUNT(*) = 7 et COUNT(noteInscription) = 6.

sqlCOUNT — exemples SkolaBase
-- COUNT(*) : toutes les lignes (y compris NULL)
SELECT COUNT(*) AS total_inscriptions FROM Inscription;   -- 7

-- COUNT(colonne) : ignorer les NULL
SELECT COUNT(noteInscription) AS notes_saisies FROM Inscription;  -- 6

-- Voir la différence
SELECT
    COUNT(*)                AS total_inscrits,
    COUNT(noteInscription)  AS notes_saisies,
    COUNT(*) - COUNT(noteInscription) AS notes_manquantes
FROM Inscription;

-- COUNT(DISTINCT) : compter les valeurs uniques
SELECT COUNT(DISTINCT numCINEtu) AS nb_etudiants_inscrits
FROM Inscription;
-- Nombre d'étudiants différents qui ont au moins une inscription

SELECT COUNT(DISTINCT villeEtu) AS nb_villes FROM Etudiant;

-- Statistiques complètes par session
SELECT
    codeSess,
    COUNT(*)                            AS nb_inscrits,
    COUNT(noteInscription)              AS notes_saisies,
    COUNT(*) - COUNT(noteInscription)   AS notes_manquantes,
    ROUND(AVG(noteInscription), 2)      AS moyenne,
    MIN(noteInscription)                AS note_min,
    MAX(noteInscription)                AS note_max,
    SUM(noteInscription)                AS total_notes
FROM Inscription
GROUP BY codeSess
ORDER BY codeSess;

2
SUM, AVG, MIN, MAX — comportement et cas d'usage
NULL ignoré · MIN/MAX sur dates · Statistiques SkolaBase
sqlSUM, AVG, MIN, MAX — SkolaBase
-- Toutes les fonctions ignorent automatiquement les NULL
SELECT
    SUM(noteInscription)    AS somme,     -- Somme des notes non-NULL
    AVG(noteInscription)    AS moyenne,   -- Moyenne des notes non-NULL
    MIN(noteInscription)    AS note_min,
    MAX(noteInscription)    AS note_max
FROM Inscription;

-- MIN / MAX sur des chaînes (ordre alphabétique)
SELECT MIN(nomEtu) AS premier_alpha, MAX(nomEtu) AS dernier_alpha
FROM Etudiant;

-- MIN / MAX sur des dates
SELECT
    MIN(dateDebutSess) AS premiere_session,
    MAX(dateFinSess)   AS derniere_fin
FROM Session;

-- Total des heures de formation par filière
SELECT
    fi.libelleFiliere,
    SUM(fo.dureeForm)   AS total_heures,
    AVG(fo.dureeForm)   AS duree_moyenne,
    COUNT(fo.codeForm)  AS nb_formations
FROM Filiere fi
    JOIN Formation fo ON fi.codeFiliere = fo.codeFiliere
GROUP BY fi.codeFiliere, fi.libelleFiliere
ORDER BY total_heures DESC;

-- Taux de réussite par session (note >= 10)
SELECT
    codeSess,
    COUNT(*) AS total,
    SUM(CASE WHEN noteInscription >= 10 THEN 1 ELSE 0 END) AS admis,
    ROUND(100 * SUM(CASE WHEN noteInscription >= 10 THEN 1 ELSE 0 END)
          / COUNT(noteInscription), 1) AS taux_reussite_pct
FROM Inscription
WHERE noteInscription IS NOT NULL
GROUP BY codeSess;
La table Inscription a 7 lignes dont 1 avec noteInscription = NULL. Quel est le résultat de AVG(noteInscription) ?
Partie 7 — DQL : Interroger les données Expressions & Opérateurs CASE · IF · COALESCE · NULLIF
⏱ 16 min

Expressions & Opérateurs avancés

Opérateurs arithmétiques, logiques et de comparaison, expressions conditionnelles CASE WHEN et IF(), gestion des NULL avec COALESCE et NULLIF, et précédence des opérateurs.

✓ Ce que vous allez apprendre
  • Opérateurs arithmétiques : +, -, *, /, DIV, MOD
  • Précédence des opérateurs et rôle des parenthèses
  • CASE WHEN ... THEN ... ELSE ... END — expression conditionnelle puissante
  • IF(condition, valeur_vrai, valeur_faux) — ternaire SQL
  • COALESCE(a, b, c) — première valeur non-NULL
  • NULLIF(a, b) — retourner NULL si a = b

1
Opérateurs arithmétiques et précédence
+ - * / · DIV · MOD · Priorité · Parenthèses
sqlOpérateurs arithmétiques — SkolaBase
-- Opérateurs de base
SELECT 10 + 3;    -- 13   addition
SELECT 10 - 3;    -- 7    soustraction
SELECT 10 * 3;    -- 30   multiplication
SELECT 10 / 3;    -- 3.33 division réelle (DECIMAL)
SELECT 10 DIV 3;  -- 3    division entière
SELECT 10 MOD 3;  -- 1    modulo (reste)
SELECT 10 % 3;    -- 1    alias de MOD

-- Priorité : * / avant + - (comme en mathématiques)
SELECT 2 + 3 * 4;     -- 14  (pas 20)
SELECT (2 + 3) * 4;   -- 20

-- Applications SkolaBase
SELECT
    codeSess,
    dureeForm,
    dureeForm * 60        AS duree_minutes,
    dureeForm / 8         AS duree_jours,
    ROUND(dureeForm / 8)  AS duree_jours_arrondis
FROM Session
    JOIN Formation USING (codeForm);

-- Bonus de 5% sur les notes < 14, plafonné à 20
SELECT
    numCINEtu,
    noteInscription AS note_initiale,
    LEAST(noteInscription * 1.05, 20) AS note_avec_bonus
FROM Inscription
WHERE noteInscription < 14 AND noteInscription IS NOT NULL;

2
CASE WHEN — expression conditionnelle
CASE simple · CASE recherché · IF() · IIF
sqlCASE WHEN — mention et appréciation des notes SkolaBase
-- CASE recherché (condition booléenne — le plus flexible)
SELECT
    numCINEtu,
    codeSess,
    noteInscription,
    CASE
        WHEN noteInscription IS NULL    THEN 'Non évalué'
        WHEN noteInscription >= 18      THEN 'Excellent'
        WHEN noteInscription >= 14      THEN 'Bien'
        WHEN noteInscription >= 12      THEN 'Assez bien'
        WHEN noteInscription >= 10      THEN 'Passable'
        ELSE                                 'Insuffisant'
    END AS mention
FROM Inscription;

-- CASE simple (comparer une colonne à des valeurs)
SELECT
    codeFiliere,
    CASE codeFiliere
        WHEN 'INF' THEN 'Informatique'
        WHEN 'GES' THEN 'Gestion'
        WHEN 'ELE' THEN 'Électronique'
        ELSE             'Autre filière'
    END AS libelle_court
FROM Formation;

-- CASE dans GROUP BY / HAVING (classifier puis compter)
SELECT
    CASE
        WHEN noteInscription >= 10 THEN 'Admis'
        ELSE 'Refusé'
    END AS statut,
    COUNT(*) AS nb
FROM Inscription
WHERE noteInscription IS NOT NULL
GROUP BY statut;

-- IF() : version courte pour 2 cas seulement
SELECT
    numCINEtu,
    noteInscription,
    IF(noteInscription >= 10, 'Admis', 'Refusé') AS decision
FROM Inscription;

-- IF() dans SUM pour compter conditionnellement
SELECT
    SUM(IF(noteInscription >= 10, 1, 0))    AS nb_admis,
    SUM(IF(noteInscription < 10, 1, 0))     AS nb_refusés,
    COUNT(noteInscription)                   AS total_notes
FROM Inscription;

3
COALESCE et NULLIF — gestion des NULL
COALESCE · NULLIF · IFNULL · Valeur de remplacement
sqlCOALESCE, NULLIF, IFNULL — SkolaBase
-- COALESCE(a, b, c) : retourne la première valeur non-NULL
SELECT
    numCINEtu,
    COALESCE(telEtu, 'Téléphone non renseigné') AS contact
FROM Etudiant;
-- Si telEtu = NULL → 'Téléphone non renseigné'
-- Si telEtu = '0612345678' → '0612345678'

-- COALESCE avec plusieurs alternatives
SELECT
    COALESCE(telEtu, emailEtu, numCINEtu) AS contact_prioritaire
FROM Etudiant;
-- Essaie tel, puis email, puis CIN (toujours non-NULL)

-- Afficher les notes avec valeur par défaut
SELECT
    numCINEtu,
    codeSess,
    COALESCE(noteInscription, 0)  AS note_affichee   -- 0 si NULL
FROM Inscription;

-- IFNULL(col, valeur_si_null) : version MySQL de COALESCE à 2 args
SELECT
    numCINEtu,
    IFNULL(noteInscription, 'À évaluer') AS note
FROM Inscription;

-- NULLIF(a, b) : retourne NULL si a = b, sinon retourne a
-- Utilité : éviter la division par zéro
SELECT
    codeSess,
    SUM(noteInscription) / NULLIF(COUNT(noteInscription), 0) AS moyenne_securisee
FROM Inscription
GROUP BY codeSess;
-- Si COUNT = 0 (aucune note) → NULLIF retourne NULL → division évitée

-- Exemple : transformer 0 en NULL (ignorer les 0 dans une moyenne)
SELECT AVG(NULLIF(noteInscription, 0)) AS moyenne_sans_zeros
FROM Inscription;
Quelle est la différence entre IF(noteInscription >= 10, 'Admis', 'Refusé') et CASE WHEN noteInscription >= 10 THEN 'Admis' ELSE 'Refusé' END pour les notes NULL ?
COALESCE(telEtu, emailEtu, 'Inconnu') — si telEtu = NULL et emailEtu = 'karim@mail.com', que retourne cette expression ?
Partie 8 — Requêtes avancées Sous-requêtes I Mono-ligne · IN · NOT IN
⏱ 18 min

Sous-requêtes I — mono-ligne & IN

Définition et positionnement des sous-requêtes (SELECT, FROM, WHERE, HAVING), sous-requêtes mono-ligne (=, >, <), sous-requêtes multi-lignes avec IN et NOT IN, et sous-requêtes scalaires dans le SELECT.

✓ Ce que vous allez apprendre
  • Définir une sous-requête et ses 4 positions possibles (SELECT, FROM, WHERE, HAVING)
  • Sous-requête mono-ligne : retourne une seule valeur, utilisée avec =, >, <, >=, <=
  • Sous-requête multi-lignes avec IN et NOT IN
  • Sous-requête scalaire dans le SELECT (colonne calculée)
  • Sous-requête dans le FROM (table dérivée)

1
Définition et positionnement des sous-requêtes
Requête imbriquée · SELECT/FROM/WHERE/HAVING · Exécution
ℹ Qu'est-ce qu'une sous-requête ?

Une sous-requête (ou requête imbriquée) est un SELECT placé à l'intérieur d'une autre requête SQL. Elle est toujours entre parenthèses. La sous-requête est exécutée en premier et son résultat est utilisé par la requête externe. Elle permet de répondre à des questions en deux étapes : d'abord trouver une valeur ou un ensemble de valeurs, puis utiliser ce résultat comme filtre.

sql4 positions d'une sous-requête
-- Position 1 : dans le SELECT (sous-requête scalaire)
SELECT
    nomEtu,
    (SELECT COUNT(*) FROM Inscription WHERE numCINEtu = e.numCINEtu) AS nb_inscriptions
FROM Etudiant e;

-- Position 2 : dans le FROM (table dérivée — doit avoir un alias)
SELECT *
FROM (
    SELECT codeSess, AVG(noteInscription) AS moyenne
    FROM Inscription
    WHERE noteInscription IS NOT NULL
    GROUP BY codeSess
) AS stats_sessions
WHERE moyenne > 13;

-- Position 3 : dans le WHERE (la plus courante)
SELECT * FROM Etudiant
WHERE numCINEtu IN (
    SELECT numCINEtu FROM Inscription WHERE noteInscription >= 14
);

-- Position 4 : dans le HAVING
SELECT codeSess, AVG(noteInscription) AS moy
FROM Inscription
GROUP BY codeSess
HAVING AVG(noteInscription) > (
    SELECT AVG(noteInscription) FROM Inscription
);

2
Sous-requêtes mono-ligne — avec = > <
Une seule valeur retournée · Opérateurs de comparaison · Erreur si multi-lignes
⚠ Une sous-requête mono-ligne doit retourner EXACTEMENT une valeur

Si la sous-requête utilisée avec = retourne plusieurs lignes, MySQL retourne une erreur : Subquery returns more than 1 row. Si elle retourne zéro ligne, la comparaison retourne NULL (et la ligne est exclue). Vérifier que la sous-requête retourne toujours exactement une valeur.

sqlSous-requêtes mono-ligne — SkolaBase
-- Étudiants dont la note > moyenne générale
SELECT numCINEtu, noteInscription
FROM Inscription
WHERE noteInscription > (
    SELECT AVG(noteInscription)
    FROM Inscription
    WHERE noteInscription IS NOT NULL
);

-- Session avec la durée de formation la plus longue
SELECT codeSess, dateDebutSess
FROM Session
WHERE codeForm = (
    SELECT codeForm
    FROM Formation
    WHERE dureeForm = (SELECT MAX(dureeForm) FROM Formation)
);

-- Étudiant avec la meilleure note (unique)
SELECT e.numCINEtu, e.nomEtu, e.prenomEtu, i.noteInscription
FROM Etudiant e
    JOIN Inscription i ON e.numCINEtu = i.numCINEtu
WHERE i.noteInscription = (
    SELECT MAX(noteInscription) FROM Inscription
);

-- Formateur qui anime la session la plus récente
SELECT nomFormateur, prenomFormateur
FROM Formateur
WHERE numFormateur = (
    SELECT numFormateur
    FROM Session
    ORDER BY dateDebutSess DESC
    LIMIT 1
);

3
Sous-requêtes multi-lignes — IN et NOT IN
IN · NOT IN · Piège NULL avec NOT IN · Table dérivée
sqlIN et NOT IN — SkolaBase
-- IN : étudiants qui ont au moins une inscription
SELECT numCINEtu, nomEtu, prenomEtu
FROM Etudiant
WHERE numCINEtu IN (
    SELECT DISTINCT numCINEtu FROM Inscription
);

-- NOT IN : étudiants sans aucune inscription
SELECT numCINEtu, nomEtu, prenomEtu
FROM Etudiant
WHERE numCINEtu NOT IN (
    SELECT DISTINCT numCINEtu FROM Inscription
);

-- Formations qui ont au moins une session
SELECT codeForm, titreForm
FROM Formation
WHERE codeForm IN (
    SELECT DISTINCT codeForm FROM Session
);

-- Sessions avec note moyenne > 13
SELECT codeSess, dateDebutSess
FROM Session
WHERE codeSess IN (
    SELECT codeSess
    FROM Inscription
    WHERE noteInscription IS NOT NULL
    GROUP BY codeSess
    HAVING AVG(noteInscription) > 13
);

-- Table dérivée : les 3 meilleures sessions par moyenne
SELECT s.codeSess, s.dateDebutSess, stats.moyenne
FROM Session s
    JOIN (
        SELECT codeSess, ROUND(AVG(noteInscription), 2) AS moyenne
        FROM Inscription
        WHERE noteInscription IS NOT NULL
        GROUP BY codeSess
    ) AS stats ON s.codeSess = stats.codeSess
ORDER BY stats.moyenne DESC
LIMIT 3;
⚠ Piège critique — NOT IN avec des NULL

Si la sous-requête de NOT IN contient au moins un NULL, le résultat entier est vide (0 lignes) ! En effet, x NOT IN (1, 2, NULL) équivaut à x != 1 AND x != 2 AND x != NULL — et x != NULL retourne toujours UNKNOWN. Solution : ajouter WHERE colonne IS NOT NULL dans la sous-requête.

La sous-requête WHERE numCINEtu = (SELECT numCINEtu FROM Inscription WHERE noteInscription > 15) retourne une erreur. Pourquoi ?
WHERE numCINEtu NOT IN (SELECT numCINEtu FROM Inscription WHERE noteInscription IS NULL) — si la sous-requête retourne (NULL, 'A123', 'B456'), combien de lignes retourne la requête externe ?
Partie 8 — Requêtes avancées Sous-requêtes II ALL · ANY · EXISTS · Corrélées
⏱ 18 min

Sous-requêtes II — ALL, ANY, EXISTS

ALL (comparaison avec toutes les valeurs), ANY/SOME (au moins une valeur), EXISTS et NOT EXISTS (test d'existence), sous-requêtes corrélées (référencent la requête externe), et comparaison avec les jointures.

✓ Ce que vous allez apprendre
  • ALL — vraie si la condition est vraie pour toutes les valeurs
  • ANY / SOME — vraie si la condition est vraie pour au moins une valeur
  • EXISTS — vrai si la sous-requête retourne au moins une ligne
  • NOT EXISTS — vrai si la sous-requête retourne zéro ligne
  • Sous-requêtes corrélées — exécutées une fois par ligne de la requête externe

1
ALL et ANY — comparaisons ensemblistes
ALL = toutes · ANY = au moins une · SOME = alias ANY
sqlALL et ANY — SkolaBase
-- ALL : vrai si la comparaison est vraie pour TOUTES les valeurs
-- Étudiants dont la note est > TOUTES les notes de la session SESS-2024-02
SELECT numCINEtu, noteInscription
FROM Inscription
WHERE codeSess = 'SESS-2024-01'
  AND noteInscription > ALL (
      SELECT noteInscription
      FROM Inscription
      WHERE codeSess = 'SESS-2024-02'
        AND noteInscription IS NOT NULL
  );
-- Revient à : note > MAX(notes de SESS-2024-02)

-- Formations dont la durée est > TOUTES les formations de filière GES
SELECT codeForm, titreForm, dureeForm
FROM Formation
WHERE dureeForm > ALL (
    SELECT dureeForm FROM Formation WHERE codeFiliere = 'GES'
);
-- Équivalent à : dureeForm > MAX(durée des formations GES)

-- ANY : vrai si la comparaison est vraie pour AU MOINS UNE valeur
-- Étudiants dont la note est > n'importe quelle note de SESS-2024-02
SELECT numCINEtu, noteInscription
FROM Inscription
WHERE codeSess = 'SESS-2024-01'
  AND noteInscription > ANY (
      SELECT noteInscription
      FROM Inscription
      WHERE codeSess = 'SESS-2024-02'
        AND noteInscription IS NOT NULL
  );
-- Revient à : note > MIN(notes de SESS-2024-02)
OpérateurSignificationÉquivalent agrégat
= ANYÉgal à au moins une valeurÉquivalent à IN
<> ALLDifférent de toutes les valeursÉquivalent à NOT IN
> ALLSupérieur à la valeur maximaleÉquivalent à > MAX(...)
> ANYSupérieur à la valeur minimaleÉquivalent à > MIN(...)
< ALLInférieur à la valeur minimaleÉquivalent à < MIN(...)
< ANYInférieur à la valeur maximaleÉquivalent à < MAX(...)

2
EXISTS et NOT EXISTS
Test d'existence · Semi-jointure · Performance · Anti-jointure
ℹ EXISTS — logique et performance

EXISTS teste si une sous-requête retourne au moins une ligne. MySQL s'arrête dès la première ligne trouvée — très efficace. La convention SELECT 1 ou SELECT * dans la sous-requête EXISTS est habituelle (la valeur retournée n'importe pas, seule l'existence compte). Avantage sur IN : pas de problème avec les NULL.

sqlEXISTS et NOT EXISTS — SkolaBase
-- EXISTS : étudiants qui ont AU MOINS UNE inscription
SELECT numCINEtu, nomEtu, prenomEtu
FROM Etudiant e
WHERE EXISTS (
    SELECT 1
    FROM Inscription i
    WHERE i.numCINEtu = e.numCINEtu   -- référence à la requête externe (corrélée)
);
-- MySQL arrête dès la 1ère inscription trouvée → très rapide

-- NOT EXISTS : étudiants SANS aucune inscription
SELECT numCINEtu, nomEtu, prenomEtu
FROM Etudiant e
WHERE NOT EXISTS (
    SELECT 1
    FROM Inscription i
    WHERE i.numCINEtu = e.numCINEtu
);
-- Avantage sur NOT IN : pas de piège NULL

-- Formateurs qui n'ont animé AUCUNE session
SELECT numFormateur, nomFormateur
FROM Formateur f
WHERE NOT EXISTS (
    SELECT 1 FROM Session s
    WHERE s.numFormateur = f.numFormateur
);

-- Sessions qui n'ont aucun inscrit
SELECT codeSess, dateDebutSess
FROM Session s
WHERE NOT EXISTS (
    SELECT 1 FROM Inscription i
    WHERE i.codeSess = s.codeSess
);

-- Étudiants inscrits à TOUTES les sessions de 2024 (division relationnelle)
-- Formulation : étudiants pour lesquels il n'existe PAS de session 2024
-- à laquelle ils ne sont PAS inscrits
SELECT numCINEtu, nomEtu
FROM Etudiant e
WHERE NOT EXISTS (
    SELECT codeSess
    FROM Session
    WHERE YEAR(dateDebutSess) = 2024
    AND codeSess NOT IN (
        SELECT codeSess FROM Inscription
        WHERE numCINEtu = e.numCINEtu
    )
);

3
Sous-requêtes corrélées
Référence externe · Exécution par ligne · Performance · Alias obligatoire
ℹ Sous-requête corrélée — définition

Une sous-requête corrélée référence une colonne de la requête externe (via son alias). Elle est réexécutée pour chaque ligne de la requête externe. Plus lente qu'une sous-requête non-corrélée (qui s'exécute une seule fois), mais parfois inévitable. Sur les grandes tables, préférer une jointure à une sous-requête corrélée.

sqlSous-requêtes corrélées — SkolaBase
-- Pour chaque étudiant, compter ses inscriptions (sous-requête corrélée)
SELECT
    e.numCINEtu,
    e.nomEtu,
    (SELECT COUNT(*)
     FROM Inscription i
     WHERE i.numCINEtu = e.numCINEtu) AS nb_inscriptions
FROM Etudiant e;
-- La sous-requête est exécutée une fois par étudiant

-- Pour chaque étudiant, afficher sa meilleure note
SELECT
    e.numCINEtu,
    e.nomEtu,
    (SELECT MAX(noteInscription)
     FROM Inscription i
     WHERE i.numCINEtu = e.numCINEtu) AS meilleure_note
FROM Etudiant e;

-- Étudiants dont la note dans SESS-2024-01 est supérieure à leur propre moyenne
SELECT numCINEtu, noteInscription AS note_sess01
FROM Inscription i1
WHERE codeSess = 'SESS-2024-01'
  AND noteInscription > (
      SELECT AVG(noteInscription)
      FROM Inscription i2
      WHERE i2.numCINEtu = i1.numCINEtu   -- corrélation : même étudiant
        AND noteInscription IS NOT NULL
  );
Pourquoi NOT EXISTS est-il généralement préféré à NOT IN quand la sous-requête peut contenir des NULL ?
Partie 8 — Requêtes avancées Opérateurs ensemblistes UNION · UNION ALL · INTERSECT · EXCEPT
⏱ 16 min

Opérateurs ensemblistes

UNION et UNION ALL, conditions de compatibilité, émulation de INTERSECT et EXCEPT/MINUS sous MySQL, diagrammes de Venn, tri et ORDER BY sur les résultats d'union.

✓ Ce que vous allez apprendre
  • Conditions de compatibilité pour UNION : même nombre de colonnes, types compatibles
  • UNION — union sans doublons (plus lent, dédoublonnage)
  • UNION ALL — union avec doublons (plus rapide, pas de dédoublonnage)
  • Émuler INTERSECT avec INNER JOIN ou IN
  • Émuler EXCEPT/MINUS avec LEFT JOIN ... IS NULL ou NOT IN

1
UNION et UNION ALL
Conditions · Doublons · Noms colonnes · ORDER BY global
ℹ Conditions de compatibilité pour UNION

Pour combiner deux SELECT avec UNION : (1) même nombre de colonnes dans chaque SELECT, (2) colonnes dans le même ordre avec des types compatibles. Les noms des colonnes dans le résultat final viennent du premier SELECT. ORDER BY s'applique au résultat global (après l'union), pas à chaque SELECT individuel.

sqlUNION et UNION ALL — SkolaBase
-- UNION : combiner noms de toutes les personnes (sans doublons)
SELECT nomFormateur AS nom, prenomFormateur AS prenom, 'Formateur' AS role
FROM Formateur
UNION
SELECT nomEtu, prenomEtu, 'Etudiant'
FROM Etudiant;
-- Les noms des colonnes viennent du 1er SELECT
-- Les doublons (même nom+prénom) sont supprimés

-- UNION ALL : garder tous (avec doublons potentiels, plus rapide)
SELECT nomFormateur AS nom, 'Formateur' AS type FROM Formateur
UNION ALL
SELECT nomEtu, 'Etudiant' FROM Etudiant;
-- Plus rapide car pas de déduplication

-- ORDER BY sur le résultat global (placer à la fin)
SELECT nomEtu AS nom, villeEtu AS ville FROM Etudiant
UNION ALL
SELECT nomFormateur, 'Casablanca' FROM Formateur
ORDER BY nom ASC;    -- Trie TOUT le résultat

-- Rapport unifié : toutes les activités de 2024
SELECT 'Inscription' AS type_activite, numCINEtu AS reference,
       codeSess AS detail, NULL AS note
FROM Inscription
WHERE codeSess LIKE '%2024%'
UNION ALL
SELECT 'Session', codeSess, codeForm, NULL
FROM Session
WHERE YEAR(dateDebutSess) = 2024
ORDER BY type_activite, reference;

2
Émuler INTERSECT et EXCEPT sous MySQL
INTERSECT → INNER JOIN / IN · EXCEPT → LEFT JOIN IS NULL / NOT IN
ℹ MySQL 8.0 — INTERSECT et EXCEPT natifs

MySQL 8.0.31+ supporte INTERSECT et EXCEPT nativement. Sur les versions antérieures, il faut les émuler. Dans tous les cas, connaître les équivalences permet de choisir la solution la plus performante.

sqlINTERSECT et EXCEPT — natif MySQL 8 et émulation
-- INTERSECT natif (MySQL 8.0.31+)
-- Étudiants inscrits à SESS-2024-01 ET à SESS-2024-02
SELECT numCINEtu FROM Inscription WHERE codeSess = 'SESS-2024-01'
INTERSECT
SELECT numCINEtu FROM Inscription WHERE codeSess = 'SESS-2024-02';

-- Émulation INTERSECT avec IN (compatible toutes versions MySQL)
SELECT DISTINCT numCINEtu
FROM Inscription
WHERE codeSess = 'SESS-2024-01'
  AND numCINEtu IN (
      SELECT numCINEtu FROM Inscription WHERE codeSess = 'SESS-2024-02'
  );

-- EXCEPT natif (MySQL 8.0.31+)
-- Étudiants inscrits à SESS-2024-01 MAIS PAS à SESS-2024-02
SELECT numCINEtu FROM Inscription WHERE codeSess = 'SESS-2024-01'
EXCEPT
SELECT numCINEtu FROM Inscription WHERE codeSess = 'SESS-2024-02';

-- Émulation EXCEPT avec NOT IN
SELECT DISTINCT numCINEtu
FROM Inscription
WHERE codeSess = 'SESS-2024-01'
  AND numCINEtu NOT IN (
      SELECT numCINEtu
      FROM Inscription
      WHERE codeSess = 'SESS-2024-02'
  );

-- Émulation EXCEPT avec LEFT JOIN (plus performant sur grandes tables)
SELECT DISTINCT i1.numCINEtu
FROM Inscription i1
    LEFT JOIN Inscription i2
        ON i1.numCINEtu = i2.numCINEtu AND i2.codeSess = 'SESS-2024-02'
WHERE i1.codeSess = 'SESS-2024-01'
  AND i2.numCINEtu IS NULL;   -- IS NULL = pas de correspondance à droite
textDiagrammes de Venn — opérateurs ensemblistes
   UNION                  INTERSECT              EXCEPT (A - B)
  A ┌───┐B            A ┌───┐B            A ┌───┐B
  ████████             ░░░██░░             ███░░░░
Tout A + tout B       Seulement            Seulement dans A,
(sans doublons)       l'intersection       pas dans B
Deux tables ont la même structure. UNION retourne 8 lignes et UNION ALL retourne 12 lignes. Combien y a-t-il de doublons ?
Partie 8 — Requêtes avancées Jointures I INNER · LEFT · RIGHT · ON · USING
⏱ 22 min

Jointures — INNER, LEFT, RIGHT

Comprendre les jointures SQL — INNER JOIN (correspondances communes), LEFT JOIN (toutes les lignes de gauche + NULL à droite), RIGHT JOIN (toutes les lignes de droite), syntaxes ON et USING, jointures multiples et préfixes de table.

✓ Ce que vous allez apprendre
  • Pourquoi les jointures : combiner des données de plusieurs tables
  • INNER JOIN — uniquement les lignes avec correspondance dans les deux tables
  • LEFT JOIN — toutes les lignes de gauche, NULL si pas de correspondance à droite
  • RIGHT JOIN — toutes les lignes de droite, NULL si pas de correspondance à gauche
  • Syntaxe ON vs USING, alias de table, jointures multiples

1
INNER JOIN — l'intersection des deux tables
ON · USING · Alias de table · Préfixe ambigu
ℹ Pourquoi les jointures ?

En Merise, les données sont distribuées dans plusieurs tables pour éviter la redondance (3FN). Pour répondre à une question qui touche plusieurs entités (« quel étudiant a eu quelle note dans quelle formation ? »), il faut joindre les tables concernées. Les jointures sont la réponse SQL au passage MLD → requêtes.

sqlINNER JOIN — exemples SkolaBase
-- INNER JOIN basique : étudiants avec leurs notes
SELECT
    e.numCINEtu,
    e.nomEtu,
    e.prenomEtu,
    i.codeSess,
    i.noteInscription
FROM Etudiant e
    INNER JOIN Inscription i ON e.numCINEtu = i.numCINEtu;
-- Seuls les étudiants AVEC au moins une inscription apparaissent
-- Les étudiants sans inscription sont exclus

-- Syntaxe USING (quand les colonnes ont le même nom)
SELECT e.nomEtu, i.noteInscription
FROM Etudiant e
    INNER JOIN Inscription i USING (numCINEtu);
-- Equivalent à ON e.numCINEtu = i.numCINEtu

-- JOIN sans INNER (INNER est implicite)
SELECT e.nomEtu, i.noteInscription
FROM Etudiant e
    JOIN Inscription i ON e.numCINEtu = i.numCINEtu;

-- Jointure sur 3 tables : étudiant + inscription + session
SELECT
    e.nomEtu,
    e.prenomEtu,
    s.codeSess,
    s.dateDebutSess,
    i.noteInscription
FROM Etudiant e
    JOIN Inscription i ON e.numCINEtu = i.numCINEtu
    JOIN Session s     ON i.codeSess  = s.codeSess;

-- Jointure sur 5 tables : parcours complet
SELECT
    e.nomEtu,
    e.prenomEtu,
    fo.titreForm,
    fi.libelleFiliere,
    CONCAT(fmt.prenomFormateur, ' ', fmt.nomFormateur) AS formateur,
    i.noteInscription
FROM Etudiant e
    JOIN Inscription i ON e.numCINEtu  = i.numCINEtu
    JOIN Session s     ON i.codeSess   = s.codeSess
    JOIN Formation fo  ON s.codeForm   = fo.codeForm
    JOIN Filiere fi    ON fo.codeFiliere = fi.codeFiliere
    JOIN Formateur fmt ON s.numFormateur = fmt.numFormateur
ORDER BY e.nomEtu, fo.titreForm;

2
LEFT JOIN et RIGHT JOIN
Toutes les lignes de gauche · NULL à droite · Anti-jointure · IS NULL
sqlLEFT JOIN — SkolaBase
-- LEFT JOIN : TOUS les étudiants, avec ou sans inscription
SELECT
    e.numCINEtu,
    e.nomEtu,
    e.prenomEtu,
    i.codeSess,           -- NULL si pas d'inscription
    i.noteInscription     -- NULL si pas d'inscription
FROM Etudiant e
    LEFT JOIN Inscription i ON e.numCINEtu = i.numCINEtu;
-- TOUS les étudiants apparaissent, y compris ceux sans inscription

-- Compter les inscriptions par étudiant (y compris 0)
SELECT
    e.numCINEtu,
    e.nomEtu,
    COUNT(i.codeSess) AS nb_inscriptions   -- COUNT ignore les NULL
FROM Etudiant e
    LEFT JOIN Inscription i ON e.numCINEtu = i.numCINEtu
GROUP BY e.numCINEtu, e.nomEtu
ORDER BY nb_inscriptions DESC;

-- Anti-jointure : étudiants SANS aucune inscription
SELECT e.numCINEtu, e.nomEtu
FROM Etudiant e
    LEFT JOIN Inscription i ON e.numCINEtu = i.numCINEtu
WHERE i.numCINEtu IS NULL;   -- IS NULL = pas de correspondance à droite

-- LEFT JOIN sur 3 tables : toutes les formations avec ou sans session
SELECT
    fi.libelleFiliere,
    fo.titreForm,
    COUNT(s.codeSess) AS nb_sessions
FROM Filiere fi
    LEFT JOIN Formation fo ON fi.codeFiliere = fo.codeFiliere
    LEFT JOIN Session s    ON fo.codeForm    = s.codeForm
GROUP BY fi.codeFiliere, fi.libelleFiliere, fo.codeForm, fo.titreForm
ORDER BY fi.libelleFiliere, fo.titreForm;

-- RIGHT JOIN : équivalent au LEFT JOIN inversé
-- Toutes les sessions avec ou sans formateur assigné
SELECT
    s.codeSess,
    f.nomFormateur      -- NULL si aucun formateur
FROM Formateur f
    RIGHT JOIN Session s ON f.numFormateur = s.numFormateur;
-- Équivalent à : Session LEFT JOIN Formateur
textDiagrammes de Venn — INNER, LEFT, RIGHT JOIN
INNER JOIN              LEFT JOIN              RIGHT JOIN
  A ┌───┐B            A ┌───┐B            A ┌───┐B
  ░░░██░░             █████░░             ░░░████
  Intersection         Tout A +             Tout B +
  seulement            intersection         intersection

LEFT JOIN + WHERE B.col IS NULL   →  Uniquement dans A (anti-jointure)
  A ┌───┐B
  ███░░░░  Tout A sauf l'intersection
SkolaBase a 6 étudiants. 4 ont des inscriptions, 2 n'en ont pas. SELECT COUNT(*) FROM Etudiant e LEFT JOIN Inscription i ON e.numCINEtu = i.numCINEtu — combien de lignes retourne ce SELECT (sans GROUP BY) ?
Partie 8 — Requêtes avancées Jointures II CROSS · SELF · FULL OUTER · Synthèse
⏱ 20 min

Jointures — CROSS, SELF, FULL OUTER

CROSS JOIN (produit cartésien), SELF JOIN (auto-jointure avec alias obligatoire), FULL OUTER JOIN (émulation MySQL avec UNION), et synthèse des 6 types de jointures avec comparaison.

✓ Ce que vous allez apprendre
  • CROSS JOIN — produit cartésien (chaque ligne de A x chaque ligne de B)
  • SELF JOIN — jointure d'une table sur elle-même, alias obligatoires
  • FULL OUTER JOIN — toutes les lignes des deux tables (émulation MySQL)
  • Tableau récapitulatif des 6 types de jointures

1
CROSS JOIN — produit cartésien
N x M lignes · Combinatoire · Attention aux grandes tables
sqlCROSS JOIN — SkolaBase
-- CROSS JOIN : chaque ligne de A combinée avec chaque ligne de B
SELECT
    e.nomEtu,
    s.codeSess
FROM Etudiant e
    CROSS JOIN Session s;
-- 6 étudiants x 4 sessions = 24 lignes
-- Utile pour générer toutes les combinaisons possibles

-- Cas d'usage : générer une grille de disponibilité
-- (toutes les paires formateur-formation possibles)
SELECT
    f.nomFormateur,
    fm.titreForm
FROM Formateur f
    CROSS JOIN Formation fm
ORDER BY f.nomFormateur, fm.titreForm;
-- 4 formateurs x 5 formations = 20 lignes

-- Attention : CROSS JOIN implicite (vieille syntaxe à éviter)
SELECT e.nomEtu, s.codeSess FROM Etudiant e, Session s;
-- Equivalent à CROSS JOIN mais moins lisible

2
SELF JOIN — jointure d'une table sur elle-même
Alias obligatoires · Comparaison de lignes · Hiérarchie
ℹ SELF JOIN — quand l'utiliser ?

Le SELF JOIN joint une table avec elle-même, avec deux alias différents. Il sert à comparer des lignes entre elles au sein de la même table : trouver des paires, gérer des hiérarchies (employé + manager dans la même table), ou détecter des doublons.

sqlSELF JOIN — SkolaBase
-- Trouver les paires d'étudiants de la même ville
SELECT
    e1.nomEtu AS etudiant1,
    e2.nomEtu AS etudiant2,
    e1.villeEtu
FROM Etudiant e1
    INNER JOIN Etudiant e2
        ON e1.villeEtu = e2.villeEtu
        AND e1.numCINEtu < e2.numCINEtu  -- éviter les doublons et les auto-paires
ORDER BY e1.villeEtu;

-- Étudiants inscrits dans les mêmes sessions
SELECT
    i1.numCINEtu AS etudiant1,
    i2.numCINEtu AS etudiant2,
    i1.codeSess
FROM Inscription i1
    INNER JOIN Inscription i2
        ON i1.codeSess = i2.codeSess
        AND i1.numCINEtu < i2.numCINEtu;

-- Exemple hiérarchie : table Organisation (manager référence un autre employé)
-- CREATE TABLE Organisation (id INT PK, nom VARCHAR, manager_id INT FK→id)
-- SELECT e.nom AS employe, m.nom AS manager
-- FROM Organisation e
--     LEFT JOIN Organisation m ON e.manager_id = m.id;

3
FULL OUTER JOIN et synthèse des jointures
Émulation UNION · Tableau récapitulatif · Choisir la bonne jointure
sqlFULL OUTER JOIN — émulation MySQL avec UNION
-- MySQL ne supporte pas FULL OUTER JOIN nativement
-- Émulation : LEFT JOIN UNION RIGHT JOIN

-- Toutes les formations et toutes les filières, avec ou sans correspondance
SELECT
    fi.libelleFiliere,
    fo.titreForm
FROM Filiere fi
    LEFT JOIN Formation fo ON fi.codeFiliere = fo.codeFiliere
UNION
SELECT
    fi.libelleFiliere,
    fo.titreForm
FROM Filiere fi
    RIGHT JOIN Formation fo ON fi.codeFiliere = fo.codeFiliere;

-- FULL OUTER ANTI-JOIN (lignes sans correspondance des deux côtés)
SELECT fi.libelleFiliere, fo.titreForm
FROM Filiere fi
    LEFT JOIN Formation fo ON fi.codeFiliere = fo.codeFiliere
WHERE fo.codeFiliere IS NULL  -- Filières sans formation
UNION
SELECT fi.libelleFiliere, fo.titreForm
FROM Filiere fi
    RIGHT JOIN Formation fo ON fi.codeFiliere = fo.codeFiliere
WHERE fi.codeFiliere IS NULL; -- Formations sans filière (ne devrait pas exister)
TypeLignes retournéesNULLUsage SkolaBase
INNER JOINSeulement les lignes avec correspondance des deux côtésAucunÉtudiants avec leurs notes
LEFT JOINToutes les lignes de gauche + correspondances à droiteColonnes droite = NULL si pas de correspondanceTous les étudiants avec ou sans inscription
RIGHT JOINToutes les lignes de droite + correspondances à gaucheColonnes gauche = NULL si pas de correspondanceToutes les sessions avec ou sans formateur
CROSS JOINToutes les combinaisons (N x M)AucunGrille disponibilité formateurs/formations
SELF JOINLignes de la même table comparées entre ellesSelon le type (INNER ou LEFT)Paires d'étudiants de la même ville
FULL OUTERToutes les lignes des deux tablesNULL des deux côtés selon correspondanceÉmulation MySQL : LEFT ∪ RIGHT
On veut trouver les filières qui n'ont aucune formation rattachée. Quelle combinaison est correcte ?
Un SELF JOIN est exécuté sur la table Etudiant (6 lignes) sans condition. Combien de lignes retourne-t-il ?
Partie 9 — Administration MySQL Sauvegarde & Restauration mysqldump · SOURCE · Workbench
⏱ 16 min

Sauvegarde & Restauration

Exporter une base de données avec mysqldump (structure seule, données seules, tout), options utiles, restauration avec SOURCE et via Workbench, stratégies de sauvegarde pour SkolaBase.

✓ Ce que vous allez apprendre
  • Comprendre l'importance des sauvegardes et les stratégies (complète, incrémentale)
  • mysqldump — exporter structure seule (--no-data), données seules (--no-create-info), tout
  • Options utiles : --single-transaction, --routines, --triggers
  • Restaurer avec mysql < fichier.sql et SOURCE fichier.sql
  • Sauvegarde et restauration graphique via MySQL Workbench

1
mysqldump — sauvegarder SkolaBase
Structure · Données · Tout · Plusieurs BDD · Options
ℹ mysqldump — qu'est-ce que c'est ?

mysqldump est un outil en ligne de commande fourni avec MySQL. Il génère un fichier texte .sql contenant les instructions SQL nécessaires pour recréer la structure et/ou les données de la base. Ce fichier est portable : il peut être restauré sur n'importe quel serveur MySQL compatible.

bashmysqldump — commandes SkolaBase
# Sauvegarder TOUT (structure + données) — la plus courante
mysqldump -u root -p skolabase > skolabase_backup_2024.sql
# -u root : utilisateur MySQL
# -p : demander le mot de passe
# > skolabase_backup_2024.sql : redirection vers le fichier

# Structure SEULEMENT (sans les données — pour recréer le schéma)
mysqldump -u root -p --no-data skolabase > skolabase_structure.sql

# Données SEULEMENT (sans CREATE TABLE — pour recharger des données)
mysqldump -u root -p --no-create-info skolabase > skolabase_data.sql

# Une seule table
mysqldump -u root -p skolabase Inscription > inscription_backup.sql

# Plusieurs tables spécifiques
mysqldump -u root -p skolabase Etudiant Inscription > etudiants_inscriptions.sql

# Plusieurs bases de données
mysqldump -u root -p --databases skolabase skolabase_test > multi_backup.sql

# TOUTES les bases (y compris mysql, information_schema)
mysqldump -u root -p --all-databases > all_databases.sql

# Options recommandées pour la production
mysqldump -u root -p \
    --single-transaction \  # Dump cohérent sans verrouiller les tables (InnoDB)
    --routines \            # Inclure les procédures stockées et fonctions
    --triggers \            # Inclure les triggers
    --events \              # Inclure les événements planifiés
    --hex-blob \            # Données binaires en hexadécimal
    skolabase > skolabase_prod_$(date +%Y%m%d).sql
# Nommage avec date : skolabase_prod_20241115.sql
textContenu d'un fichier mysqldump (extrait)
-- MySQL dump 8.0.36
-- Host: localhost    Database: skolabase
-- ------------------------------------------------------

CREATE DATABASE IF NOT EXISTS `skolabase`;
USE `skolabase`;

DROP TABLE IF EXISTS `Filiere`;
CREATE TABLE `Filiere` (
    `codeFiliere` CHAR(6) NOT NULL,
    `libelleFiliere` VARCHAR(80) NOT NULL,
    PRIMARY KEY (`codeFiliere`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

LOCK TABLES `Filiere` WRITE;
INSERT INTO `Filiere` VALUES
    ('INF','Informatique'),
    ('GES','Gestion et Commerce');
UNLOCK TABLES;

2
Restauration — SOURCE et mysql
mysql < · SOURCE · Workbench Import · Ordre de restauration
bashRestauration — ligne de commande
# Méthode 1 : redirection en ligne de commande
mysql -u root -p skolabase < skolabase_backup_2024.sql
# Restaure toutes les tables et données dans la base skolabase

# Si la base n'existe pas encore
mysql -u root -p -e "CREATE DATABASE IF NOT EXISTS skolabase CHARACTER SET utf8mb4;"
mysql -u root -p skolabase < skolabase_backup_2024.sql

# Méthode 2 : à l'intérieur de MySQL Shell
mysql -u root -p
-- Dans MySQL :
SOURCE /chemin/vers/skolabase_backup_2024.sql;
-- ou sur Windows :
SOURCE C:/backup/skolabase_backup_2024.sql;

# Vérifier que la restauration a fonctionné
mysql -u root -p -e "USE skolabase; SHOW TABLES; SELECT COUNT(*) FROM Etudiant;"
textRestauration via MySQL Workbench — 6 étapes
① Ouvrir Workbench et se connecter à SkolaBase_Local
② Server → Data Import
③ Choisir "Import from Self-Contained File"
④ Cliquer ... et sélectionner le fichier .sql de sauvegarde
⑤ Default Target Schema : choisir skolabase
    (ou "New..." pour créer une nouvelle base)
⑥ Cliquer "Start Import" → attendre la fin
⑦ Vérifier dans l'onglet "Object Browser" que les tables sont bien présentes
⚠ Attention à l'ordre lors de la restauration

Si le fichier .sql contient DROP TABLE IF EXISTS avant chaque CREATE TABLE (comportement par défaut de mysqldump), et que les tables ont des FK, la restauration peut échouer si l'ordre n'est pas correct. mysqldump génère automatiquement SET FOREIGN_KEY_CHECKS = 0; au début du fichier pour éviter ce problème. Vérifier que cette ligne est présente dans le fichier de restauration.

On veut sauvegarder uniquement la structure de SkolaBase (sans les données) pour la partager avec un collègue qui doit créer la même BDD. Quelle option mysqldump utiliser ?
mysqldump --single-transaction est recommandé pour InnoDB. Pourquoi ?
Partie 9 — Administration MySQL Import & Export CSV LOAD DATA · SELECT INTO OUTFILE · Workbench
⏱ 14 min

Import & Export de données

Importer un fichier CSV dans une table MySQL avec LOAD DATA INFILE, exporter les résultats d'un SELECT dans un fichier avec SELECT INTO OUTFILE, et utiliser l'assistant d'import/export de MySQL Workbench.

✓ Ce que vous allez apprendre
  • LOAD DATA INFILE — importer un fichier CSV dans une table
  • Configurer le séparateur, le qualificateur de texte et la fin de ligne
  • Ignorer l'en-tête, mapper les colonnes
  • SELECT ... INTO OUTFILE — exporter une table ou un SELECT en CSV
  • Import/export graphique via MySQL Workbench Table Data Import Wizard

1
Importer un fichier CSV avec LOAD DATA INFILE
LOAD DATA · FIELDS TERMINATED BY · IGNORE 1 LINES · SET
textetudiants_import.csv — exemple de fichier source
numCINEtu,nomEtu,prenomEtu,dateNaissEtu,villeEtu,telEtu
A1234567,Alaoui,Karim,2002-05-15,Casablanca,0612345678
B7654321,Bennani,Sara,2001-11-22,Rabat,0698765432
C2468135,Chraibi,Youssef,2003-01-08,Marrakech,
sqlLOAD DATA INFILE — importer etudiants_import.csv
-- Import basique
LOAD DATA INFILE '/var/lib/mysql-files/etudiants_import.csv'
INTO TABLE Etudiant
FIELDS TERMINATED BY ','           -- Séparateur de colonnes
       ENCLOSED BY '"'              -- Qualificateur de texte (guillemets)
LINES TERMINATED BY '\n'           -- Fin de ligne (Unix) ou '\r\n' (Windows)
IGNORE 1 LINES                     -- Ignorer la ligne d'en-tête
(numCINEtu, nomEtu, prenomEtu, dateNaissEtu, villeEtu, telEtu);

-- Import avec transformation : majuscules sur le nom
LOAD DATA INFILE '/var/lib/mysql-files/etudiants_import.csv'
INTO TABLE Etudiant
FIELDS TERMINATED BY ',' ENCLOSED BY '"'
LINES TERMINATED BY '\n'
IGNORE 1 LINES
(@cin, @nom, @prenom, @naissance, @ville, @tel)
SET
    numCINEtu    = @cin,
    nomEtu       = UPPER(@nom),         -- Forcer les majuscules
    prenomEtu    = @prenom,
    dateNaissEtu = STR_TO_DATE(@naissance, '%Y-%m-%d'),
    villeEtu     = COALESCE(NULLIF(@ville, ''), 'Casablanca'),
    telEtu       = NULLIF(@tel, '');    -- '' → NULL

-- Vérifier le résultat
SELECT * FROM Etudiant LIMIT 5;
⚠ Chemin du fichier avec LOAD DATA INFILE

MySQL n'accepte les fichiers que depuis un répertoire sécurisé (secure_file_priv). Sous Windows : vérifier SHOW VARIABLES LIKE 'secure_file_priv'. Le résultat indique le seul dossier autorisé. Copier le fichier CSV dans ce dossier avant d'exécuter LOAD DATA.


2
Exporter avec SELECT INTO OUTFILE
SELECT INTO OUTFILE · CSV · Chemin serveur · Workbench Export
sqlSELECT INTO OUTFILE — exporter SkolaBase
-- Exporter la table Etudiant en CSV
SELECT *
INTO OUTFILE '/var/lib/mysql-files/etudiants_export.csv'
FIELDS TERMINATED BY ','
       OPTIONALLY ENCLOSED BY '"'
LINES TERMINATED BY '\n'
FROM Etudiant;

-- Exporter avec en-tête (astuce : UNION ALL avec les noms de colonnes)
SELECT 'numCINEtu', 'nomEtu', 'prenomEtu', 'dateNaissEtu', 'villeEtu'
UNION ALL
SELECT numCINEtu, nomEtu, prenomEtu,
       DATE_FORMAT(dateNaissEtu, '%d/%m/%Y'), villeEtu
INTO OUTFILE '/var/lib/mysql-files/etudiants_avec_entete.csv'
FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"'
LINES TERMINATED BY '\n'
FROM Etudiant;

-- Exporter un résultat de jointure
SELECT
    e.numCINEtu,
    CONCAT(e.prenomEtu, ' ', e.nomEtu) AS nom_complet,
    fo.titreForm,
    i.noteInscription
INTO OUTFILE '/var/lib/mysql-files/resultats_etudiants.csv'
FIELDS TERMINATED BY ';' ENCLOSED BY '"'
LINES TERMINATED BY '\r\n'
FROM Etudiant e
    JOIN Inscription i  ON e.numCINEtu = i.numCINEtu
    JOIN Session s      ON i.codeSess  = s.codeSess
    JOIN Formation fo   ON s.codeForm  = fo.codeForm
ORDER BY e.nomEtu;
textImport CSV via Workbench — Table Data Import Wizard
① Clic droit sur la table Etudiant dans l'Object Browser
② Choisir "Table Data Import Wizard"
③ Cliquer "Browse" et sélectionner le fichier CSV
④ Choisir l'encodage (UTF-8 pour les accents et caractères arabes)
⑤ Configurer le séparateur (virgule, point-virgule...)
⑥ Mapper les colonnes du CSV aux colonnes de la table
⑦ Cliquer "Next" puis "Execute Import"
⑧ Vérifier le rapport : nb lignes importées, erreurs éventuelles
LOAD DATA INFILE importe 100 lignes mais 3 ont un numCINEtu déjà présent dans la table (doublon PK). Que se passe-t-il par défaut ?
Partie 9 — Administration MySQL Gestion des utilisateurs CREATE USER · ALTER USER · DROP USER
⏱ 14 min

Gestion des utilisateurs MySQL

Créer des comptes utilisateurs MySQL (CREATE USER), gérer les hôtes autorisés, modifier les mots de passe (ALTER USER), lister les comptes dans mysql.user, supprimer un compte (DROP USER) et tester les connexions.

✓ Ce que vous allez apprendre
  • Comprendre la notion d'utilisateur MySQL : login@hôte
  • CREATE USER 'nom'@'hôte' IDENTIFIED BY 'mot_de_passe'
  • Hôtes : localhost, % (tous), adresse IP spécifique
  • Lister les comptes : SELECT ... FROM mysql.user
  • ALTER USER — changer le mot de passe, expiration
  • DROP USER — supprimer un compte

1
Créer des utilisateurs SkolaBase
CREATE USER · Hôte · IDENTIFIED BY · IF NOT EXISTS
ℹ Utilisateur MySQL — format login@hôte

Un compte MySQL est toujours identifié par deux composants : le nom d'utilisateur ET l'hôte depuis lequel il se connecte. 'karim'@'localhost' et 'karim'@'%' sont deux comptes différents avec potentiellement des privilèges différents. '%' = accepte depuis n'importe quel hôte.

sqlCréer les utilisateurs SkolaBase — 3 rôles
-- Utilisateur administrateur SkolaBase (connexion locale seulement)
CREATE USER IF NOT EXISTS 'skola_admin'@'localhost'
    IDENTIFIED BY 'SkolaAdmin_2024!';

-- Utilisateur application (lecture + écriture, depuis l'application web)
CREATE USER IF NOT EXISTS 'skola_app'@'localhost'
    IDENTIFIED BY 'SkolaApp_2024!';

-- Utilisateur lecture seule (pour les rapports, depuis n'importe où)
CREATE USER IF NOT EXISTS 'skola_reader'@'%'
    IDENTIFIED BY 'SkolaReader_2024!';

-- Vérifier la création
SELECT User, Host, plugin, password_expired
FROM mysql.user
WHERE User LIKE 'skola%';

-- Résultat attendu :
-- User          | Host      | plugin                | password_expired
-- skola_admin   | localhost | caching_sha2_password | N
-- skola_app     | localhost | caching_sha2_password | N
-- skola_reader  | %         | caching_sha2_password | N

2
Modifier et supprimer des comptes
ALTER USER · Mot de passe · Expiration · RENAME · DROP USER
sqlALTER USER et DROP USER
-- Changer le mot de passe
ALTER USER 'skola_app'@'localhost'
    IDENTIFIED BY 'NouveauMdp_2024!';

-- Forcer le changement de mot de passe à la prochaine connexion
ALTER USER 'skola_reader'@'%'
    PASSWORD EXPIRE;

-- Expiration automatique tous les 90 jours
ALTER USER 'skola_app'@'localhost'
    PASSWORD EXPIRE INTERVAL 90 DAY;

-- Désactiver le compte (sans le supprimer)
ALTER USER 'skola_reader'@'%' ACCOUNT LOCK;

-- Réactiver le compte
ALTER USER 'skola_reader'@'%' ACCOUNT UNLOCK;

-- Changer son propre mot de passe (connecté comme skola_app)
ALTER USER CURRENT_USER() IDENTIFIED BY 'MonNouveauMdp!';

-- Supprimer un compte (et tous ses privilèges)
DROP USER IF EXISTS 'skola_reader'@'%';

-- Tester la connexion depuis le terminal
-- mysql -u skola_app -p skolabase
-- Entrer le mot de passe → doit se connecter

-- Voir le compte courant
SELECT CURRENT_USER();
'karim'@'localhost' et 'karim'@'%' — si les deux comptes existent, depuis une connexion locale (localhost), quel compte MySQL utilise-t-il ?
Partie 9 — Administration MySQL Privilèges & Sécurité GRANT · REVOKE · 6 niveaux
⏱ 16 min

Privilèges & Sécurité

Accorder des privilèges avec GRANT (6 niveaux de granularité), tableau des privilèges MySQL, révoquer avec REVOKE, vérifier les droits avec SHOW GRANTS, et stratégie de sécurité pour SkolaBase (principe du moindre privilège).

✓ Ce que vous allez apprendre
  • Les 6 niveaux de privilèges MySQL : Global, BDD, Table, Colonne, Routine, Proxy
  • GRANT privilege ON niveau TO utilisateur
  • Privilèges courants : SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, ALL
  • REVOKE — retirer des privilèges
  • SHOW GRANTS FOR — voir les privilèges d'un utilisateur
  • Principe du moindre privilège appliqué à SkolaBase

1
Les 6 niveaux de privilèges
Global · BDD · Table · Colonne · Routine · Proxy
NiveauSyntaxe ONGranularitéExemple SkolaBase
GlobalON *.*S'applique à toutes les BDD du serveurAdministrateur système MySQL
BDDON skolabase.*S'applique à toutes les tables d'une BDDAdministrateur SkolaBase uniquement
TableON skolabase.EtudiantS'applique à une seule tableSecrétaire ne gère que les étudiants
ColonneON table (colonne)S'applique à une ou plusieurs colonnesCacher la note à certains utilisateurs
RoutineON PROCEDURE/FUNCTIONS'applique à une procédure stockéeAccès à une procédure spécifique
ProxyPROXY ONUsurper les droits d'un autre utilisateurRare — gestion avancée

2
GRANT — accorder les privilèges SkolaBase
ALL PRIVILEGES · SELECT · INSERT UPDATE DELETE · Principe moindre privilège
PrivilègePermetUsage SkolaBase
SELECTLire les donnéesTous les utilisateurs
INSERTAjouter des lignesApplication, admin
UPDATEModifier des lignesApplication, admin
DELETESupprimer des lignesAdmin uniquement
CREATECréer des tables/BDDAdmin uniquement
DROPSupprimer tables/BDDAdmin uniquement
ALTERModifier la structureAdmin uniquement
INDEXCréer/supprimer des indexAdmin uniquement
GRANT OPTIONTransmettre ses privilèges à d'autresJamais pour les comptes applicatifs
ALL PRIVILEGESTous les privilègesroot et admins système uniquement
sqlGRANT — stratégie complète SkolaBase
-- skola_admin : tous les droits sur SkolaBase uniquement
GRANT ALL PRIVILEGES ON skolabase.* TO 'skola_admin'@'localhost';

-- skola_app : droits CRUD (pas DROP, CREATE, ALTER)
GRANT SELECT, INSERT, UPDATE, DELETE
    ON skolabase.*
    TO 'skola_app'@'localhost';

-- skola_reader : lecture seule sur toute la base
GRANT SELECT ON skolabase.* TO 'skola_reader'@'%';

-- Niveau table : secrétaire gère uniquement les étudiants
GRANT SELECT, INSERT, UPDATE ON skolabase.Etudiant
    TO 'secretaire'@'localhost';
GRANT SELECT ON skolabase.Inscription
    TO 'secretaire'@'localhost';

-- Niveau colonne : cacher les notes à certains utilisateurs
GRANT SELECT (numCINEtu, codeSess) ON skolabase.Inscription
    TO 'skola_view'@'localhost';
-- skola_view peut voir numCINEtu et codeSess mais PAS noteInscription

-- Appliquer immédiatement (MySQL 8 recharge automatiquement)
FLUSH PRIVILEGES;
-- Note : FLUSH PRIVILEGES est nécessaire seulement si on modifie
-- directement les tables mysql.user (à éviter)

-- Vérifier les droits accordés
SHOW GRANTS FOR 'skola_app'@'localhost';
-- Résultat :
-- GRANT SELECT, INSERT, UPDATE, DELETE ON `skolabase`.* TO 'skola_app'@'localhost'

3
REVOKE — retirer des privilèges
REVOKE · SHOW GRANTS · Principe moindre privilège · Audit
sqlREVOKE et audit des privilèges
-- Retirer le droit DELETE à skola_app
REVOKE DELETE ON skolabase.* FROM 'skola_app'@'localhost';

-- Retirer TOUS les droits
REVOKE ALL PRIVILEGES ON skolabase.* FROM 'skola_reader'@'%';

-- Vérifier les droits de tous les utilisateurs SkolaBase
SELECT
    User,
    Host,
    Select_priv,
    Insert_priv,
    Update_priv,
    Delete_priv,
    Create_priv,
    Drop_priv
FROM mysql.user
WHERE User LIKE 'skola%';

-- Lister tous les GRANT sur une base spécifique
SELECT *
FROM information_schema.SCHEMA_PRIVILEGES
WHERE TABLE_SCHEMA = 'skolabase';

-- Résumé de la stratégie de sécurité SkolaBase :
-- root         → NE JAMAIS utiliser pour l'application
-- skola_admin  → Admins techniques (migrations, sauvegardes)
-- skola_app    → Application web (SELECT/INSERT/UPDATE/DELETE)
-- skola_reader → Rapports, analyses (SELECT uniquement)
-- secretaire   → Interface secrétariat (Etudiant + Inscription SELECT/INSERT/UPDATE)
✓ Principe du moindre privilège — règle d'or

Chaque compte ne doit avoir que les privilèges strictement nécessaires à sa fonction. Un compte applicatif (application web) n'a jamais besoin de DROP ou CREATE — si la connexion est compromisée, l'attaquant ne peut pas détruire la structure. Un utilisateur de rapports n'a besoin que de SELECT. Cette segmentation limite considérablement les dommages en cas de compromission.

GRANT ALL PRIVILEGES ON *.* TO 'skola_app'@'localhost' est configuré pour le compte applicatif. Quel est le risque de sécurité principal ?
Quelle est la différence entre REVOKE ALL PRIVILEGES ON skolabase.* FROM 'skola_app'@'localhost' et DROP USER 'skola_app'@'localhost' ?
Projet Final — SkolaBase CDC & Analyse Merise RG · DD · MCD · MLD
⏱ 20 min

SkolaBase — CDC & Analyse Merise complète

Cahier des charges du centre de formation SkolaBase, extraction des règles de gestion, dictionnaire de données complet, graphe des DF, MCD et MLD — la démarche Merise complète de A à Z en un seul cas.

ℹ Objectif du projet final

SkolaBase est la base de données d'un centre de formation marocain. Ce projet mobilise toutes les compétences du cours : Merise (RG, DD, DF, MCD, MLD), MySQL (DDL, DML, DQL, jointures, sous-requêtes) et administration. Chaque étape s'appuie sur la précédente.


1
Cahier des charges SkolaBase
Contexte · Besoins · Périmètre · Contraintes
textCDC SkolaBase — Centre de Formation (version complète)
CAHIER DES CHARGES — SkolaBase
Centre de Formation Professionnelle — Maroc
==============================================

1. CONTEXTE
   Le centre SkolaBase dispense des formations professionnelles continues
   pour des techniciens et cadres marocains. Il gère actuellement ses
   données sur registres papier et souhaite une base de données MySQL.

2. ENTITES IDENTIFIEES
   ● ETUDIANT : toute personne inscrite à une session de formation.
     Chaque étudiant possède un numéro CIN unique (lettre + 7 chiffres).
   ● FORMATEUR : intervenant qui anime les sessions.
   ● FORMATION : programme pédagogique avec titre, durée et niveau.
   ● SESSION : occurrence décalée d'une formation dans le temps et l'espace.
   ● FILIERE : domaine regroupant plusieurs formations (INF, GES, ELE, BTP).

3. REGLES DE GESTION
   RG1 : Un étudiant peut s'inscrire à plusieurs sessions. Une session
         peut accueillir plusieurs étudiants. (N:N)
   RG2 : Chaque inscription d'un étudiant à une session donne lieu à
         une note (0 à 20, peut être absente si non encore saisie).
   RG3 : Chaque session est animée par exactement un formateur.
         Un formateur peut animer plusieurs sessions. (1:N)
   RG4 : Chaque session porte sur exactement une formation.
         Une formation peut donner lieu à plusieurs sessions. (1:N)
   RG5 : Chaque formation appartient à exactement une filière.
         Une filière regroupe une ou plusieurs formations. (1:N)

4. PERIMETRE
   Inclus   : gestion inscriptions, sessions, notes, formateurs, formations, filières
   Exclus   : paie des formateurs, comptabilité générale, app mobile

5. CONTRAINTES TECHNIQUES
   SGBD : MySQL 8.0 — moteur InnoDB — charset utf8mb4
   Serveur : Windows Server local ou Linux
   Accès simultanés : 10 utilisateurs maximum

2
Dictionnaire de données & Graphe DF
20 données · 5 types · Convention objetConcept · DF directes
CodeDésignationTTailleObservationsEntité
numCINEtuN° CIN étudiantAN8PK, format A1234567ETUDIANT
nomEtuNom étudiantA50NNETUDIANT
prenomEtuPrénom étudiantA50NNETUDIANT
dateNaissEtuDate de naissanceD—NULL acceptéETUDIANT
villeEtuVille résidenceA50Défaut CasablancaETUDIANT
telEtuTéléphoneAN15NULL acceptéETUDIANT
numFormateurID formateurN4PK AUTO_INCREMENTFORMATEUR
nomFormateurNom formateurA50NNFORMATEUR
prenomFormateurPrénom formateurA50NNFORMATEUR
specialiteFormSpécialitéA80NULL acceptéFORMATEUR
codeSessCode sessionAN10PK, format SESS-AAAA-NNSESSION
dateDebutSessDate débutD—NNSESSION
dateFinSessDate finD—NULL acceptéSESSION
lieuSessLieu sessionAN100NULL acceptéSESSION
codeFormCode formationAN10PK uniqueFORMATION
titreFormTitre formationAN100NNFORMATION
dureeFormDurée (heures)N3Entier positifFORMATION
niveauFormNiveau requisA20ENUM Bac/Bac+2/Bac+3/Tech.FORMATION
codeFiliereCode filièreAN6PK, ex: INF, GESFILIERE
libelleFiliereLibellé filièreA80NNFILIERE
noteInscriptionNote obtenueN4,20.00–20.00, NULL si non saisieINSCRIPTION
textGraphe des DF SkolaBase — DF directes uniquement
numCINEtu    ──► nomEtu, prenomEtu, dateNaissEtu, villeEtu, telEtu
numFormateur ──► nomFormateur, prenomFormateur, specialiteForm
codeSess     ──► dateDebutSess, dateFinSess, lieuSess, numFormateur (FK), codeForm (FK)
codeForm     ──► titreForm, dureeForm, niveauForm, codeFiliere (FK)
codeFiliere  ──► libelleFiliere

DF composée :
numCINEtu + codeSess ──► noteInscription   (association INSCRIPTION porteuse)

3
MCD et MLD SkolaBase
5 entités · 4 associations · 6 tables · FK nommées
textMCD SkolaBase — récapitulatif des associations
ETUDIANT  (0,N) ◆─ INSCRIPTION (porteuse: noteInscription) ─◆ (1,N) SESSION
                        R3 → table pivot INSCRIPTION
SESSION   (1,N) ◆─ ANIME (RG3) ─◆ (1,1) FORMATEUR
                        R2 → FK numFormateur dans SESSION
SESSION   (1,N) ◆─ PORTE SUR (RG4) ─◆ (1,1) FORMATION
                        R2 → FK codeForm dans SESSION
FORMATION (1,N) ◆─ APPARTIENT A (RG5) ─◆ (1,1) FILIERE
                        R2 → FK codeFiliere dans FORMATION
textMLD SkolaBase — 6 tables
FILIERE    (#codeFiliere, libelleFiliere)

FORMATION  (#codeForm, titreForm, dureeForm, niveauForm,
            *codeFiliere → FILIERE.codeFiliere)

FORMATEUR  (#numFormateur AI, nomFormateur, prenomFormateur, specialiteForm)

SESSION    (#codeSess, dateDebutSess, dateFinSess, lieuSess,
            *numFormateur → FORMATEUR.numFormateur,
            *codeForm     → FORMATION.codeForm)

ETUDIANT   (#numCINEtu, nomEtu, prenomEtu, dateNaissEtu, villeEtu, telEtu)

INSCRIPTION(#numCINEtu → ETUDIANT.numCINEtu,
            #codeSess  → SESSION.codeSess,
            noteInscription)
            CLE COMPOSEE : (numCINEtu, codeSess)
Projet Final — SkolaBase Étape 1 — Création BDD DDL complet · FK · CHECK · INDEX
⏱ 18 min

Étape 1 — Création de la BDD (DDL complet)

Script SQL complet de création de la base SkolaBase : CREATE DATABASE, les 6 tables dans le bon ordre, toutes les contraintes (PK, FK nommées, CHECK, DEFAULT), index et commentaires.


★
Script DDL complet — à exécuter dans l'ordre
sqlskolabase_ddl.sql — script complet de création
-- ============================================================
--  SkolaBase — Script DDL complet
--  Centre de formation marocain — MySQL 8.0
-- ============================================================

DROP DATABASE IF EXISTS skolabase;
CREATE DATABASE skolabase
    CHARACTER SET utf8mb4
    COLLATE utf8mb4_unicode_ci
    COMMENT 'Base de données centre de formation SkolaBase';

USE skolabase;

-- ── Table 1 : FILIERE (aucune FK — créer en premier) ────────
CREATE TABLE IF NOT EXISTS Filiere (
    codeFiliere     CHAR(6)      NOT NULL,
    libelleFiliere  VARCHAR(80)  NOT NULL,
    CONSTRAINT pk_Filiere PRIMARY KEY (codeFiliere)
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4
  COMMENT = 'Filières de formation (INF, GES, ELE, BTP)';

-- ── Table 2 : FORMATION ─────────────────────────────────────
CREATE TABLE IF NOT EXISTS Formation (
    codeForm    VARCHAR(10)                             NOT NULL,
    titreForm   VARCHAR(100)                            NOT NULL,
    dureeForm   SMALLINT UNSIGNED                       NOT NULL COMMENT 'Durée en heures',
    niveauForm  ENUM('Technicien','Bac','Bac+2','Bac+3') NULL,
    codeFiliere CHAR(6)                                 NOT NULL,
    CONSTRAINT pk_Formation  PRIMARY KEY (codeForm),
    CONSTRAINT fk_Form_Fil   FOREIGN KEY (codeFiliere)
        REFERENCES Filiere(codeFiliere)
        ON DELETE RESTRICT ON UPDATE CASCADE,
    CONSTRAINT chk_Duree     CHECK (dureeForm > 0)
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4;

-- ── Table 3 : FORMATEUR ─────────────────────────────────────
CREATE TABLE IF NOT EXISTS Formateur (
    numFormateur    INT          NOT NULL AUTO_INCREMENT,
    nomFormateur    VARCHAR(50)  NOT NULL,
    prenomFormateur VARCHAR(50)  NOT NULL,
    specialiteForm  VARCHAR(80)  NULL,
    CONSTRAINT pk_Formateur PRIMARY KEY (numFormateur)
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4;

-- ── Table 4 : SESSION ───────────────────────────────────────
CREATE TABLE IF NOT EXISTS Session (
    codeSess      VARCHAR(10)  NOT NULL,
    dateDebutSess DATE         NOT NULL,
    dateFinSess   DATE         NULL,
    lieuSess      VARCHAR(100) NULL,
    numFormateur  INT          NOT NULL,
    codeForm      VARCHAR(10)  NOT NULL,
    CONSTRAINT pk_Session       PRIMARY KEY (codeSess),
    CONSTRAINT fk_Sess_Format   FOREIGN KEY (numFormateur)
        REFERENCES Formateur(numFormateur)
        ON DELETE RESTRICT ON UPDATE CASCADE,
    CONSTRAINT fk_Sess_Form     FOREIGN KEY (codeForm)
        REFERENCES Formation(codeForm)
        ON DELETE RESTRICT ON UPDATE CASCADE,
    CONSTRAINT chk_DatesSess    CHECK (dateFinSess IS NULL OR dateFinSess >= dateDebutSess),
    INDEX idx_Sess_Form (codeForm),
    INDEX idx_Sess_Debut (dateDebutSess)
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4;

-- ── Table 5 : ETUDIANT ──────────────────────────────────────
CREATE TABLE IF NOT EXISTS Etudiant (
    numCINEtu    CHAR(8)      NOT NULL COMMENT 'Format : lettre + 7 chiffres',
    nomEtu       VARCHAR(50)  NOT NULL,
    prenomEtu    VARCHAR(50)  NOT NULL,
    dateNaissEtu DATE         NULL,
    villeEtu     VARCHAR(50)  NOT NULL DEFAULT 'Casablanca',
    telEtu       VARCHAR(15)  NULL,
    CONSTRAINT pk_Etudiant PRIMARY KEY (numCINEtu),
    CONSTRAINT chk_CIN
        CHECK (numCINEtu REGEXP '^[A-Z][0-9]{7}$') ENFORCED,
    CONSTRAINT chk_DateNaiss
        CHECK (dateNaissEtu IS NULL OR dateNaissEtu < CURDATE()) ENFORCED,
    INDEX idx_Etu_Ville (villeEtu)
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4;

-- ── Table 6 : INSCRIPTION (créer en dernier — FK vers Etudiant + Session) ─
CREATE TABLE IF NOT EXISTS Inscription (
    numCINEtu       CHAR(8)      NOT NULL,
    codeSess        VARCHAR(10)  NOT NULL,
    noteInscription DECIMAL(4,2) NULL COMMENT 'Note sur 20',
    CONSTRAINT pk_Inscription   PRIMARY KEY (numCINEtu, codeSess),
    CONSTRAINT fk_Insc_Etu      FOREIGN KEY (numCINEtu)
        REFERENCES Etudiant(numCINEtu)
        ON DELETE CASCADE ON UPDATE CASCADE,
    CONSTRAINT fk_Insc_Sess     FOREIGN KEY (codeSess)
        REFERENCES Session(codeSess)
        ON DELETE CASCADE ON UPDATE CASCADE,
    CONSTRAINT chk_Note
        CHECK (noteInscription IS NULL OR
              (noteInscription >= 0 AND noteInscription <= 20)) ENFORCED
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4;

-- Vérification
SHOW TABLES;
SELECT TABLE_NAME, ENGINE, TABLE_ROWS, TABLE_COMMENT
FROM information_schema.TABLES
WHERE TABLE_SCHEMA = 'skolabase';
Projet Final — SkolaBase Étape 2 — Peuplement INSERT · UPDATE · Données marocaines
⏱ 16 min

Étape 2 — Peuplement des données (DML)

Script DML complet pour peupler SkolaBase avec des données marocaines réalistes — 4 filières, 5 formations, 4 formateurs, 4 sessions, 6 étudiants et 7 inscriptions avec notes.


★
Script DML complet — données marocaines SkolaBase
sqlskolabase_dml.sql — peuplement complet
USE skolabase;

-- ── 1. Filières ────────────────────────────────────────────
INSERT INTO Filiere (codeFiliere, libelleFiliere) VALUES
    ('INF', 'Informatique'),
    ('GES', 'Gestion et Commerce'),
    ('ELE', 'Electronique et Electrotechnique'),
    ('BTP', 'Batiment et Travaux Publics');

-- ── 2. Formations ───────────────────────────────────────────
INSERT INTO Formation (codeForm, titreForm, dureeForm, niveauForm, codeFiliere) VALUES
    ('DEV-WEB', 'Developpement Web Full Stack',        120, 'Bac+2', 'INF'),
    ('DEV-MOB', 'Developpement Mobile Android',         80, 'Bac+2', 'INF'),
    ('BDD-ADM', 'Administration des Bases de Donnees', 100, 'Bac+3', 'INF'),
    ('CPT-GEN', 'Comptabilite Generale',                90, 'Bac',   'GES'),
    ('MKT-DIG', 'Marketing Digital',                    60, 'Bac+2', 'GES');

-- ── 3. Formateurs ───────────────────────────────────────────
INSERT INTO Formateur (nomFormateur, prenomFormateur, specialiteForm) VALUES
    ('Alaoui',   'Karim',  'Developpement Web, PHP, Laravel'),
    ('Bennani',  'Nadia',  'Bases de donnees, MySQL, Oracle'),
    ('Chraibi',  'Hassan', 'Reseaux, Administration systeme'),
    ('Idrissi',  'Leila',  'Marketing digital, SEO');

-- ── 4. Sessions ─────────────────────────────────────────────
INSERT INTO Session (codeSess, dateDebutSess, dateFinSess, lieuSess, numFormateur, codeForm) VALUES
    ('SESS-2024-01', '2024-09-02', '2024-12-20', 'Salle A101 - Casablanca', 1, 'DEV-WEB'),
    ('SESS-2024-02', '2024-09-09', '2024-11-29', 'Salle B205 - Rabat',      2, 'BDD-ADM'),
    ('SESS-2024-03', '2024-10-07', '2024-12-13', 'Salle A102 - Casablanca', 1, 'DEV-MOB'),
    ('SESS-2025-01', '2025-01-13', '2025-04-04', 'Salle A101 - Casablanca', 1, 'DEV-WEB');

-- ── 5. Etudiants ────────────────────────────────────────────
INSERT INTO Etudiant (numCINEtu, nomEtu, prenomEtu, dateNaissEtu, villeEtu, telEtu) VALUES
    ('A1234567', 'Alaoui',   'Karim',   '2002-05-15', 'Casablanca', '0612345678'),
    ('B7654321', 'Bennani',  'Sara',    '2001-11-22', 'Rabat',      '0698765432'),
    ('C2468135', 'Chraibi',  'Youssef', '2003-01-08', 'Marrakech',  '0635791246'),
    ('D1357924', 'Idrissi',  'Fatima',  '2002-08-30', 'Fes',        '0674513892'),
    ('E9876543', 'Mansouri', 'Amine',   '2001-03-17', 'Casablanca', '0656789012'),
    ('F3692581', 'Tazi',     'Zineb',   '2003-06-25', 'Tanger',     '0678901234');

-- ── 6. Inscriptions ─────────────────────────────────────────
INSERT INTO Inscription (numCINEtu, codeSess, noteInscription) VALUES
    ('A1234567', 'SESS-2024-01', 14.50),
    ('B7654321', 'SESS-2024-01', 16.00),
    ('C2468135', 'SESS-2024-01', 11.75),
    ('A1234567', 'SESS-2024-02', 13.25),
    ('D1357924', 'SESS-2024-02', 17.50),
    ('E9876543', 'SESS-2024-01',  NULL),   -- Note pas encore saisie
    ('F3692581', 'SESS-2024-03', 15.00);

-- ── Vérification du peuplement ────────────────────────────────
SELECT 'Filiere'     AS table_name, COUNT(*) AS nb FROM Filiere    UNION ALL
SELECT 'Formation',                 COUNT(*) FROM Formation         UNION ALL
SELECT 'Formateur',                 COUNT(*) FROM Formateur         UNION ALL
SELECT 'Session',                   COUNT(*) FROM Session           UNION ALL
SELECT 'Etudiant',                  COUNT(*) FROM Etudiant          UNION ALL
SELECT 'Inscription',               COUNT(*) FROM Inscription;

-- Quelques corrections via UPDATE pour illustrer
UPDATE Etudiant
SET telEtu = '0612000099'
WHERE numCINEtu = 'A1234567';

-- Saisir la note manquante d'E9876543
UPDATE Inscription
SET noteInscription = 12.50
WHERE numCINEtu = 'E9876543' AND codeSess = 'SESS-2024-01';
Projet Final — SkolaBase Étape 3 — Requêtes SELECT Filtres · Agrégats · Fonctions
⏱ 20 min

Étape 3 — Requêtes SELECT

20 requêtes SELECT progressives sur SkolaBase — filtres WHERE, tri ORDER BY, agrégats GROUP BY/HAVING, fonctions SQL (dates, chaînes, math), CASE WHEN et expressions conditionnelles.


★
20 requêtes SELECT — du simple au complexe
sqlskolabase_select.sql — 20 requêtes SELECT
USE skolabase;

-- Q1 : Tous les étudiants triés par nom
SELECT numCINEtu, nomEtu, prenomEtu, villeEtu FROM Etudiant ORDER BY nomEtu;

-- Q2 : Etudiants de Casablanca uniquement
SELECT * FROM Etudiant WHERE villeEtu = 'Casablanca';

-- Q3 : Etudiants dont le nom commence par 'A' ou 'B'
SELECT nomEtu, prenomEtu FROM Etudiant WHERE nomEtu LIKE 'A%' OR nomEtu LIKE 'B%';

-- Q4 : Formations de plus de 80 heures
SELECT titreForm, dureeForm, niveauForm FROM Formation WHERE dureeForm > 80 ORDER BY dureeForm DESC;

-- Q5 : Sessions en cours en 2024
SELECT codeSess, dateDebutSess, dateFinSess FROM Session
WHERE YEAR(dateDebutSess) = 2024 ORDER BY dateDebutSess;

-- Q6 : Notes entre 12 et 16 (inclus)
SELECT numCINEtu, codeSess, noteInscription FROM Inscription
WHERE noteInscription BETWEEN 12 AND 16 ORDER BY noteInscription DESC;

-- Q7 : Inscriptions sans note
SELECT numCINEtu, codeSess FROM Inscription WHERE noteInscription IS NULL;

-- Q8 : Nombre d'étudiants par ville
SELECT villeEtu, COUNT(*) AS nb_etudiants FROM Etudiant GROUP BY villeEtu ORDER BY nb_etudiants DESC;

-- Q9 : Moyenne, min et max des notes par session
SELECT
    codeSess,
    COUNT(*)                            AS nb_inscrits,
    COUNT(noteInscription)              AS notes_saisies,
    ROUND(AVG(noteInscription), 2)      AS moyenne,
    MIN(noteInscription)                AS note_min,
    MAX(noteInscription)                AS note_max
FROM Inscription GROUP BY codeSess;

-- Q10 : Sessions avec moyenne supérieure à 13
SELECT codeSess, ROUND(AVG(noteInscription), 2) AS moyenne
FROM Inscription WHERE noteInscription IS NOT NULL
GROUP BY codeSess HAVING AVG(noteInscription) > 13;

-- Q11 : Âge de chaque étudiant (calculé depuis dateNaissEtu)
SELECT
    CONCAT(prenomEtu, ' ', nomEtu) AS nom_complet,
    dateNaissEtu,
    TIMESTAMPDIFF(YEAR, dateNaissEtu, CURDATE()) AS age
FROM Etudiant WHERE dateNaissEtu IS NOT NULL ORDER BY age;

-- Q12 : Durée de chaque session en jours
SELECT codeSess, dateDebutSess, dateFinSess,
       DATEDIFF(dateFinSess, dateDebutSess) AS duree_jours
FROM Session WHERE dateFinSess IS NOT NULL;

-- Q13 : Mention selon la note (CASE WHEN)
SELECT numCINEtu, codeSess, noteInscription,
    CASE
        WHEN noteInscription IS NULL  THEN 'Non evalue'
        WHEN noteInscription >= 16   THEN 'Tres bien'
        WHEN noteInscription >= 14   THEN 'Bien'
        WHEN noteInscription >= 12   THEN 'Assez bien'
        WHEN noteInscription >= 10   THEN 'Passable'
        ELSE                              'Insuffisant'
    END AS mention
FROM Inscription ORDER BY noteInscription DESC;

-- Q14 : Taux de réussite par session (note >= 10)
SELECT codeSess,
    COUNT(noteInscription) AS evaluations,
    SUM(IF(noteInscription >= 10, 1, 0)) AS admis,
    ROUND(100 * SUM(IF(noteInscription >= 10, 1, 0)) / COUNT(noteInscription), 1) AS taux_pct
FROM Inscription WHERE noteInscription IS NOT NULL GROUP BY codeSess;

-- Q15 : Formations par filière (nombre et total heures)
SELECT codeFiliere, COUNT(*) AS nb_formations, SUM(dureeForm) AS heures_totales
FROM Formation GROUP BY codeFiliere HAVING COUNT(*) >= 2;

-- Q16 : Formateur le plus actif (plus de sessions)
SELECT numFormateur, COUNT(*) AS nb_sessions FROM Session
GROUP BY numFormateur ORDER BY nb_sessions DESC LIMIT 1;

-- Q17 : Etudiants inscrits à plus d'une session
SELECT numCINEtu, COUNT(*) AS nb_sessions FROM Inscription
GROUP BY numCINEtu HAVING COUNT(*) > 1;

-- Q18 : Note de chaque étudiant avec son écart à la moyenne générale
SELECT numCINEtu, codeSess, noteInscription,
    ROUND(noteInscription - (SELECT AVG(noteInscription) FROM Inscription
                              WHERE noteInscription IS NOT NULL), 2) AS ecart_moyenne
FROM Inscription WHERE noteInscription IS NOT NULL;

-- Q19 : Formations sans session planifiée
SELECT codeForm, titreForm FROM Formation
WHERE codeForm NOT IN (SELECT DISTINCT codeForm FROM Session);

-- Q20 : Statistiques globales SkolaBase
SELECT
    (SELECT COUNT(*) FROM Etudiant)    AS nb_etudiants,
    (SELECT COUNT(*) FROM Session)     AS nb_sessions,
    (SELECT COUNT(*) FROM Inscription) AS nb_inscriptions,
    (SELECT ROUND(AVG(noteInscription), 2)
     FROM Inscription
     WHERE noteInscription IS NOT NULL)  AS moyenne_generale;
Projet Final — SkolaBase Étape 4 — Jointures & Sous-requêtes JOIN · LEFT · EXISTS · Corrélées
⏱ 22 min

Étape 4 — Jointures & Sous-requêtes

15 requêtes avancées sur SkolaBase — jointures multi-tables (INNER, LEFT, SELF), sous-requêtes mono-ligne, IN/NOT IN, EXISTS/NOT EXISTS et sous-requêtes corrélées.


★
15 requêtes avancées — jointures et sous-requêtes
sqlskolabase_joins.sql — 15 requêtes avancées
USE skolabase;

-- ── JOINTURES ────────────────────────────────────────────

-- J1 : Parcours complet (étudiant + formation + formateur)
SELECT
    CONCAT(e.prenomEtu, ' ', e.nomEtu) AS etudiant,
    fo.titreForm                        AS formation,
    fi.libelleFiliere                   AS filiere,
    CONCAT(fmt.prenomFormateur, ' ', fmt.nomFormateur) AS formateur,
    s.dateDebutSess,
    i.noteInscription
FROM Etudiant e
    JOIN Inscription i  ON e.numCINEtu   = i.numCINEtu
    JOIN Session s      ON i.codeSess    = s.codeSess
    JOIN Formation fo   ON s.codeForm    = fo.codeForm
    JOIN Filiere fi     ON fo.codeFiliere = fi.codeFiliere
    JOIN Formateur fmt  ON s.numFormateur = fmt.numFormateur
ORDER BY e.nomEtu, s.dateDebutSess;

-- J2 : Toutes les formations avec nombre de sessions (LEFT JOIN)
SELECT fo.codeForm, fo.titreForm, fo.dureeForm,
       COUNT(s.codeSess) AS nb_sessions
FROM Formation fo
    LEFT JOIN Session s ON fo.codeForm = s.codeForm
GROUP BY fo.codeForm, fo.titreForm, fo.dureeForm
ORDER BY nb_sessions DESC;

-- J3 : Filières avec nombre de formations et heures totales
SELECT fi.libelleFiliere,
       COUNT(fo.codeForm)  AS nb_formations,
       COALESCE(SUM(fo.dureeForm), 0) AS heures_totales
FROM Filiere fi
    LEFT JOIN Formation fo ON fi.codeFiliere = fo.codeFiliere
GROUP BY fi.codeFiliere, fi.libelleFiliere
ORDER BY heures_totales DESC;

-- J4 : Etudiants avec leurs meilleures notes
SELECT e.numCINEtu,
       CONCAT(e.prenomEtu, ' ', e.nomEtu) AS etudiant,
       MAX(i.noteInscription) AS meilleure_note,
       COUNT(i.codeSess)      AS nb_inscriptions
FROM Etudiant e
    LEFT JOIN Inscription i ON e.numCINEtu = i.numCINEtu
GROUP BY e.numCINEtu, e.nomEtu, e.prenomEtu
ORDER BY meilleure_note DESC;

-- J5 : Formateurs avec leurs sessions et formations
SELECT fmt.nomFormateur, fmt.prenomFormateur,
       s.codeSess, fo.titreForm, s.dateDebutSess
FROM Formateur fmt
    LEFT JOIN Session s   ON fmt.numFormateur = s.numFormateur
    LEFT JOIN Formation fo ON s.codeForm       = fo.codeForm
ORDER BY fmt.nomFormateur, s.dateDebutSess;

-- J6 : Pairs d'étudiants dans la même session (SELF JOIN)
SELECT i1.numCINEtu AS etudiant1, i2.numCINEtu AS etudiant2, i1.codeSess
FROM Inscription i1
    JOIN Inscription i2 ON i1.codeSess = i2.codeSess
                        AND i1.numCINEtu < i2.numCINEtu
ORDER BY i1.codeSess;

-- ── SOUS-REQUETES ────────────────────────────────────────

-- S1 : Etudiants avec note > moyenne générale
SELECT numCINEtu, codeSess, noteInscription
FROM Inscription
WHERE noteInscription > (SELECT AVG(noteInscription) FROM Inscription
                          WHERE noteInscription IS NOT NULL);

-- S2 : Meilleur étudiant de la session SESS-2024-01
SELECT e.numCINEtu, CONCAT(e.prenomEtu, ' ', e.nomEtu) AS etudiant, i.noteInscription
FROM Etudiant e JOIN Inscription i ON e.numCINEtu = i.numCINEtu
WHERE i.codeSess = 'SESS-2024-01'
  AND i.noteInscription = (SELECT MAX(noteInscription) FROM Inscription
                            WHERE codeSess = 'SESS-2024-01');

-- S3 : Etudiants inscrits à au moins une session (EXISTS)
SELECT numCINEtu, nomEtu, prenomEtu FROM Etudiant e
WHERE EXISTS (SELECT 1 FROM Inscription i WHERE i.numCINEtu = e.numCINEtu);

-- S4 : Etudiants sans aucune inscription (NOT EXISTS)
SELECT numCINEtu, nomEtu, prenomEtu FROM Etudiant e
WHERE NOT EXISTS (SELECT 1 FROM Inscription i WHERE i.numCINEtu = e.numCINEtu);

-- S5 : Formations qui ont eu au moins une session en 2024
SELECT codeForm, titreForm FROM Formation
WHERE codeForm IN (SELECT codeForm FROM Session WHERE YEAR(dateDebutSess) = 2024);

-- S6 : Formateur avec le plus de sessions animées
SELECT numFormateur, nomFormateur, prenomFormateur FROM Formateur
WHERE numFormateur = (SELECT numFormateur FROM Session
                      GROUP BY numFormateur ORDER BY COUNT(*) DESC LIMIT 1);

-- S7 : Etudiants dont la note dans SESS-2024-01 est > leur propre moyenne
SELECT i1.numCINEtu, i1.noteInscription AS note_sess01
FROM Inscription i1
WHERE i1.codeSess = 'SESS-2024-01'
  AND i1.noteInscription > (SELECT AVG(i2.noteInscription)
                             FROM Inscription i2
                             WHERE i2.numCINEtu = i1.numCINEtu
                               AND i2.noteInscription IS NOT NULL);

-- S8 : Sessions de la formation la plus longue
SELECT codeSess, dateDebutSess FROM Session
WHERE codeForm = (SELECT codeForm FROM Formation ORDER BY dureeForm DESC LIMIT 1);

-- S9 : Table dérivée : top 3 sessions par moyenne
SELECT s.codeSess, s.dateDebutSess, stats.moyenne
FROM Session s
    JOIN (SELECT codeSess, ROUND(AVG(noteInscription), 2) AS moyenne
          FROM Inscription WHERE noteInscription IS NOT NULL
          GROUP BY codeSess) AS stats ON s.codeSess = stats.codeSess
ORDER BY stats.moyenne DESC LIMIT 3;
Projet Final — SkolaBase Étape 5 — Administration Backup · Utilisateurs · Privilèges
⏱ 16 min

Étape 5 — Administration SkolaBase

Script d'administration complet — sauvegarde avec mysqldump, création des 4 comptes utilisateurs selon le principe du moindre privilège, vérification des droits et procédure de restauration.


★
Script d'administration complet SkolaBase
bash1. Sauvegarde SkolaBase avec mysqldump
# Sauvegarde complète (structure + données)
mysqldump -u root -p \
    --single-transaction \
    --routines \
    --triggers \
    skolabase > skolabase_backup_$(date +%Y%m%d).sql

# Vérifier le fichier généré
ls -lh skolabase_backup_*.sql
# skolabase_backup_20241115.sql  12K

# Sauvegarde structure seulement (partager le schéma)
mysqldump -u root -p --no-data skolabase > skolabase_schema.sql

# Restauration complète
mysql -u root -p -e "DROP DATABASE IF EXISTS skolabase;"
mysql -u root -p -e "CREATE DATABASE skolabase CHARACTER SET utf8mb4;"
mysql -u root -p skolabase < skolabase_backup_20241115.sql

# Vérification après restauration
mysql -u root -p skolabase -e "SHOW TABLES; SELECT COUNT(*) FROM Etudiant;"
sql2. Gestion des utilisateurs SkolaBase
-- ── Création des 4 comptes ──────────────────────────────────

-- Compte administrateur (droits complets sur skolabase)
CREATE USER IF NOT EXISTS 'skola_admin'@'localhost'
    IDENTIFIED BY 'SkolaAdmin_2024!';
GRANT ALL PRIVILEGES ON skolabase.* TO 'skola_admin'@'localhost';

-- Compte application web (CRUD sans DROP/CREATE/ALTER)
CREATE USER IF NOT EXISTS 'skola_app'@'localhost'
    IDENTIFIED BY 'SkolaApp_2024!';
GRANT SELECT, INSERT, UPDATE, DELETE ON skolabase.*
    TO 'skola_app'@'localhost';

-- Compte secrétariat (Etudiant + Inscription uniquement)
CREATE USER IF NOT EXISTS 'secretariat'@'localhost'
    IDENTIFIED BY 'Secretariat_2024!';
GRANT SELECT, INSERT, UPDATE ON skolabase.Etudiant
    TO 'secretariat'@'localhost';
GRANT SELECT, INSERT ON skolabase.Inscription
    TO 'secretariat'@'localhost';
GRANT SELECT ON skolabase.Session
    TO 'secretariat'@'localhost';

-- Compte rapports (lecture seule depuis n'importe où)
CREATE USER IF NOT EXISTS 'skola_reader'@'%'
    IDENTIFIED BY 'SkolaReader_2024!';
GRANT SELECT ON skolabase.* TO 'skola_reader'@'%';

-- ── Vérification ───────────────────────────────────────────
SHOW GRANTS FOR 'skola_app'@'localhost';
SHOW GRANTS FOR 'secretariat'@'localhost';

SELECT User, Host, plugin
FROM mysql.user WHERE User LIKE 'skola%' OR User = 'secretariat';

-- ── Tests de connexion ───────────────────────────────────────
-- (exécuter depuis le terminal)
-- mysql -u skola_app -p skolabase -e "SELECT COUNT(*) FROM Etudiant;"
-- mysql -u skola_reader -p skolabase -e "SELECT titreForm FROM Formation;"
-- mysql -u secretariat -p skolabase -e "DROP TABLE Etudiant;" -- doit échouer !

-- ── Maintenance ─────────────────────────────────────────────
-- Changer le mot de passe d'un compte
ALTER USER 'skola_app'@'localhost'
    IDENTIFIED BY 'NouveauMdp_SkolaApp_2025!';

-- Révoquer le DELETE pour skola_app (restriction de sécurité)
REVOKE DELETE ON skolabase.* FROM 'skola_app'@'localhost';
SHOW GRANTS FOR 'skola_app'@'localhost';

-- Supprimer un compte obsolète
DROP USER IF EXISTS 'skola_reader'@'%';

-- ── Bilan de sécurité SkolaBase ──────────────────────────────
SELECT
    TABLE_SCHEMA    AS base,
    GRANTEE         AS utilisateur,
    PRIVILEGE_TYPE  AS privilege,
    IS_GRANTABLE    AS peut_transmettre
FROM information_schema.SCHEMA_PRIVILEGES
WHERE TABLE_SCHEMA = 'skolabase'
ORDER BY GRANTEE, PRIVILEGE_TYPE;
✓ Bilan du projet SkolaBase — compétences mobilisées
ÉtapeCompétencesParties du cours
CDC & MeriseRG, DD, DF, MCD, MLDParties 1 & 2
WorkbenchEER, Forward Engineering, FK graphiquesPartie 3
DDLCREATE DATABASE, CREATE TABLE, contraintes nomméesParties 4 & 5
DMLINSERT multi-lignes, UPDATE, DELETE, TRUNCATEPartie 6
SELECTWHERE, GROUP BY, HAVING, fonctions, CASE WHENPartie 7
Requêtes avancéesJOIN 5 tables, sous-requêtes, EXISTS, corréléesPartie 8
Administrationmysqldump, CREATE USER, GRANT, REVOKEPartie 9