Chapitre 23
Using and RDBMS
Lecture : 21 minQuiz de 12 questions
# Using and RDBMS
## Objectifs et prérequis
Ce chapitre vise à permettre aux élèves de Upper Sixth (ICT) de comprendre et d'appliquer les concepts fondamentaux des Systèmes de Gestion de Bases de Données Relationnelles (RDBMS) dans un contexte éducatif et professionnel camerounais. À l'issue de ce chapitre, l'élève sera capable de : concevoir et créer des tables avec des relations appropriées, formuler des requêtes SQL simples et complexes, générer des rapports et des formulaires utiles, et intégrer ces compétences dans un projet complet simulant un système d'information réel (ex. gestion scolaire, suivi agricole, ou gestion de petite entreprise).
Prérequis : maîtrise de base de l'ordinateur, compréhension des concepts de données (données, enregistrements, champs), familiarité avec un tableur (Excel/LibreOffice), et notions élémentaires de logique et de résolution de problèmes. Aucune connaissance préalable en SQL n'est requise, mais une logique structurée est essentielle.
## Introduction
Dans le système éducatif camerounais anglophone, l'enseignement de l'ICT au niveau Upper Sixth prépare les élèves à l'enseignement supérieur et au monde du travail, où la gestion efficace des données est cruciale. Les RDBMS (Relational Database Management Systems) comme MySQL, PostgreSQL ou Microsoft Access sont largement utilisés dans les administrations publiques (ex. MINEDUC, MINSANTE), les entreprises privées (banques, télécoms comme MTN ou Orange Cameroun), et les ONG pour stocker, organiser et extraire des informations pertinentes. Ce chapitre ne se limite pas à la théorie : il met l'accent sur la pratique concrète, en s'appuyant sur des scénarios locaux (gestion des inscriptions scolaires dans un lycée de Yaoundé, suivi des récoltes dans une coopérative agricole de l'Ouest, ou gestion des patients dans un centre de santé de Douala) pour rendre l'apprentissage significatif et directement applicable.
## I. Creating tables and relationships
### Contexte
La conception d'une base de données relationnelle commence par la définition de ses tables et des liens entre elles. Une mauvaise conception entraîne des redondances, des incohérences et des difficultés de requête. Dans le contexte camerounais, pensez à un système de gestion des bourses nationales : sans relations claires entre les tables « Étudiants », « Établissements », « Filières » et « Versements », il serait impossible de suivre correctement l'attribution des fonds ou d'éviter les doublons.
### Définitions et faits clés
> **Table** : Structure organisée en lignes (enregistrements) et colonnes (champs) pour stocker des données homogènes.
> **Champ (Field)** : Unité de donnée unique dans une table, définie par un nom et un type de données (ex. Texte, Entier, Date, Booléen).
> **Clé primaire (Primary Key)** : Champ ou combinaison de champs qui identifie de manière unique chaque enregistrement dans une table. Aucun doublon autorisé, aucune valeur nulle.
> **Clé étrangère (Foreign Key)** : Champ dans une table qui fait référence à la clé primaire d'une autre table, établissant une relation.
> **Relation** : Association logique entre deux tables via une clé étrangère. Types : un à un (1:1), un à plusieurs (1:N), plusieurs à plusieurs (N:N).
> **Intégrité référentielle** : Règle qui garantit que les valeurs d'une clé étrangère correspondent toujours à une clé primaire existante dans la table liée (ou sont nulles si autorisé).
### Types de données courants en RDBMS (ex. MySQL/Acess)
| Type de données | Description | Exemple camerounais |
|-----------------|-------------|---------------------|
| VARCHAR(n) | Chaîne de caractères de longueur variable, max n | Nom d'étudiant : 'Jean-Marie Kouega' |
| INT | Nombre entier | Âge : 17, Numéro de bourse : 2024001 |
| DATE | Date (AAAA-MM-JJ) | Date de naissance : 2006-05-15 |
| DECIMAL(p,s) | Nombre décimal avec précision p et échelle s | Frais de scolarité : 50000.00 |
| BOOLEAN | Valeur vraie/fausse | Bourse accordée : TRUE/FALSE |
### Étapes de création des tables et relations
1. **Identifier les entités** : Quels objets du monde réel faut-il modéliser ? (Ex. Étudiant, Cours, Professeur, Paiement).
2. **Définir les attributs** : Quelles caractéristiques décrivent chaque entité ? (Ex. Pour Étudiant : Nom, Prénom, Date de naissance, Sexe, Lieu d'origine).
3. **Choisir la clé primaire** : Quel attribut (ou combinaison) garantit l'unicité ? (Ex. Numéro d'inscription pour Étudiant, Code cours pour Cours).
4. **Établir les relations** : Comment les entités interagissent-elles ? Utiliser des clés étrangères. (Ex. Un étudiant suit plusieurs cours → table intermédiaire « Inscription » avec FK vers Étudiant et FK vers Cours).
5. **Appliquer l'intégrité référentielle** : Configurer les règles de suppression/mise à jour (ex. RESTRICT, CASCADE) pour éviter les orphelins.
6. **Normaliser** : Vérifier que la conception réduit les redondances (au moins jusqu'à 3FN pour ce niveau).
### Exemple concret : Système de gestion des inscriptions scolaires (Lycée bilingue de Yaoundé)
* **Table Étudiants** :
`StudentID` (INT, PK), `FirstName` (VARCHAR(50)), `LastName` (VARCHAR(50)), `DateOfBirth` (DATE), `Gender` (CHAR(1)), `RegionOrigin` (VARCHAR(30))
> *Clé primaire : StudentID*
* **Table Filières** :
`StreamID` (INT, PK), `StreamName` (VARCHAR(50))
> *Exemples : 'Science', 'Arts', 'Technical'*
> *Clé primaire : StreamID*
* **Table Niveaux** :
`LevelID` (INT, PK), `LevelName` (VARCHAR(20))
> *Exemples : 'Lower Sixth', 'Upper Sixth'*
> *Clé primaire : LevelID*
* **Table Inscriptions** (relation N:N entre Étudiants et Filières/Niveaux pour une année donnée) :
`EnrollmentID` (INT, PK), `StudentID` (INT, FK → Étudiants.StudentID), `StreamID` (INT, FK → Filières.StreamID), `LevelID` (INT, FK → Niveaux.LevelID), `AcademicYear` (VARCHAR(9))
> *Clés étrangères : StudentID, StreamID, LevelID*
> *Règle : Un étudiant ne peut s'inscrire qu'une seule fois par filière/niveau/année → combinaison unique (StudentID, StreamID, LevelID, AcademicYear) comme clé candidate ou index unique.*
### Vocabulaire à retenir
Table, Champ, Enregistrement, Clé primaire, Clé étrangère, Relation (1:1, 1:N, N:N), Intégrité référentielle, Normalisation, Entité, Attribut, Clé candidate, Index unique.
### Exemple de sujet type examen avec plan
**Sujet** : Le lycée technique de Kumba souhaite informatiser la gestion de son atelier de soudure. Chaque apprenti possède un numéro d'apprenti, un nom, une date de naissance et provient d'une région spécifique. L'atelier propose plusieurs modules de formation (ex. Soudure à l'arc, Soudure MIG, Lecture de plans). Chaque apprenti peut suivre plusieurs modules, et chaque module peut être suivi par plusieurs apprentis. Pour chaque suivi de module, on enregistre la date de début et la note obtenue (sur 20).
**Plan attendu** :
1. Identification des entités et de leurs attributs (Apprenti, Module, SuiviModule).
2. Définition des tables avec leurs champs et types de données appropriés (justifier le choix des types).
3. Désignation des clés primaires pour chaque table.
4. Explication des relations nécessaires et mise en place des clés étrangères dans la table de junction (SuiviModule).
5. Description de comment l'intégrité référentielle serait assurée (ex. suppression d'un apprenti → suppression de ses suivis via CASCADE ou blocage via RESTRICT selon la politique).
6. Schéma texte ou liste des tables avec PK/FK clairement indiqués.
## II. Queries 1
### Contexte
Une fois les tables créées et peuplées de données, l'étape suivante consiste à extraire des informations utiles. Les requêtes simples (Queries 1) permettent de sélectionner, filtrer et trier des données provenant d'une seule table ou de tables liées par des jointures simples. Dans un contexte camerounais, cela pourrait être utilisé par un responsable de coopérative agricole pour lister tous les producteurs de café de la région de l'Ouest ayant produit plus de 500 kg cette saison, ou par un responsable de santé pour trouver tous les patients de plus de 60 ans ayant reçu leur vaccin contre la fièvre jaune dans un district donné.
### Définitions et faits clés
> **Requête SQL (SELECT)** : Instruction utilisée pour récupérer des données d'une ou plusieurs tables dans une base de données.
> **Clause SELECT** : Spécifie les colonnes (champs) à inclure dans le résultat.
> **Clause FROM** : Spécifie la ou les tables source(s) des données.
> **Clause WHERE** : Filtre les lignes en fonction d'une condition (critère). Utilise des opérateurs de comparaison (=, <>, <, >, <=, >=) et logiques (AND, OR, NOT).
> **Clause ORDER BY** : Trie le résultat résultant par une ou plusieurs colonnes (ASC par défaut, DESC pour ordre décroissant).
> **Opérateur LIKE** : Utilisé dans WHERE pour rechercher un motif dans une chaîne de caractères (utilise % pour zéro ou plusieurs caractères, _ pour exactement un caractère).
> **Valeur NULL** : Représente l'absence de valeur. Nécessite des opérateurs spéciaux : IS NULL ou IS NOT NULL (ne pas utiliser = NULL).
### Syntaxe de base d'une requête SELECT simple
```sql
SELECT colonne1, colonne2, ...
FROM nom_table
WHERE condition
ORDER BY colonne1 [ASC|DESC], colonne2 [ASC|DESC];
```
### Opérateurs et fonctions courantes
| Type | Opérateur/Fonction | Exemple | Résultat (exemple camerounais) |
|------|---------------------|---------|--------------------------------|
| Comparaison | =, <>, <, >, <=, >= | `Age >= 18` | Vrai pour les apprenants majeurs |
| Logique | AND, OR, NOT | `Region = 'West' AND Production > 500` | Producteurs de l'Ouest avec >500kg |
| Chaîne | LIKE | `LastName LIKE 'Kou%'` | Noms commençant par 'Kou' (Kouega, Kouotou) |
| Chaîne | LIKE | `FirstName LIKE '_a%'` | Prénoms où la 2ème lettre est 'a' (Jean-Marie → 'ea' non, mais Patrice → 'at' oui si 2ème='a') |
| Spécial | IS NULL, IS NOT NULL | `PhoneNumber IS NOT NULL` | Enregistrements avec un numéro de téléphone renseigné |
| Agrégation simple (prérequis pour Q2) | COUNT(*) | `SELECT COUNT(*) FROM Students WHERE StreamID = 1` | Nombre d'étudiants en Sciences |
### Exemple concret : Base de données des patients d'un centre de santé de Bamenda
* **Table Patients** :
`PatientID` (INT, PK), `FirstName` (VARCHAR(50)), `LastName` (VARCHAR(50)), `DateOfBirth` (DATE), `Sex` (CHAR(1)), `Village` (VARCHAR(50)), `PhoneNumber` (VARCHAR(15), NULL autorisé)
* **Requête 1 : Lister toutes les patientes féminines âgées de 40 ans ou plus, habitant à Bamenda ou environs, triées par nom de famille.**
```sql
SELECT PatientID, FirstName, LastName, DateOfBirth, Village
FROM Patients
WHERE Sex = 'F'
AND DateOfBirth <= DATE_SUB(CURDATE(), INTERVAL 40 YEAR)
AND (Village = 'Bamenda' OR Village LIKE 'Bamenda%')
ORDER BY LastName, FirstName;
```
> *Explication : DATE_SUB(CURDATE(), INTERVAL 40 YEAR) calcule la date il y a 40 ans. On vérifie que la date de naissance est antérieure ou égale à cette date. Le LIKE 'Bamenda%' attrape les villages comme 'Bamenda Town', 'Bamenda Village'.*
* **Requête 2 : Compter le nombre de patients dont le numéro de téléphone n'est pas enregistré.**
```sql
SELECT COUNT(*) AS PatientsSansTelephone
FROM Patients
WHERE PhoneNumber IS NULL;
```
* **Requête 3 : Lister les patients dont le nom de famille contient 'nga' (insensible à la casse dans beaucoup de systèmes, mais on note la principe).**
```sql
SELECT FirstName, LastName, Village
FROM Patients
WHERE LastName LIKE '%nga%';
```
> *Résultat attendu : Munga, Ngang, Songa, etc. fréquents dans les régions de l'Ouest et du Nord-Ouest.*
### Vocabulaire à retenir
Requête SQL, SELECT, FROM, WHERE, ORDER BY, ASC, DESC, LIKE, %, _, IS NULL, IS NOT NULL, opérateur de comparaison, opérateur logique, critère, filtrage, tri, résultat, agrégation (COUNT), fonction de date (CURDATE, DATE_SUB).
### Exemple de sujet type examen avec plan
**Sujet** : Une base de données gère les informations sur les cultivateurs de cacao dans la région du Sud-Ouest. La table `Farmers` contient : `FarmerID` (PK, INT), `FirstName`, `LastName`, `Village`, `YearsExperience` (INT), `HasCertification` (BOOLEAN, TRUE/FALSE), `AnnualYieldKg` (INT).
**Plan attendu** :
1. Écrire une requête pour lister tous les cultivateurs certifiés (`HasCertification = TRUE`) ayant plus de 10 ans d'expérience, triés par rendement annuel décroissant.
2. Écrire une requête pour compter le nombre de cultivateurs venant du village de 'Kumba' ou ayant un rendement inférieur à 300 kg.
3. Écrire une requête pour afficher le prénom, le nom et le village des cultivateurs dont le nom de famille commence par 'M' et se termine par 'a' (ex. Musa, Mba). Justifier l'utilisation du opérateur LIKE.
4. Expliquer pourquoi on utilise `IS NULL` plutôt que `= NULL` pour vérifier l'absence de données dans un champ optionnel comme un numéro de téléphone (si ajouté au schéma).
## III. Queries 2
### Contexte
Les requêtes avancées (Queries 2) introduisent les fonctions d'agrégation (SUM, AVG, MIN, MAX, COUNT), le regroupement de données (GROUP BY) et le filtrage des groupes (HAVING). Elles permettent de résumer et d'analyser des ensembles de données, passant de la liste individuelle à des synthèses significatives. Cela est essentiel pour la prise de décision basée sur les données dans des contextes comme la planification agricole régionale (MINAGRI), l'allocation budgétaire scolaire (MINEDUC), ou l'évaluation de la performance des centres de santé (MINSANTE).
### Définitions et faits clés
> **Fonction d'agrégation** : Fonction qui effectue un calcul sur un ensemble de valeurs et retourne une seule valeur.
> **SUM()** : Retourne la somme des valeurs numériques d'une colonne. Ignore les NULL.
> **AVG()** : Retourne la moyenne des valeurs numériques d'une colonne. Ignore les NULL.
> **MIN()** : Retourne la plus petite valeur dans une colonne (numérique, date, ou texte selon l'ordre de tri). Ignore les NULL.
> **MAX()** : Retourne la plus grande valeur dans une colonne. Ignore les NULL.
> **COUNT()** : Retourne le nombre de lignes. `COUNT(*)` compte toutes les lignes. `COUNT(colonne)` compte les lignes où la colonne n'est pas NULL.
> **Clause GROUP BY** : Regroupe les lignes ayant les mêmes valeurs dans les colonnes spécifiées, permettant d'appliquer des fonctions d'agrégation à chaque groupe.
> **Clause HAVING** : Filtre les groupes résultant de GROUP BY, basé sur une condition impliquant souvent une fonction d'agrégation. Équivalent de WHERE pour les groupes.
> **Jointure interne (INNER JOIN)** : Retourne uniquement les lignes où il y a une correspondance dans les deux tables selon la condition de jointure. Syntaxe explicite : `TABLE1 INNER JOIN TABLE2 ON TABLE1.col = TABLE2.col`.
> **Jointure gauche (LEFT JOIN)** : Retourne toutes les lignes de la table de gauche, et les lignes correspondantes de la table de droite. Si pas de correspondance, le résultat contient NULL du côté droit. Utile pour trouver des enregistrements sans lien (ex. étudiants sans inscription).
### Syntaxe de base avec agrégation et regroupement
```sql
SELECT colonne1, fonction_agregation(colonne2), ...
FROM nom_table
[WHERE condition]
GROUP BY colonne1, colonne2, ...
[HAVING condition_agregation]
ORDER BY colonne1 [ASC|DESC];
```
### Syntaxe de base d'une jointure
```sql
SELECT t1.colonneA, t2.colonneB
FROM table1 AS t1
[INNER|LEFT|RIGHT] JOIN table2 AS t2
ON t1.colonne_cle = t2.colonne_cle
[WHERE condition]
[ORDER BY ...];
```
### Exemple concret : Base de données de la production agricole d'une coopérative de l'Ouest (ex. Coopérative Café des Monts Bamboutos)
* **Table Farmers** :
`FarmerID` (INT, PK), `FirstName`, `LastName`, `Village`
* **Table Harvests** :
`HarvestID` (INT, PK), `FarmerID` (INT, FK → Farmers.FarmerID), `CropType` (VARCHAR(30)), `HarvestDate` (DATE), `QuantityKg` (DECIMAL(8,2)), `PricePerKg` (DECIMAL(6,2))
* **Requête 1 (Agrégation simple) : Calculer la quantité totale de café récoltée par la coopérative cette année.**
```sql
SELECT SUM(QuantityKg) AS TotalCoffeeKg
FROM Harvests
WHERE CropType = 'Coffee'
AND YEAR(HarvestDate) = YEAR(CURDATE());
```
> *Utilise YEAR() pour extraire l'année de la date.*
* **Requête 2 (GROUP BY) : Trouver le rendement moyen par producteur pour le café.**
```sql
SELECT f.FarmerID, f.FirstName, f.LastName, AVG(h.QuantityKg) AS AvgYieldKg
FROM Farmers f
INNER JOIN Harvests h ON f.FarmerID = h.FarmerID
WHERE h.CropType = 'Coffee'
GROUP BY f.FarmerID, f.FirstName, f.LastName
ORDER BY AvgYieldKg DESC;
```
> *INNER JOIN garantit qu'on ne considère que les producteurs ayant effectivement récolté du café. GROUP BY par producteur permet de calculer la moyenne pour chacun.*
* **Requête 3 (HAVING) : Lister les villages dont la production totale de café dépasse 5000 kg.**
```sql
SELECT f.Village, SUM(h.QuantityKg) AS TotalVillageKg
FROM Farmers f
INNER JOIN Harvests h ON f.FarmerID = h.FarmerID
WHERE h.CropType = 'Coffee'
GROUP BY f.Village
HAVING SUM(h.QuantityKg) > 5000
ORDER BY TotalVillageKg DESC;
```
> *HAVING filtre après le GROUP BY : on ne garde que les villages où la somme agrégée dépasse le seuil.*
* **Requête 4 (LEFT JOIN pour trouver les absents) : Trouver les producteurs qui n'ont pas enregistré de récolte de café cette saison.**
```sql
SELECT f.FarmerID, f.FirstName, f.LastName, f.Village
FROM Farmers f
LEFT JOIN Harvests h ON f.FarmerID = h.FarmerID AND h.CropType = 'Coffee' AND YEAR(h.HarvestDate) = YEAR(CURDATE())
WHERE h.HarvestID IS NULL;
```
> *Le LEFT JOIN garde tous les producteurs. La condition dans ON limite la jointure au café de l'année courante. Ceux sans récolte auront tous les champs de h à NULL → filtré par `h.HarvestID IS NULL`.*
### Vocabulaire à retenir
Fonction d'agrégation, SUM, AVG, MIN, MAX, COUNT, COUNT(*), GROUP BY, HAVING, INNER JOIN, LEFT JOIN, RIGHT JOIN, clause de jointure, condition de jointure, alias de table (AS), fonction de date (YEAR, CURDATE), agrégation par groupe, filtrage de groupe, résultat agrégé.
### Exemple de sujet type examen avec plan
**Sujet** : Une ONG camerounaise suit la distribution de moustiquaires imprégnées dans les régions du Nord et de l'Extrême-Nord. La table `Distributions` contient : `DistID` (PK, INT), `VillageID` (INT, FK → Villages.VillageID), `DateDist` (DATE), `NetsDistributed` (INT). La table `Villages` contient : `VillageID` (PK, INT), `VillageName`, `Region` (VARCHAR(20)), `Population`.
**Plan attendu** :
1. Écrire une requête pour calculer le nombre total de moustiquaires distribuées dans la région de l'Extrême-Nord cette année (en supposant que le champ Region contient exactement 'Extreme-Nord').
2. Écrire une requête utilisant GROUP BY pour trouver le nombre moyen de moustiquaires distribuées par distribution dans chaque village de la région du Nord. Inclure le nom du village et la moyenne. Trier par moyenne décroissante.
3. Écrire une requête utilisant HAVING pour lister les régions où le total de moustiquaires distribuées dépasse 10 000 unités.
4. Écrire une requête utilisant LEFT JOIN pour identifier les villages de la région du Nord qui n'ont reçu aucune distribution cette année. Expliquer pourquoi LEFT JOIN est nécessaire ici et pas INNER JOIN.
5. Justifier l'utilisation de l'alias de table (ex. `v` pour Villages, `d` pour Distributions) dans les requêtes comportant des jointures.
## IV. Reports and forms
### Contexte
Les requêtes extraient les données, mais pour une utilisation efficace par des non-techniciens (agents administratifs, enseignants, agriculteurs), il faut présenter ces informations de manière claire, structurée et adaptée à l'impression ou à l'interaction. Les rapports (Reports) sont destinés principalement à l'impression ou à l'export (PDF, Excel) pour présenter des synthèses, des listes ou des analyses. Les formulaires (Forms) sont des interfaces interactives pour saisir, modifier ou consulter des données de manière guidée et conviviale. Dans le système éducatif camerounais, un rapport pourrait lister les résultats du BAC par région, tandis qu'un formulaire pourrait faciliter l'inscription des nouveaux élèves en début d'année scolaire dans un lycée technique.
### Définitions et faits clés
> **Rapport (Report)** : Objet de base de données conçu pour présenter des données de manière formatée, généralement destiné à l'impression ou à l'exportation. Met l'accent sur la mise en page, le regroupement, les totaux intermédiaires et généraux, et l'en-tête/pied de page.
> **Formulaire (Form)** : Objet de base de données fournissant une interface graphique pour interagir avec les données (ajouter, modifier, supprimer, consulter un enregistrement). Utilise des contrôles comme zones de texte, listes déroulantes, cases à cocher, boutons de commande.
> **En-tête de rapport** : Section apparaissant en haut de chaque page (ou du rapport entier), contenant souvent le titre, la date, le logo.
> **Pied de rapport** : Section apparaissant en bas de chaque page (ou du rapport entier), contenant souvent les numéros de page, la date d'impression.
> **En-tête de groupe** : Section dans un rapport qui apparaît avant chaque groupe de données (défini par un champ de regroupement), utile pour introduire une catégorie (ex. nom du village avant ses producteurs).
> **Pied de groupe** : Section dans un rapport qui apparaît après chaque groupe de données, utile pour afficher des sous-totaux (ex. total de production par village).
> **Pied de rapport** : Section pour les totaux généraux (ex. production totale nationale).
> **Contrôle lié** : Contrôle dans un formulaire ou un rapport dont la source de données est directement liée à un champ d'une table ou d'une requête (ex. une zone de texte montrant le `FirstName` provenant de la table `Students`).
> **Contrôle non lié** : Contrôle dont la source de données n'est pas liée à un champ (ex. une étiquette de titre, un bouton qui exécute une macro).
> **Zone de liste déroulante (Combo Box)** : Contrôle permettant à l'utilisateur de sélectionner une valeur parmi une liste prédéfinie (souvent provenant d'une autre table ou requête), utile pour garantir la cohérence des données (ex. sélection d'un `StreamID` à partir de la table `Streams`).
> **Bouton de commande** : Contrôle qui déclenche une action lorsqu'il est cliqué (ex. ouvrir un autre formulaire, imprimer le rapport actuel, fermer la fenêtre).
### Exemple concret : Système de gestion des résultats scolaires (Lycée de Buea)
* **Objectif du Rapport** : Produire un relevé de notes trimestriel pour une classe de Upper Sixth Sciences, montrant la moyenne de chaque élève par matière et leur rang dans la classe.
* **Source** : Requête nommée `qryStudentTermResults` (déjà créée) contenant : `StudentID`, `FirstName`, `LastName`, `SubjectName`, `Score`, `Term`.
* **Structure du Rapport** :
* En-tête du rapport : "Lycée de Buea - Relevé de Notes Trimestriel - 3ème Trimestre - Classe: Upper Sixth Sciences" + Logo + Date d'impression.
* En-tête de groupe (regroupé par `StudentID`, `FirstName`, `LastName`) : Affiche les informations de l'élève (Nom, Prénom, Matricule).
* Détail : Liste les matières (`SubjectName`) et les scores (`Score`) pour cet élève.
* Pied de groupe : Calcule et affiche la moyenne des scores pour l'élève (`AVG([Score])`) et son rang dans la classe (nécessiterait une sous-requête ou un calcul complexe, mais au niveau du concept : afficher un total/moyenne par groupe).
* Pied de rapport : Affiche le nombre total d'élèves dans le rapport (`COUNT([StudentID])`) et la moyenne générale de la classe.
* **Mise en forme** : Utilisation de polices lisibles (Arial, taille 10 pour le détail, 12 bold pour les en-têtes), alignement des colonnes, lignes de séparation subtiles, format numérique pour les scores (1 décimale).
* **Objectif du Formulaire** : Faciliter l'inscription d'un nouvel élève en début d'année.
* **Source** : Table `Students` (et potentiellement requêtes pour les listes déroulantes de Filières et Niveaux).
* **Structure du Formulaire** :
* Étiquette (Label) non liée : "Nouvelle Inscription - Année Académique 2024/2025"
* Zone de texte liée : liée à `FirstName` (avec étiquette "Prénom :")
* Zone de texte liée : liée à `LastName` (avec étiquette "Nom :")
* Zone de texte liée : liée à `DateOfBirth` (avec étiquette "Date de Naissance :", format court)
* Liste déroulante liée : liée à `StreamID`, mais dont la liste des options provient de la requête `qryStreamsList` (affichant `StreamName`, cachant `StreamID`) (avec étiquette "Filière :")
* Liste déroulante liée : liée à `LevelID`, liste provenant de `qryLevelsList` (affichant `LevelName`) (avec étiquette "Niveau :")
* Bouton de commande lié : "Enregistrer l'étudiant" (déclenche une action de sauvegarde et de fermeture)
* Bouton de commande lié : "Annuler" (ferme le formulaire sans sauvegarder)
* **Fonctionnalités clés** :
* Les listes déroulantes empêchent les erreurs de saisie (on ne peut pas taper "Sciece" pour Filière, on doit choisir dans la liste).
* Le format de la zone de texte Date de Naissance assure une saisie cohérente (JJ/MM/AAAA ou AAAA-MM-JJ selon les paramètres régionaux).
* Les boutons de commande guident l'utilisateur vers les actions souhaitées.
### Vocabulaire à retenir
Rapport, Formulaire, En-tête, Pied de page, En-tête de groupe, Pied de groupe, Contrôle lié, Contrôle non lié, Zone de texte, Étiquette (Label), Liste déroulante (Combo Box), Bouton de commande, Source de données, Mise en page, Regroupement, Totaux intermédiaires, Totaux généraux, Interface utilisateur, Saisie guidée.
### Exemple de sujet type examen avec plan
**Sujet** : Le ministère de l'Éducation de base souhaite créer un outil pour suivre la distribution des manuels scolaires dans les écoles publiques d'une division. Une base de données contient les tables `Schools` (SchoolID, SchoolName, Division, SubDivision, HasLibrary) et `BookDistributions` (DistID, SchoolID, BookTitle, QuantityDistributed, DistDate).
**Plan attendu** :
1. Décrire l'objectif et le contenu d'un **rapport** destiné à être imprimé chaque trimestre pour les inspecteurs pédagogiques, montrant la répartition des distributions de manuels par école et par titre de livre, avec des totaux par école et un total général. Préciser les regroupements, les en-têtes/pieds de page/groupes utiles, et les contrôles liés à utiliser pour les champs et les calculs (totaux).
2. Décrire l'objectif et la structure d'un **formulaire** destiné aux responsables de division pour saisir une nouvelle distribution de manuels dans une école. Préciser les contrôles à utiliser (zones de texte, listes déroulantes pour choisir l'école et le titre du livre à partir de listes préremplies, boutons de commande), leur liaison (liés/non liés), et comment ils empêchent les erreurs de saisie (ex. sélection d'école valide, quantité numérique positive).
3. Expliquer comment l'utilisation d'une liste déroulante liée à la table `Schools` dans le formulaire améliore la qualité des données par rapport à une simple zone de texte où l'on taperait le nom de l'école.
4. Justifier le choix d'utiliser un pied de groupe dans le rapport pour afficher le total de manuels distribués par école, plutôt que de le calculer manuellement après impression.
Quiz du chapitre
12 questions — vérifie chaque réponse pour voir l'explication.