<?xml version="1.0" encoding="UTF-8"?>
<quiz>
<question type="category">
  <category>
    <text>$course$/QCM de NSI/Terminale/Bases de données et SQL</text>
  </category>
  <info format="html">
    <text><![CDATA[<p>Modèle relationnel (tables, attributs, clés primaires<br/>
et étrangères), contraintes d'intégrité, anomalies dans<br/>
un schéma, langage SQL (SELECT, FROM, WHERE, JOIN,<br/>
INSERT, UPDATE, DELETE), services rendus par un SGBD.</p>]]></text>
  </info>
</question>

<question type="multichoice">
  <name>
    <text>Bases de données et SQL — Q01 : Définition d'un SGBD</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Que désigne le sigle SGBD ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Un SGBD relationnel (SGBDR) ajoute la gestion du modèle<br/>
relationnel et du langage SQL. Tous les exemples cités<br/>
ci-dessus sont des SGBDR.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Système de Génération Binaire de Données</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : sigle inventé. SGBD est lié à la <strong>gestion</strong><br/>
des bases de données.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Stockage Garanti des Bases Distribuées</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : sigle inventé.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Standard Général des Bibliothèques de Données</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : sigle inventé.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Système de Gestion de Base de Données</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : un SGBD est un logiciel qui permet de<br/>
stocker, organiser, interroger et sécuriser des<br/>
données. Exemples : MySQL, PostgreSQL, SQLite, Oracle.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Bases de données et SQL — Q02 : Vocabulaire du modèle relationnel</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Dans le modèle relationnel, comment appelle-t-on <strong>une ligne</strong><br/>
d'une table ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Vocabulaire du modèle relationnel : <strong>table</strong> (relation),<br/>
<strong>ligne</strong> (n-uplet, enregistrement), <strong>colonne</strong> (attribut),<br/>
<strong>domaine</strong> (type des valeurs), <strong>clé primaire</strong> (identifiant<br/>
unique).</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Un attribut</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : un attribut est une <strong>colonne</strong> (un champ),<br/>
pas une ligne.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Un domaine</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : un domaine est l'ensemble des valeurs possibles<br/>
pour un attribut (par exemple, les entiers naturels<br/>
pour l'âge).</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Un n-uplet</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : une ligne d'une table relationnelle est<br/>
un n-uplet (en français) ou <em>tuple</em> (en anglais), aussi<br/>
appelé enregistrement. Elle représente une instance<br/>
d'entité.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Une clé</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : une clé est une combinaison d'attributs qui<br/>
identifie de manière unique chaque ligne.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Bases de données et SQL — Q03 : Clé primaire</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Quelle est la propriété fondamentale d'une <strong>clé primaire</strong> ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Une clé primaire est : (1) unique, (2) non nulle, (3) stable<br/>
dans le temps. Elle peut être composite (composée de<br/>
plusieurs colonnes) si aucune colonne unique ne suffit.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Elle identifie de façon unique chaque ligne</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : la clé primaire est par définition<br/>
unique dans la table. Deux lignes ne peuvent jamais<br/>
avoir la même valeur de clé primaire.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Elle doit obligatoirement être un nombre entier positif</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : une clé primaire peut être de n'importe quel<br/>
type (chaîne, code-barre, identifiant composite). Le<br/>
type entier est seulement le plus courant.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Elle doit toujours être une seule colonne</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : une clé primaire peut être <strong>composite</strong> (sur<br/>
plusieurs colonnes). Par exemple, dans une table<br/>
d'inscriptions, le couple (eleve_id, cours_id) peut<br/>
être une clé primaire composite.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Elle peut prendre la valeur NULL</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : une clé primaire ne peut <strong>jamais</strong> être<br/>
NULL, sinon elle ne pourrait plus identifier une<br/>
ligne de manière unique.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Bases de données et SQL — Q04 : Clé étrangère</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Que représente une <strong>clé étrangère</strong> dans une table ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Les clés étrangères implémentent les <strong>relations</strong> entre<br/>
tables et permettent au SGBD de garantir l'<strong>intégrité référentielle</strong> : on ne peut pas créer une commande pour<br/>
un client inexistant.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Une clé importée d'un autre fichier</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : « étrangère » ne signifie pas « importée<br/>
d'un fichier ». Elle référence simplement une autre<br/>
<strong>table</strong> dans la même base.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Une clé dont la valeur ne peut jamais être modifiée ensuite</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : la modification est possible. Le terme<br/>
« étrangère » concerne la référence vers une autre<br/>
table.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Un attribut crypté pour la sécurité</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : aucune notion de chiffrement dans le concept<br/>
de clé étrangère. C'est une notion structurelle, pas<br/>
de sécurité.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Un attribut référençant la clé primaire d'une autre table</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : la clé étrangère établit un lien<br/>
relationnel entre deux tables. Par exemple, dans une<br/>
table Commandes, l'attribut client_id référence<br/>
la clé primaire de la table Clients.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Bases de données et SQL — Q05 : Syntaxe de base de SELECT</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Quelle est la syntaxe SQL pour récupérer <strong>toutes</strong> les<br/>
colonnes de la table eleves ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Bonne pratique : éviter SELECT * en production et lister<br/>
explicitement les colonnes nécessaires. Cela rend le code<br/>
plus robuste aux évolutions de schéma et plus clair.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>SELECT eleves</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : la syntaxe SELECT requiert au minimum la<br/>
liste des colonnes (ou *) puis FROM pour la table.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>GET ALL FROM eleves</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : GET n'existe pas en SQL. La commande de<br/>
lecture est SELECT.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>READ eleves</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : READ n'est pas un mot-clé SQL. La lecture<br/>
se fait avec SELECT.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>SELECT * FROM eleves</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : * est le joker qui désigne toutes<br/>
les colonnes. FROM indique la table source.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Bases de données et SQL — Q06 : Filtrage avec WHERE</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Pour ne sélectionner que les élèves majeurs de la table<br/>
eleves, quelle requête utiliser ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Une requête SQL classique a la forme :<br/>
SELECT colonnes FROM table WHERE condition. Les<br/>
conditions multiples se combinent avec AND, OR, NOT.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>SELECT * FROM eleves IF age &gt;= 18</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : IF n'est pas un mot-clé SQL pour le<br/>
filtrage. Le filtre se fait avec WHERE.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>SELECT * FROM eleves CONDITION age &gt;= 18</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : CONDITION n'existe pas en SQL. C'est WHERE<br/>
qui introduit la condition.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>FILTER eleves WHERE age &gt;= 18</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : FILTER n'est pas la syntaxe SQL standard.<br/>
On utilise SELECT ... WHERE.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>SELECT * FROM eleves WHERE age &gt;= 18</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : WHERE introduit la condition de<br/>
filtrage. La syntaxe est WHERE condition, où la<br/>
condition compare des valeurs avec les opérateurs<br/>
=, &lt;, &gt;, &lt;=, &gt;= ou &lt;&gt;.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Bases de données et SQL — Q07 : Tri avec ORDER BY</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Pour afficher les élèves par ordre alphabétique de leur<br/>
nom, on utilise :</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Pour trier par nom puis par prénom : ORDER BY nom, prenom.<br/>
Pour ordre décroissant : ORDER BY nom DESC. On peut<br/>
mélanger : ORDER BY classe ASC, moyenne DESC.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>SELECT * FROM eleves ORDER BY nom</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : ORDER BY trie le résultat selon une<br/>
ou plusieurs colonnes. Par défaut, l'ordre est<br/>
ascendant (ASC). Pour un ordre descendant, ajouter<br/>
DESC.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>SELECT * FROM eleves ARRANGE BY nom</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : ARRANGE BY n'est pas du SQL valide.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>SELECT * FROM eleves SORT BY nom</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : SORT BY n'est pas une syntaxe SQL. Le tri<br/>
se fait avec ORDER BY.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>SELECT * FROM eleves SORTED nom</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : SORTED n'existe pas en SQL.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Bases de données et SQL — Q08 : Contraintes d'intégrité</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Qu'est-ce qu'une <strong>contrainte d'intégrité</strong> dans une base de<br/>
données relationnelle ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Les contraintes d'intégrité sont <strong>vérifiées automatiquement</strong> par le SGBD à chaque modification. Si<br/>
une opération les violerait, elle est rejetée. C'est une<br/>
garantie forte de cohérence.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Un mot de passe pour accéder à une table</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : aucun rapport avec l'authentification. Les<br/>
contraintes d'intégrité concernent la cohérence des<br/>
données, pas la sécurité d'accès.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Une règle restreignant les valeurs admissibles, vérifiée par le SGBD</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : les contraintes garantissent la<br/>
cohérence des données. Exemples : NOT NULL (valeur<br/>
obligatoire), UNIQUE (pas de doublon), clé primaire,<br/>
clé étrangère, CHECK (condition arbitraire).</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Un index pour accélérer les requêtes</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : les index sont des structures auxiliaires<br/>
pour la performance, pas des règles de cohérence.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Une copie de sauvegarde automatique et régulière des données</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : aucun rapport avec les sauvegardes.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Bases de données et SQL — Q09 : Insertion d'une ligne</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Quelle commande SQL ajoute une ligne dans une table ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Les quatre commandes principales pour manipuler les données<br/>
d'une table sont : SELECT (lire), INSERT (ajouter),<br/>
UPDATE (modifier), DELETE (supprimer).</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>CREATE INTO eleves VALUES ('Alice', 17)</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : CREATE est utilisé pour créer une table<br/>
(CREATE TABLE), pas pour insérer une ligne.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>INSERT INTO eleves VALUES ('Alice', 17)</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : INSERT INTO table VALUES (...) est la<br/>
forme classique. On peut aussi préciser les colonnes :<br/>
INSERT INTO eleves (nom, age) VALUES ('Alice', 17).</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>ADD INTO eleves VALUES ('Alice', 17)</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : ADD n'est pas la syntaxe SQL standard pour<br/>
ajouter une ligne.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>PUT INTO eleves VALUES ('Alice', 17)</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : PUT n'existe pas en SQL.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Bases de données et SQL — Q10 : Valeurs atomiques</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Dans une base relationnelle correctement conçue, on<br/>
attend que chaque attribut contienne une valeur<br/>
<strong>atomique</strong>. Que signifie cette propriété ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Stocker des valeurs non atomiques (listes, couples,<br/>
tableaux) dans une cellule est une anomalie<br/>
fréquente. Cela empêche de filtrer ou de joindre<br/>
facilement la donnée et peut générer des<br/>
redondances et des incohérences.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>La valeur doit impérativement être un nombre entier</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : aucune contrainte de type. Une valeur<br/>
atomique peut être une chaîne, un booléen, un<br/>
flottant…</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>La valeur ne peut jamais être modifiée</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : « atomique » ne signifie pas<br/>
« immuable ». Les valeurs peuvent évidemment<br/>
être mises à jour avec UPDATE.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>La valeur ne peut jamais être nulle (NULL interdit)</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : aucun rapport. L'absence de valeur est<br/>
gérée par NULL ou par la contrainte<br/>
NOT NULL.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>La valeur ne se décompose pas en plusieurs informations</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : un attribut comme<br/>
telephones = "06 12 ; 06 34" mélange deux<br/>
informations dans une cellule, ce qui rend les<br/>
requêtes difficiles. Il faut alors créer une<br/>
seconde table reliée par une clé étrangère.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Bases de données et SQL — Q11 : Jointure entre deux tables</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Pour combiner les tables commandes et clients en<br/>
reliant commandes.client_id à clients.id, quelle<br/>
syntaxe utiliser ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Une jointure s'écrit FROM table1 JOIN table2 ON condition.<br/>
La condition relie en général la clé étrangère d'une table à<br/>
la clé primaire de l'autre ; les lignes sans correspondance<br/>
n'apparaissent pas dans le résultat.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>SELECT * FROM commandes JOIN clients</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : sans condition ON, rien n'indique quelle commande<br/>
va avec quel client. Chaque commande est associée à chaque<br/>
client, ce qui n'a aucun sens.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>SELECT * FROM commandes JOIN clients ON commandes.id = clients.id</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : la condition relie la clé primaire des<br/>
commandes à celle des clients, alors que le lien est<br/>
porté par la clé étrangère commandes.client_id.<br/>
Chaque commande serait associée au client dont<br/>
l'identifiant coïncide par hasard avec son propre<br/>
numéro, ce qui n'a aucun sens.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>SELECT * FROM commandes JOIN clients ON commandes.client_id = clients.id</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : la condition ON relie la clé étrangère<br/>
commandes.client_id à la clé primaire clients.id. Seules<br/>
les commandes ayant un client correspondant apparaissent.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>SELECT * FROM commandes WHERE commandes.client_id = clients.id</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : la table clients n'est citée ni dans FROM ni dans<br/>
un JOIN. Le SGBD ne connaît donc pas clients.id et signale<br/>
une colonne inconnue.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Bases de données et SQL — Q12 : Fonctions d'agrégation</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Pour calculer la <strong>moyenne des âges</strong> des élèves, quelle<br/>
requête utiliser ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Les fonctions d'agrégation principales en SQL sont<br/>
COUNT, SUM, AVG, MIN et MAX. Elles<br/>
synthétisent une colonne entière en une seule<br/>
valeur dans le résultat de la requête.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>SELECT (age) FROM eleves AVERAGE</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : la syntaxe AVERAGE après le FROM n'existe<br/>
pas. Les fonctions d'agrégation s'appliquent à<br/>
l'intérieur du SELECT.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>SELECT AVG(age) FROM eleves</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : AVG (<em>average</em>) calcule la moyenne<br/>
arithmétique. Les fonctions d'agrégation principales<br/>
sont COUNT, SUM, AVG, MIN, MAX.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>SELECT MOYENNE(age) FROM eleves</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : SQL utilise des mots-clés en anglais. La<br/>
version française n'existe pas.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>SELECT MEAN(age) FROM eleves</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : la fonction de moyenne en SQL standard<br/>
s'appelle AVG, pas MEAN.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Bases de données et SQL — Q13 : Combiner WHERE et ORDER BY</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Quelle requête renvoie les noms des élèves majeurs,<br/>
classés par âge <strong>décroissant</strong> ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>L'ordre canonique des clauses dans une requête<br/>
d'interrogation est : SELECT … FROM … WHERE …<br/>
ORDER BY …. Le mot-clé DESC après ORDER BY<br/>
indique un tri décroissant ; ASC (par défaut)<br/>
indique un tri croissant.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>SELECT nom FROM eleves ORDER BY age DESC WHERE age &gt;= 18</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : l'ordre des clauses est imposé en SQL.<br/>
WHERE se place avant ORDER BY.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>SELECT nom FROM eleves WHERE age &gt;= 18 ORDER BY age</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : sans le mot-clé DESC, le tri se fait<br/>
par défaut en ordre croissant.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>SELECT nom FROM eleves WHERE age &gt;= 18 ORDER BY age DESC</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : WHERE filtre les lignes<br/>
(majeurs), puis ORDER BY age DESC les trie par<br/>
âge décroissant.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>SELECT nom FROM eleves WHERE age &gt;= 18 SORT age DESC</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : la clause SORT n'existe pas en SQL<br/>
standard. Il faut utiliser ORDER BY.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Bases de données et SQL — Q14 : Modification d'une ligne</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Pour augmenter de 1 point la note de l'élève d'identifiant<br/>
42, quelle requête utiliser ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Toujours penser à mettre une clause WHERE sur les<br/>
UPDATE et DELETE. <strong>Sans elle, la modification s'applique à toutes les lignes</strong> de la table, ce qui est rarement ce<br/>
qu'on veut et souvent catastrophique.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>MODIFY eleves SET note = note + 1 WHERE id = 42</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : MODIFY n'est pas un mot-clé SQL standard.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>UPDATE eleves SET note = note + 1 WHERE id = 42</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : UPDATE met à jour des lignes<br/>
existantes. La clause SET indique les modifications<br/>
et WHERE filtre les lignes affectées.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>UPDATE eleves WHERE id = 42 SET note = note + 1</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : ordre incorrect des clauses. La syntaxe<br/>
standard est UPDATE table SET ... WHERE ....</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>CHANGE eleves SET note = note + 1 WHERE id = 42</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : CHANGE n'est pas un mot-clé SQL standard.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Bases de données et SQL — Q15 : Suppression de doublons</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Pour obtenir la liste des <strong>classes différentes</strong> présentes<br/>
dans la table eleves (sans doublons), quelle requête<br/>
utiliser ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>DISTINCT agit sur l'ensemble des colonnes<br/>
sélectionnées. Par exemple,<br/>
SELECT DISTINCT nom, prenom FROM eleves ne renverra<br/>
qu'une ligne par couple (nom, prenom) distinct.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>SELECT DISTINCT classe FROM eleves</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : DISTINCT élimine les doublons. Si<br/>
la table contient 30 élèves de la classe « 1NSI »<br/>
et 25 de « TNSI », la requête renvoie deux lignes :<br/>
« 1NSI » et « TNSI ».</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>SELECT classe DISTINCT FROM eleves</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : DISTINCT se place <strong>avant</strong> la liste des<br/>
colonnes, juste après SELECT.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>SELECT UNIQUE classe FROM eleves</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : UNIQUE est utilisé pour les contraintes au<br/>
moment de la création de table, pas pour la sélection.<br/>
Le mot-clé pour la sélection est DISTINCT.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>SELECT classe FROM eleves</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : sans DISTINCT, le résultat contiendra une<br/>
entrée par élève, donc beaucoup de doublons.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Bases de données et SQL — Q16 : Représenter une association multiple</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>On souhaite représenter le fait qu'un élève peut<br/>
suivre <strong>plusieurs cours</strong> et qu'un cours peut<br/>
accueillir <strong>plusieurs élèves</strong>. Quel schéma<br/>
relationnel adopter ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Une association « plusieurs à plusieurs » se<br/>
représente par une table d'association qui contient<br/>
les clés étrangères des deux entités liées. C'est un<br/>
patron classique du modèle relationnel pour éviter<br/>
les redondances.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Une seule table eleves avec autant de colonnes cours_1, cours_2, cours_3 qu'il y a de cours possibles</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : ce schéma est rigide (il faut<br/>
modifier la structure si un nouveau cours<br/>
apparaît) et la plupart des cellules seront<br/>
vides.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Une seule table contenant eleve et tous ses cours dans une même cellule</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : on viole la propriété d'atomicité des<br/>
attributs et on ne peut plus interroger<br/>
facilement les données.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Trois tables eleves(id, nom), cours(id, intitule) et inscriptions(eleve_id, cours_id) reliées par des clés étrangères</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : on isole chaque entité dans sa<br/>
table et on crée une table <strong>d'association</strong><br/>
dont chaque ligne représente une inscription<br/>
d'un élève à un cours.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Deux tables avec une duplication des cours dans chaque ligne d'élève</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : la duplication crée des redondances et<br/>
des anomalies de mise à jour si l'intitulé<br/>
d'un cours change.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Bases de données et SQL — Q18 : Suppression d'une ligne</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Que fait la requête DELETE FROM eleves; ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Toujours utiliser WHERE avec DELETE, sauf intention<br/>
explicite de tout vider. Beaucoup de SGBD permettent<br/>
d'imposer une clause WHERE obligatoire en mode<br/>
« <em>safe updates</em> » pour éviter les catastrophes.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Elle lève une erreur SQL</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : la syntaxe est valide. Aucune erreur n'est<br/>
levée : c'est précisément le piège.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Elle supprime la table entière (structure et contenu)</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : c'est DROP TABLE qui supprime la structure.<br/>
DELETE FROM ne touche que les lignes, pas le schéma.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Elle supprime toutes les lignes de la table eleves</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : DELETE sans clause WHERE vide la<br/>
table (mais la structure reste). C'est l'erreur<br/>
classique en production. Pour supprimer la table<br/>
entière (structure incluse), il faut DROP TABLE eleves.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Elle ne fait rien (manque de WHERE)</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : sans WHERE, la requête s'applique à<br/>
<strong>toutes</strong> les lignes. Elle est syntaxiquement valide.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Bases de données et SQL — Q19 : Services rendus par un SGBD</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Lequel des éléments suivants n'est <strong>pas</strong> un<br/>
service rendu par un système de gestion de bases de<br/>
données ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Les services principaux d'un SGBD sont la<br/>
persistance, la gestion des accès concurrents,<br/>
l'efficacité du traitement des requêtes et la<br/>
sécurisation des accès. Le programme officiel<br/>
demande de les <strong>identifier</strong>, sans en détailler le<br/>
fonctionnement interne.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>La gestion des accès concurrents par plusieurs utilisateurs ou programmes</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : c'est bien un service du SGBD, qui évite<br/>
les incohérences quand plusieurs requêtes<br/>
modifient les mêmes données simultanément.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>La persistance des données (les données survivent à l'arrêt du programme)</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : c'est bien un service du SGBD, qui assure<br/>
le stockage durable des données sur disque.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>La sécurisation des accès (authentification, droits par utilisateur)</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : c'est bien un service du SGBD, qui<br/>
contrôle qui peut lire ou modifier quoi.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>La compilation du code source d'un programme Python</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : la compilation de code Python<br/>
n'a aucun rapport avec un SGBD. C'est le rôle de<br/>
l'interpréteur Python ou d'un compilateur, pas<br/>
du gestionnaire de bases de données.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Bases de données et SQL — Q20 : Intégrité référentielle</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Quelle situation viole l'<strong>intégrité référentielle</strong> ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>L'intégrité référentielle est garantie par la clé étrangère :<br/>
le SGBD refuse toute insertion ou modification qui ferait<br/>
pointer client_id vers un client inexistant, et refuse aussi<br/>
de supprimer un client encore cité par des commandes.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Avoir deux clients avec le même nom</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : ce n'est pas une violation tant que la clé<br/>
primaire (l'id) est unique. Le nom peut être en<br/>
double.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Insérer une commande avec un client_id inexistant dans clients</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : la clé étrangère client_id doit<br/>
pointer vers une ligne existante de la table<br/>
clients. Sinon, on a une référence orpheline,<br/>
violation typique de l'intégrité référentielle.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Insérer une commande sans préciser la quantité</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : une valeur manquante concerne l'attribut lui-même,<br/>
pas l'intégrité référentielle. Cette dernière porte sur les<br/>
références d'une table vers une autre.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Trier l'ensemble des commandes par leur date croissante</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : un tri ne viole aucune contrainte.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Bases de données et SQL — Q22 : Détection d'une redondance</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Une table commandes(id, client_id, nom_client, prenom_client, produit, prix)<br/>
pose un problème classique de schéma. Lequel ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>La normalisation vise à éliminer les redondances pour<br/>
garantir la <strong>cohérence</strong>. Si on stocke le nom du client<br/>
dans chaque commande et que le client se marie, il faut<br/>
mettre à jour toutes ses commandes, risqué et coûteux.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Le prix devrait être stocké dans une table produits séparée</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : le prix peut varier d'une commande à l'autre<br/>
(promotions, historiques) et a sa place dans commandes.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Les informations du client sont dupliquées à chaque commande</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : c'est une <strong>redondance</strong><br/>
classique, source d'incohérences. Le nom et le prénom dépendent de<br/>
client_id, pas de l'id de commande. Il<br/>
faudrait les mettre dans une table clients<br/>
séparée et conserver uniquement la clé<br/>
étrangère client_id dans commandes.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>La clé primaire de la table est manifestement mal choisie</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : id est un choix raisonnable de clé primaire<br/>
pour des commandes.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>La table contient trop de colonnes pour être performante</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : le nombre de colonnes n'est pas un problème<br/>
en soi. Le problème est ailleurs.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Bases de données et SQL — Q23 : Anomalie de suppression</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Le lycée enregistre les inscriptions aux clubs dans une seule<br/>
table :</p>
<p>`<code><br/>
| id_inscription | nom_eleve | club      | salle |<br/>
|----------------|-----------|-----------|-------|<br/>
| 1              | Amina     | Échecs    | B12   |<br/>
| 2              | Basile    | Théâtre   | A03   |<br/>
| 3              | Chloé     | Théâtre   | A03   |<br/>
| 4              | Dorian    | Robotique | C07   |<br/>
</code></p>
<p>Dorian quitte le club de robotique, et l'on exécute<br/>
DELETE FROM inscriptions WHERE id_inscription = 4;`.<br/>
Quel défaut du schéma cette suppression révèle-t-elle ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>La table mélange deux informations : les inscriptions et les<br/>
salles des clubs. On sépare le schéma en<br/>
clubs(<em>id_club, nom, salle) et<br/>
inscriptions(</em>id_inscription, nom_eleve, id_club#) : supprimer<br/>
une inscription ne fait alors plus rien perdre sur le club.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Le SGBD refuse la suppression, la salle C07 étant encore utilisée</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : aucune clé étrangère ne relie cette table à une table<br/>
de salles. Rien n'empêche la suppression, qui est acceptée, et<br/>
c'est justement ce qui fait perdre l'information.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>La requête supprime aussi les autres inscriptions de Dorian</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : la condition id_inscription = 4 désigne une seule<br/>
ligne, puisque id_inscription est la clé primaire. Aucune autre<br/>
ligne n'est touchée.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Aucun défaut : chaque club garde sa salle dans une autre ligne</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : c'est vrai pour le théâtre, présent dans deux lignes,<br/>
mais pas pour la robotique, qui n'apparaissait que dans la ligne<br/>
supprimée.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>La base ne sait plus que la robotique a lieu en salle C07</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : la salle d'un club n'est enregistrée que dans<br/>
les lignes d'inscription. En supprimant la seule inscription au<br/>
club de robotique, on perd aussi cette information : c'est une<br/>
anomalie de suppression.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Bases de données et SQL — Q24 : Problème de concurrence</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Si le SGBD ne gérait pas les accès concurrents, deux programmes<br/>
qui modifient en même temps le même compte bancaire pourraient<br/>
provoquer :</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>La gestion des accès concurrents est l'un des<br/>
services principaux d'un SGBD. Le système prend en<br/>
charge l'enchaînement des opérations pour garantir<br/>
la cohérence des données, même quand plusieurs<br/>
utilisateurs ou programmes les manipulent en même<br/>
temps.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Une accélération de l'exécution des deux programmes</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : sans gestion des accès concurrents, on obtient au<br/>
contraire des incohérences. La coordination des écritures<br/>
demande un peu de temps, mais rend les données fiables.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Une perte de mise à jour : une modification efface l'effet de l'autre</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : si le programme A lit le solde (1000), puis<br/>
le programme B le lit aussi (1000), puis A ajoute 100 et<br/>
écrit 1100, puis B ajoute 50 et écrit 1050, le dépôt<br/>
de A est perdu. C'est la <strong>perte de mise à jour</strong><br/>
classique.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Une duplication automatique des données</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : aucune duplication automatique. C'est plutôt<br/>
de la perte d'information.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Une erreur de syntaxe SQL au moment de l'exécution</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : la syntaxe est correcte. Le problème est de<br/>
<strong>cohérence</strong>, pas syntaxique.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Bases de données et SQL — Q26 : Structure ou contenu d'une base</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Dans la base de données d'un lycée, laquelle de ces opérations<br/>
modifie la <strong>structure</strong> de la base, et non son contenu ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>La structure d'une base est l'ensemble de ses schémas<br/>
relationnels : relations, attributs, domaines, clés primaires et<br/>
étrangères. Le contenu, ce sont les lignes, que les requêtes<br/>
INSERT, UPDATE et DELETE font évoluer sans toucher à la<br/>
structure.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Changer la classe d'un élève qui a été réorienté</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : un UPDATE modifie la valeur d'un attribut dans une<br/>
ligne existante. Les attributs de la relation et leurs domaines<br/>
ne changent pas.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Ajouter un attribut email à la relation eleves</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : ajouter un attribut change le schéma relationnel<br/>
de eleves, donc la structure de la base. Toutes les lignes,<br/>
présentes et futures, sont concernées.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Inscrire un nouvel élève dans la relation eleves</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : un INSERT ajoute une ligne, c'est-à-dire un nouvel<br/>
élément du contenu. Le schéma de la relation eleves reste le<br/>
même.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Supprimer tous les élèves qui ont quitté le lycée</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : même s'il retire beaucoup de lignes d'un coup, un<br/>
DELETE ne touche que le contenu. La relation garde les mêmes<br/>
attributs.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Bases de données et SQL — Q27 : Compter après une jointure filtrée</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>On dispose des deux tables suivantes.<br/>
Table eleves :<br/>
`<code><br/>
| id | nom    | classe |<br/>
|----|--------|--------|<br/>
| 1  | Amina  | T1     |<br/>
| 2  | Basile | T2     |<br/>
| 3  | Chloé  | T1     |<br/>
| 4  | Dorian | T1     |<br/>
</code><br/>
Table notes :<br/>
<code><br/>
| id | id_eleve | valeur |<br/>
|----|----------|--------|<br/>
| 10 | 1        | 14     |<br/>
| 11 | 1        | 10     |<br/>
| 12 | 2        | 16     |<br/>
| 13 | 3        | 9      |<br/>
| 14 | 1        | 15     |<br/>
| 15 | 3        | 12     |<br/>
| 16 | 4        | 7      |<br/>
</code><br/>
Que renvoie la requête suivante ?<br/>
<code>sql<br/>
SELECT COUNT(*)<br/>
FROM notes<br/>
JOIN eleves ON notes.id_eleve = eleves.id<br/>
WHERE eleves.classe = 'T1' AND notes.valeur &gt;= 10;<br/>
</code>`</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>La requête s'évalue en trois temps : la jointure apparie chaque<br/>
note à son élève, le WHERE ne garde que les lignes qui vérifient<br/>
les deux conditions, puis COUNT(*) compte les lignes restantes.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>6</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : 6 est le nombre de notes des élèves de T1. La seconde<br/>
condition du WHERE écarte encore les notes 9, 7.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>3</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : ce serait le résultat avec notes.valeur &gt; 10. La<br/>
condition &gt;= retient aussi la note 10.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>4</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : la jointure associe chaque note à son élève.<br/>
Parmi les six notes des élèves de T1, quatre valent au moins<br/>
10 : 14, 10, 15 pour Amina, 12 pour Chloé.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>2</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : 2 est le nombre d’élèves concernés, Amina et Chloé.<br/>
La requête compte les lignes de la jointure, une par note : les<br/>
notes retenues d'un même élève comptent chacune.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Bases de données et SQL — Q30 : Trace d'une requête SELECT avec WHERE</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>On considère la table eleves suivante :<br/>
`<code><br/>
| id | nom    | classe | moyenne |<br/>
|----|--------|--------|---------|<br/>
| 1  | Alice  | 1A     | 14.5    |<br/>
| 2  | Bob    | 1B     | 9.0     |<br/>
| 3  | Chloé  | 1A     | 16.0    |<br/>
| 4  | David  | 1B     | 13.0    |<br/>
| 5  | Émma   | 1A     | 11.5    |<br/>
</code><br/>
Que renvoie la requête suivante ?<br/>
<code>sql<br/>
SELECT nom, moyenne<br/>
FROM eleves<br/>
WHERE classe = '1A' AND moyenne &gt;= 12<br/>
ORDER BY moyenne DESC;<br/>
</code>`</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Méthode systématique pour évaluer une requête<br/>
SQL : (1) appliquer le filtre WHERE pour ne<br/>
conserver que les lignes pertinentes ; (2)<br/>
projeter sur les colonnes du SELECT ; (3)<br/>
trier selon ORDER BY si présent. Cette<br/>
séquence d'étapes est l'algèbre relationnelle en<br/>
action.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Cinq lignes (toutes les lignes de la table)</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : on a oublié le filtrage par WHERE.<br/>
Sans filtre, on aurait bien toutes les<br/>
lignes, mais ici la requête restreint aux<br/>
élèves de 1A avec une moyenne d'au moins<br/>
12.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Une seule ligne : ('Chloé', 16.0)</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : Alice satisfait aussi les deux<br/>
conditions (classe 1A et moyenne d'au moins<br/>
12). Cette ligne doit donc apparaître dans le<br/>
résultat, après la première du fait du tri<br/>
décroissant.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Deux lignes : ('Chloé', 16.0) puis ('Alice', 14.5)</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse. Étape 1, le filtre<br/>
WHERE classe = '1A' AND moyenne &gt;= 12<br/>
retient les élèves de la classe 1A avec<br/>
une moyenne d'au moins 12 : Alice (14{,}5) et Chloé (16).<br/>
Émma est en 1A mais sa moyenne (11{,}5) ne satisfait pas la deuxième condition. Étape 2, on ne garde<br/>
que les colonnes nom et moyenne. Étape 3,<br/>
on trie par moyenne DESC : Chloé d'abord, puis Alice.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Trois lignes, dans l'ordre de la table : ('Alice', 14.5), ('Chloé', 16.0), ('Émma', 11.5)</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : l'ordre n'est pas celui de la table<br/>
mais celui de ORDER BY moyenne DESC, et le<br/>
filtre moyenne &gt;= 12 doit être vérifié<br/>
ligne par ligne.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Bases de données et SQL — Q31 : Trace d'une jointure</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>On dispose des deux tables suivantes :</p>
<p>Table clients :</p>
<p>`<code><br/>
| id | nom    |<br/>
|----|--------|<br/>
| 1  | Alice  |<br/>
| 2  | Bob    |<br/>
| 3  | Chloé  |<br/>
</code></p>
<p>Table commandes :</p>
<p><code><br/>
| id | client_id | produit  |<br/>
|----|-----------|----------|<br/>
| 10 | 1         | Livre    |<br/>
| 11 | 2         | Cahier   |<br/>
| 12 | 1         | Stylo    |<br/>
</code></p>
<p>Combien de lignes renvoie la requête suivante ?</p>
<p><code>sql<br/>
SELECT c.nom, cmd.produit<br/>
FROM clients c<br/>
JOIN commandes cmd ON c.id = cmd.client_id;<br/>
</code>`</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Une jointure JOIN ... ON produit une<br/>
ligne par paire qui vérifie la<br/>
condition. Un client sans commande,<br/>
comme Chloé, disparaît du résultat ;<br/>
un client à plusieurs commandes, comme<br/>
Alice, y figure plusieurs fois.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>9 lignes (chaque client apparié à chaque commande)</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : ce serait le résultat sans<br/>
condition de jointure. La condition<br/>
ON c.id = cmd.client_id ne garde que<br/>
les paires cohérentes, soit trois<br/>
lignes ici.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>4 lignes</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : seules trois commandes existent,<br/>
et chacune est associée à un seul<br/>
client. Chloé, qui n'a aucune commande,<br/>
n'apporte aucune ligne au résultat.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>2 lignes (une seule par client présent dans<br/>
les commandes)</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : Alice a <strong>deux</strong> commandes, donc<br/>
elle apparaît deux fois dans le résultat<br/>
(avec 'Livre' et avec 'Stylo'). La<br/>
jointure ne fusionne pas les commandes<br/>
d'un même client.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>3 lignes</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : la jointure interne (JOIN,<br/>
synonyme de INNER JOIN) ne garde que les<br/>
paires (client, commande) où la condition<br/>
c.id = cmd.client_id est vraie. Alice<br/>
(id 1) a deux commandes (10 et 12),<br/>
Bob (id 2) en a une, Chloé n'en a aucune<br/>
et disparaît du résultat. Total : trois<br/>
lignes. Le résultat est :<br/>
('Alice', 'Livre'), ('Bob', 'Cahier'),<br/>
('Alice', 'Stylo').</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Bases de données et SQL — Q32 : Lire un résultat de requête depuis Python</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>La table eleves(id, nom, moyenne) de la base lycee.db contient<br/>
quatre lignes : Basile (13.5), Amina (15.0), Chloé (11.0) et<br/>
Dorian (12.0). On exécute :</p>
<p>``python<br/>
import sqlite3</p>
<p>connexion = sqlite3.connect("lycee.db")<br/>
curseur = connexion.cursor()<br/>
curseur.execute("SELECT nom, moyenne FROM eleves WHERE moyenne &gt; 12 ORDER BY nom")<br/>
resultats = curseur.fetchall()<br/>
print(resultats[0])<br/>
connexion.close()<br/>
``</p>
<p>Qu'affiche ce programme ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Depuis Python, execute envoie la requête SQL au SGBD, et<br/>
fetchall récupère le résultat sous forme de liste de p-uplets,<br/>
un par ligne. On traite ensuite ces données avec les outils<br/>
habituels : indexation, boucles, tests.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Amina</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : chaque ligne du résultat est un p-uplet qui contient<br/>
toutes les colonnes demandées dans le SELECT, ici nom et<br/>
moyenne. resultats[0] est ce p-uplet entier.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>('Basile', 13.5)</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : Basile est la première ligne de la table, mais<br/>
ORDER BY nom range le résultat par ordre alphabétique. Amina<br/>
passe devant.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>('Amina', 15.0)</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : fetchall renvoie la liste des lignes du<br/>
résultat, chacune sous forme de p-uplet. Amina et Basile ont une<br/>
moyenne supérieure à 12, et Amina vient en premier dans<br/>
l'ordre alphabétique.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>[('Amina', 15.0), ('Basile', 13.5)]</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : c'est le contenu de resultats tout entier.<br/>
L'indexation resultats[0] n'en extrait que le premier<br/>
élément.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Bases de données et SQL — Q34 : Lecture d'un schéma relationnel</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>On considère le schéma relationnel suivant :</p>
<p>`<code><br/>
eleves(<em>id_eleve, nom, prenom, id_classe#)<br/>
classes(</em>id_classe, niveau, salle)<br/>
notes(<em>id_eleve#, </em>id_devoir#, note)<br/>
devoirs(*id_devoir, matiere, date)<br/>
</code></p>
<p>Le * marque les attributs qui composent la<br/>
clé primaire de chaque table (souligné dans<br/>
la notation usuelle) et le #` désigne une<br/>
clé étrangère. Quelle affirmation est<br/>
correcte ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Méthode pour lire un schéma relationnel : (1)<br/>
identifier la clé primaire de chaque table<br/>
(souvent soulignée ou notée en premier) ; (2)<br/>
repérer les clés étrangères (notées #,<br/>
soulignées en pointillés, ou en italique selon<br/>
la convention) ; (3) interpréter les<br/>
cardinalités. Ici, l'association notes est<br/>
une <strong>association plusieurs-à-plusieurs</strong><br/>
typique, qui ne peut pas se modéliser par une<br/>
simple clé étrangère ajoutée à une table<br/>
existante.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>La table eleves n'a pas de lien avec<br/>
classes</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : la colonne id_classe# dans<br/>
eleves est précisément une clé<br/>
étrangère qui pointe vers classes, ce<br/>
qui établit le lien « un élève appartient<br/>
à une classe ».</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Pour ajouter une note dans notes, il<br/>
n'est pas nécessaire que l'élève existe<br/>
dans eleves</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : la clé étrangère id_eleve# dans<br/>
notes impose que la valeur référence un<br/>
élève existant. Insérer une note pour un<br/>
élève inexistant viole l'intégrité<br/>
référentielle et le SGBD rejette<br/>
l'opération.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>La clé primaire de notes est composite,<br/>
formée de deux clés étrangères</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : la clé (id_eleve,<br/>
id_devoir) référence respectivement<br/>
eleves et devoirs. C'est la lecture<br/>
correcte du schéma. La table notes représente une<br/>
association binaire porteuse d'un attribut<br/>
(elle relie un élève et un devoir, et<br/>
porte la note). La clé primaire composite<br/>
garantit l'unicité (un élève ne peut avoir<br/>
qu'une note par devoir), et les clés<br/>
étrangères assurent l'intégrité<br/>
référentielle (on ne peut pas mettre une<br/>
note pour un élève ou un devoir<br/>
inexistants).</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>On peut avoir plusieurs élèves avec le<br/>
même id_eleve</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : id_eleve est la clé primaire de<br/>
la table eleves, donc unique par<br/>
définition. Deux élèves différents ne<br/>
peuvent pas partager la même valeur de<br/>
id_eleve.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Bases de données et SQL — Q35 : Injection SQL</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Un programme construit la requête SQL suivante<br/>
en concaténant directement la chaîne<br/>
nom_saisi reçue de l'utilisateur :</p>
<p>`<code>python<br/>
requete = "SELECT * FROM users WHERE nom = '" + nom_saisi + "';"<br/>
</code></p>
<p>Si l'utilisateur saisit<br/>
' OR '1'='1`, que se passe-t-il ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>L'injection SQL reste, en 2026, l'une des<br/>
vulnérabilités les plus exploitées dans les<br/>
applications web. La parade est connue depuis<br/>
longtemps : ne <strong>jamais</strong> construire une<br/>
requête SQL par concaténation de chaînes<br/>
utilisateur, mais utiliser systématiquement<br/>
des <strong>requêtes préparées</strong> où les paramètres<br/>
sont passés séparément<br/>
(cursor.execute("... WHERE nom = ?", (nom_saisi,))).<br/>
Le SGBD échappe alors automatiquement les<br/>
caractères dangereux.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>La requête ne retourne aucune ligne</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : c'est l'inverse. La condition<br/>
'1'='1' étant toujours vraie, <strong>toutes</strong><br/>
les lignes de la table sont retournées,<br/>
y compris des données potentiellement<br/>
sensibles que l'utilisateur ne devrait<br/>
pas voir.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Toutes les lignes de la table sont<br/>
renvoyées : c'est une injection SQL</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : la requête devient<br/>
SELECT * FROM users WHERE nom = '' OR '1'='1';.<br/>
La concaténation naïve fait<br/>
sortir la chaîne saisie de son rôle de<br/>
simple donnée et l'injecte dans la<br/>
structure SQL. La condition '1'='1'<br/>
étant toujours vraie, l'opérateur OR la<br/>
fait court-circuiter le filtre. C'est la<br/>
forme la plus simple d'injection SQL,<br/>
célèbre attaque qui a touché de nombreux<br/>
sites mal protégés. La parade standard :<br/>
utiliser des <strong>requêtes préparées</strong> avec<br/>
des paramètres liés<br/>
(cursor.execute(req, (nom_saisi,))).</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Le SGBD détecte l'injection et rejette la<br/>
requête</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : la requête est syntaxiquement<br/>
parfaitement valide. Le SGBD n'a aucun<br/>
moyen de détecter qu'elle vient d'une<br/>
concaténation dangereuse plutôt que d'une<br/>
intention légitime. C'est précisément ce<br/>
qui rend l'injection SQL si pernicieuse.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Python lève une exception au moment de la<br/>
concaténation</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : Python concatène sans aucun<br/>
problème les chaînes, quel que soit leur<br/>
contenu. Aucune exception n'est levée.<br/>
C'est précisément le drame : tout se passe<br/>
silencieusement.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Bases de données et SQL — Q36 : Trace d'un UPDATE ciblé</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>On part de la table comptes suivante :<br/>
`<code><br/>
| id | titulaire | solde |<br/>
|----|-----------|-------|<br/>
| 1  | Alice     | 1000  |<br/>
| 2  | Bob       | 500   |<br/>
| 3  | Chloé     | 2000  |<br/>
</code><br/>
On exécute la requête suivante :<br/>
<code>sql<br/>
UPDATE comptes<br/>
SET solde = solde * 1.05<br/>
WHERE solde &gt;= 1000;<br/>
</code>`<br/>
Quel est le contenu de la table après<br/>
exécution ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Schéma général d'un UPDATE : (1) la clause<br/>
WHERE sélectionne les lignes affectées ; (2)<br/>
la clause SET indique comment modifier ces<br/>
lignes ; (3) le SGBD applique la modification<br/>
atomiquement (toutes les lignes en une seule<br/>
opération). Sans WHERE, <strong>toutes</strong> les lignes<br/>
sont modifiées, ce qui est rarement souhaité<br/>
et souvent catastrophique.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Bob est supprimé de la table</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : UPDATE ne supprime jamais de<br/>
ligne, il ne fait que modifier des<br/>
valeurs. Pour supprimer une ligne, il<br/>
faudrait utiliser DELETE FROM comptes<br/>
WHERE solde &lt; 1000;.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Toutes les lignes voient leur solde<br/>
multiplié par 1{,}05</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : c'est ce qui se passerait si la<br/>
clause WHERE était absente. Avec<br/>
WHERE solde &gt;= 1000, seules les lignes<br/>
satisfaisant la condition sont<br/>
modifiées. Bob (500) ne fait pas partie<br/>
du lot.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Alice : 1050, Bob : 500 (inchangé), Chloé : 2100</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : la clause WHERE solde &gt;= 1000<br/>
sélectionne les lignes où le solde est<br/>
d'au moins 1000 (Alice et Chloé). Pour<br/>
chacune, on applique solde = solde * 1.05.<br/>
Alice passe de 1000 à 1050, Chloé de 2000 à 2100. Bob, dont le solde est inférieur à 1000, n'est pas affecté.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>La table reste inchangée car la clause<br/>
WHERE est trop restrictive</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : Alice (1000) et Chloé (2000)<br/>
satisfait bien la condition solde &gt;= 1000,<br/>
donc la ligne est modifiée. La<br/>
condition n'est pas trop restrictive : elle<br/>
est ciblée.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Bases de données et SQL — Q37 : Rôle de la clause ON</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Dans la requête<br/>
SELECT * FROM livres JOIN auteurs ON livres.id_auteur = auteurs.id,<br/>
à quoi sert la clause ON ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Une jointure combine deux tables ligne à ligne. La<br/>
clause ON donne la règle d'appariement, presque<br/>
toujours l'égalité entre la clé étrangère d'une<br/>
table et la clé primaire de l'autre. Sans elle, le<br/>
SGBD ne saurait pas quelle ligne d'auteurs<br/>
accompagne chaque livre.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>À renommer la table auteurs en livres le temps de la requête</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Renommer une table se fait avec AS ; ON<br/>
compare des colonnes, il ne renomme rien.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>À trier les lignes du résultat selon les valeurs de la colonne auteurs.id</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Le tri s'obtient avec ORDER BY ; ON ne<br/>
change pas l'ordre des lignes.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>À choisir les colonnes des deux tables qui apparaissent dans le résultat</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Ce choix revient à SELECT ; ici l'étoile<br/>
affiche toutes les colonnes des deux tables.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>À indiquer la condition qui apparie une ligne de livres à une ligne d'auteurs</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Chaque livre est associé à l'auteur dont<br/>
l'identifiant est égal à sa clé étrangère<br/>
id_auteur.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Bases de données et SQL — Q38 : Écrire une jointure villes et pays</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>La base contient villes(id, nom, id_pays) et<br/>
pays(id, nom), où id_pays est une clé étrangère<br/>
vers pays. Quelle requête affiche le nom de chaque<br/>
ville suivi du nom de son pays ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Pour relier deux tables, on cherche la clé étrangère<br/>
de l'une et la clé primaire de l'autre :<br/>
villes.id_pays désigne pays.id. La condition de<br/>
jointure compare exactement ces deux colonnes.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>SELECT villes.nom, pays.nom FROM villes JOIN pays ON villes.nom = pays.nom</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Comparer le nom d'une ville au nom d'un pays<br/>
n'apparie rien, sauf homonymie accidentelle.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>SELECT villes.nom, pays.nom FROM villes JOIN pays ON villes.id_pays = pays.id</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>La clé étrangère id_pays est comparée à la clé<br/>
primaire id de la table pays.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>SELECT villes.nom, pays.nom FROM villes JOIN pays ON villes.id = pays.id</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Cette condition apparie une ville et un pays qui<br/>
ont par hasard le même numéro d'identifiant, ce<br/>
qui n'a aucun sens.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>SELECT villes.nom, pays.nom FROM villes WHERE villes.id_pays = pays.id</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>La table pays n'est pas dans la clause FROM :<br/>
le SGBD signale une colonne inconnue.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Bases de données et SQL — Q39 : Un auteur absent du résultat</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Table auteurs :</p>
<p>`<code><br/>
| id | nom     |<br/>
|----|---------|<br/>
| 1  | Colette |<br/>
| 2  | Camus   |<br/>
| 3  | Duras   |<br/>
</code></p>
<p>Table livres :</p>
<p><code><br/>
| id | titre      | id_auteur |<br/>
|----|------------|-----------|<br/>
| 10 | Chéri      | 1         |<br/>
| 11 | La Peste   | 2         |<br/>
| 12 | Sido       | 1         |<br/>
| 13 | L'Étranger | 2         |<br/>
| 14 | Gigi       | 1         |<br/>
</code></p>
<p>On exécute :</p>
<p><code>sql<br/>
SELECT auteurs.nom, livres.titre<br/>
FROM auteurs JOIN livres ON auteurs.id = livres.id_auteur;<br/>
</code>`</p>
<p>Pourquoi le nom « Duras » n'apparaît-il pas dans le<br/>
résultat ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Le résultat compte cinq lignes, une par livre,<br/>
chacune avec le nom de son auteur. Un auteur sans<br/>
livre ne forme aucune paire et disparaît : c'est le<br/>
comportement de la jointure interne, la seule au<br/>
programme.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Parce qu'aucun livre n'a id_auteur égal à 3 : la jointure ne garde que les paires appariées</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Une jointure produit une ligne par couple<br/>
(auteur, livre) vérifiant la condition ; Duras<br/>
n'entre dans aucun couple.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Parce que la table auteurs est citée en premier dans FROM, ce qui l'exclut du résultat</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>L'ordre des tables dans la jointure ne retire<br/>
aucune ligne ; Colette et Camus, de la même<br/>
table, apparaissent bien.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Parce que la requête contient une erreur et ne renvoie que des lignes partielles</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>La requête est correcte et renvoie cinq lignes<br/>
complètes, une par livre.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Parce que le SGBD n'affiche que les deux premiers auteurs de la table</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Rien ne limite le nombre d'auteurs ; Colette et<br/>
Camus figurent parce qu'ils ont des livres, pas<br/>
parce qu'ils sont en tête.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Bases de données et SQL — Q40 : Noms courts dans une jointure</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Que désignent e et c dans la requête suivante ?</p>
<p>`<code>sql<br/>
SELECT e.nom, c.libelle<br/>
FROM eleves AS e<br/>
JOIN clubs AS c ON e.id_club = c.id;<br/>
</code>`</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>eleves AS e déclare un alias. Partout ailleurs<br/>
dans la requête, e.nom signifie eleves.nom. Le<br/>
mot AS est facultatif : FROM eleves e a le même<br/>
effet.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Deux colonnes de la table eleves, qui contiennent respectivement le nom et le libellé</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>nom et libelle sont les colonnes ; e et c<br/>
précèdent le point et désignent des tables.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>L'ordre de tri du résultat : d'abord selon les élèves (e), puis selon les clubs (c)</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Aucun ORDER BY n'est présent ; e et c ne<br/>
disent rien de l'ordre des lignes.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Des alias : des noms courts donnés aux tables eleves et clubs le temps de la requête</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Ils allègent l'écriture des colonnes et lèvent<br/>
toute ambiguïté quand deux tables ont une colonne<br/>
de même nom.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Deux nouvelles tables, créées dans la base au moment où la requête est exécutée</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>AS n'écrit rien dans la base ; les noms courts<br/>
disparaissent dès la fin de la requête.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Bases de données et SQL — Q41 : Jointure puis filtre</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Avec livres(id, titre, annee, id_auteur) et<br/>
auteurs(id, nom), quelle requête renvoie les<br/>
titres des livres écrits par Colette ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Deux étapes : relier chaque livre à son auteur par<br/>
la clé étrangère, puis filtrer sur le nom. Le filtre<br/>
va dans WHERE, la règle d'appariement dans ON.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>SELECT livres.titre FROM livres JOIN auteurs ON livres.id_auteur = auteurs.id WHERE livres.id_auteur = 'Colette'</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>La jointure est bonne, mais id_auteur contient un<br/>
numéro, jamais un nom : le filtre ne garde aucune<br/>
ligne.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>SELECT livres.titre FROM livres JOIN auteurs ON livres.id = auteurs.id WHERE auteurs.nom = 'Colette'</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>La condition de jointure compare deux clés<br/>
primaires sans rapport : aucun livre n'est relié<br/>
à son auteur, et le résultat est faux sans<br/>
message d'erreur.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>SELECT livres.titre FROM livres JOIN auteurs ON auteurs.nom = 'Colette'</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>La condition de jointure ne relie pas les deux<br/>
tables : chaque livre est apparié à Colette,<br/>
qu'il soit d'elle ou non, et tous les titres<br/>
sortent.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>SELECT livres.titre FROM livres JOIN auteurs ON livres.id_auteur = auteurs.id WHERE auteurs.nom = 'Colette'</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>La jointure attache l'auteur à chaque livre, puis<br/>
WHERE ne garde que les lignes dont l'auteur<br/>
s'appelle Colette.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Bases de données et SQL — Q42 : Première ligne d'une jointure triée</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Table equipes :</p>
<p>`<code><br/>
| id | nom     |<br/>
|----|---------|<br/>
| 1  | Lions   |<br/>
| 2  | Aigles  |<br/>
| 3  | Requins |<br/>
</code></p>
<p>Table joueurs :</p>
<p><code><br/>
| id | nom  | id_equipe | buts |<br/>
|----|------|-----------|------|<br/>
| 1  | Sami | 2         | 4    |<br/>
| 2  | Lou  | 1         | 7    |<br/>
| 3  | Inès | 3         | 2    |<br/>
| 4  | Teo  | 2         | 9    |<br/>
| 5  | Maya | 1         | 5    |<br/>
</code></p>
<p><code>sql<br/>
SELECT joueurs.nom, equipes.nom<br/>
FROM joueurs JOIN equipes ON joueurs.id_equipe = equipes.id<br/>
ORDER BY joueurs.buts DESC;<br/>
</code>`</p>
<p>Quelle est la première ligne du résultat ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>La jointure remplace chaque id_equipe par le nom<br/>
de l'équipe correspondante ; le tri décroissant sur<br/>
buts place Teo (9) devant Lou (7), Maya (5),<br/>
Sami (4) et Inès (2).</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Teo | Aigles</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Teo a le plus de buts (9) et son équipe,<br/>
d'identifiant 2, est Aigles.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Lou | Lions</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Lou vient en deuxième position avec 7 buts.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Teo | Lions</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Teo joue dans l'équipe 2, Aigles ; Lions porte<br/>
l'identifiant 1.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Inès | Requins</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Inès, avec 2 buts, termine dernière du<br/>
classement décroissant.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Bases de données et SQL — Q43 : Jointure sur trois tables</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Schéma : eleves(id, nom), activites(id, libelle)<br/>
et inscriptions(id_eleve, id_activite). Quelle<br/>
requête affiche le nom de chaque élève avec le<br/>
libellé de chaque activité où il est inscrit ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>inscriptions est une table de liaison : elle ne<br/>
contient que des clés étrangères. Il faut deux<br/>
jointures en chaîne, chacune reliant une clé<br/>
étrangère à la clé primaire visée.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>`<code>sql<br/>
SELECT eleves.nom, activites.libelle<br/>
FROM eleves<br/>
JOIN inscriptions ON eleves.id = inscriptions.id_eleve<br/>
JOIN activites ON inscriptions.id_activite = activites.id;<br/>
</code>`</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Deux jointures en chaîne : l'élève est relié à<br/>
ses inscriptions, chaque inscription à son<br/>
activité.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>`<code>sql<br/>
SELECT eleves.nom, activites.libelle<br/>
FROM eleves<br/>
JOIN inscriptions ON eleves.id = inscriptions.id_activite<br/>
JOIN activites ON inscriptions.id_eleve = activites.id;<br/>
</code>`</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Les clés sont croisées : un élève est apparié<br/>
aux inscriptions dont le numéro d'activité vaut<br/>
son propre numéro. Le résultat est faux sans<br/>
aucun message d'erreur.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>`<code>sql<br/>
SELECT eleves.nom, activites.libelle<br/>
FROM eleves<br/>
JOIN activites ON eleves.id = activites.id;<br/>
</code>`</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>La table inscriptions est oubliée : on apparie<br/>
un élève à l'activité qui porte le même numéro,<br/>
sans rapport avec ses inscriptions.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>`<code>sql<br/>
SELECT eleves.nom, activites.libelle<br/>
FROM eleves, inscriptions, activites;<br/>
</code>`</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Sans condition d'appariement, chaque élève est<br/>
associé à chaque inscription et à chaque<br/>
activité : le résultat contient toutes les<br/>
combinaisons.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Bases de données et SQL — Q44 : Quand une jointure est nécessaire</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Base : livres(id, titre, annee, id_auteur) et<br/>
auteurs(id, nom, pays). Quelle demande exige une<br/>
jointure ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Une jointure sert quand les informations demandées,<br/>
ou les critères de filtrage, sont répartis sur<br/>
plusieurs tables. Si tout se trouve dans une seule<br/>
table, un SELECT simple suffit.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Les noms des auteurs dont le pays est la France</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>La table auteurs contient le nom et le pays :<br/>
aucune autre table n'est nécessaire.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Les titres des livres parus après l'année 2000</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Titre et année sont dans la seule table<br/>
livres : un WHERE annee &gt; 2000 suffit.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Le nombre de livres parus pendant l'année 1947</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>COUNT(*) sur livres avec WHERE annee = 1947<br/>
répond sans toucher à auteurs.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Les titres des livres d'un auteur irlandais</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Le titre est dans livres et le pays dans<br/>
auteurs : il faut relier les deux par<br/>
id_auteur.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Bases de données et SQL — Q45 : Persistance des données</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>On dit qu'un SGBD assure la <strong>persistance</strong> des données. Que<br/>
signifie cette propriété ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>La persistance est l'un des services fondamentaux d'un SGBD : ce<br/>
qui a été validé est conservé durablement, quels que soient les<br/>
arrêts ou les pannes de courant ultérieurs.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Les données ne peuvent plus être modifiées une fois insérées dans la base</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : une base vit, on y insère, modifie et supprime des<br/>
lignes. La persistance garantit que l'état courant survit aux<br/>
arrêts, pas qu'il est figé.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Les données sont gardées en mémoire vive pour être lues plus rapidement</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : la mémoire vive s'efface à l'extinction. La persistance<br/>
repose justement sur l'écriture sur un support durable, le cache<br/>
en mémoire n'étant qu'une accélération.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Les données sont recopiées automatiquement sur un second site distant</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : la réplication est une mesure de sécurité<br/>
supplémentaire, pas la définition de la persistance, qui<br/>
concerne d'abord la conservation locale sur disque.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Les données survivent à l'arrêt du programme et de la machine</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : les données sont écrites sur un support durable<br/>
et retrouvées intactes au redémarrage, contrairement aux<br/>
variables d'un programme, qui disparaissent avec lui.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Bases de données et SQL — Q46 : Droits d'accès à une table</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Dans la base d'un lycée, le compte utilisé par l'application<br/>
d'affichage des emplois du temps doit pouvoir lire la table cours<br/>
mais jamais la modifier. Quel mécanisme du SGBD répond à ce<br/>
besoin ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>La sécurisation des accès est un service du SGBD : chaque compte<br/>
reçoit des droits précis, lecture seule pour une application<br/>
d'affichage, écriture pour la gestion, administration pour<br/>
quelques personnes.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Une contrainte d'intégrité qui rejette toute requête UPDATE sur la table</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : les contraintes d'intégrité portent sur la validité des<br/>
données, pas sur l'identité de celui qui les modifie. C'est la<br/>
gestion des droits qui distingue les comptes.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Le chiffrement de la table cours, illisible sans la clé de déchiffrement</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : chiffrer la table empêcherait aussi la lecture, qui est<br/>
précisément ce que l'application doit pouvoir faire. Le besoin<br/>
porte sur les opérations autorisées, pas sur la confidentialité.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>La clé primaire de la table cours, qui interdit toute modification des lignes</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : une clé primaire garantit l'unicité des lignes, elle ne<br/>
limite en rien les opérations permises à un compte.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Des droits d'accès limités à SELECT pour ce compte</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : le SGBD associe à chaque compte des droits par<br/>
table et par opération. Une requête de modification émise par<br/>
ce compte est refusée avant même d'être exécutée.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Bases de données et SQL — Q47 : Deux réservations simultanées</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Deux clients tentent au même instant de réserver la dernière place<br/>
d'un spectacle. Comment le SGBD évite-t-il de vendre deux fois la<br/>
même place ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Sans gestion des accès concurrents, deux lectures simultanées de<br/>
« place libre » conduiraient à deux ventes. Le SGBD sérialise les<br/>
opérations conflictuelles pour que la base reste cohérente.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Il accepte les deux réservations et signale le conflit à l'administrateur du site</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : accepter les deux, c'est précisément l'incohérence à<br/>
éviter. Le SGBD l'empêche avant qu'elle ne soit écrite, il ne se<br/>
contente pas de la signaler.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Il refuse toute réservation tant que plusieurs clients sont connectés en même temps</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : bloquer tout le monde rendrait le service inutilisable.<br/>
Le SGBD n'arbitre que les opérations qui touchent les mêmes<br/>
données.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Il attribue la place au client dont la connexion au serveur est la plus rapide</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : la vitesse de connexion n'intervient pas. Le SGBD<br/>
garantit seulement qu'une des deux opérations est entièrement<br/>
traitée avant que l'autre ne lise l'état de la place.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Il les traite l'une après l'autre, et la seconde trouve la place déjà prise</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : la gestion des accès concurrents ordonne les<br/>
opérations comme si elles avaient été faites l'une après<br/>
l'autre. Le second client reçoit un refus cohérent.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Bases de données et SQL — Q48 : Parade à l'injection SQL</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Un programme construit ses requêtes à partir de valeurs saisies<br/>
par l'utilisateur. Quelle pratique le protège contre l'injection<br/>
SQL ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>L'injection SQL vient de la concaténation de texte saisi dans une<br/>
requête. La parade consiste à ne jamais mélanger les deux : la<br/>
requête est écrite avec des emplacements, et les valeurs sont<br/>
fournies à part.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Des requêtes paramétrées, les valeurs étant transmises à part</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : avec une requête paramétrée, la structure de la<br/>
requête est fixée avant que les valeurs n'y soient insérées.<br/>
Une saisie contenant ' OR 1=1 reste une simple chaîne de<br/>
caractères comparée telle quelle.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Le masquage des messages d'erreur renvoyés par le SGBD à l'utilisateur</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : cacher les erreurs complique le travail de l'attaquant<br/>
mais n'empêche pas l'injection. Une requête détournée s'exécute<br/>
toujours, en silence.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>La limitation de la longueur des champs du formulaire à vingt caractères</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : ' OR 1=1 -- tient en moins de vingt caractères. La<br/>
limitation gêne à peine l'attaque et ne traite pas sa cause, le<br/>
mélange entre code SQL et données.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Le chiffrement de l'ensemble du contenu de la base de données</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : le chiffrement protège les données volées ou lues sur<br/>
le disque. Une requête injectée est exécutée par le SGBD<br/>
lui-même, qui déchiffre normalement ce qu'il renvoie.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Bases de données et SQL — Q49 : Les sauvegardes d'une base de données</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Pourquoi un système de gestion de bases de données sauvegarde-t-il<br/>
régulièrement les données qu'il héberge ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Parmi les services d'un SGBD figure la sécurité des données au<br/>
sens de leur conservation : la sauvegarde en est l'outil.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Pour accélérer les requêtes les plus fréquentes du site</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : la vitesse relève des index et de la mémoire cache, pas<br/>
des sauvegardes.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Pour restaurer les données après une panne ou une erreur</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : un disque qui lâche, une requête de suppression<br/>
malheureuse ou un piratage détruisent des données ; seule une<br/>
copie récente permet de les retrouver.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Pour supprimer automatiquement les lignes en double</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : les doublons se traitent par les contraintes<br/>
d'intégrité.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Pour remplacer la gestion des droits d'accès des utilisateurs</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : sauvegarde et droits d'accès sont deux garanties<br/>
distinctes.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Bases de données et SQL — Q50 : Le compte utilisé par une application de consultation</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Un site affiche les horaires d'une bibliothèque depuis une base de<br/>
données, sans jamais les modifier. Avec quel compte doit-il se<br/>
connecter à la base ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Les droits d'accès s'attribuent selon le besoin réel : lire quand<br/>
il suffit de lire.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Aucun compte, les horaires étant des données publiques de toute façon</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : le SGBD exige une identification pour tout accès, même<br/>
en lecture.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Un compte limité à la lecture, pour qu'une faille ne modifie rien</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : donner le moins de droits possible limite les<br/>
dégâts d'une attaque ; un compte en lecture seule ne peut ni<br/>
effacer ni altérer les horaires.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Un compte distinct pour chaque visiteur, créé à la volée</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : les visiteurs ne se connectent pas à la base, c'est le<br/>
site qui le fait.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Le compte administrateur, pour n'essuyer aucun refus d'accès</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : une injection réussie disposerait alors de tous les<br/>
droits, suppression comprise.</p>]]></text>
    </feedback>
  </answer>
</question>

</quiz>
