Exercice (5 points) — dans l'esprit des sessions 2015–2025, section Sciences de l'informatique
La base VéloCité du service municipal de vélos en libre-service de Sfax a la représentation textuelle suivante (clés primaires soulignées, clés étrangères suivies de #) :
- Station ( idStation , nomStation , quartier , capacite )
- Modele ( codeModele , libModele , typeModele , tarifMinute )
- Velo ( idVelo , dateService , codeModele# , idStation# )
- Formule ( codeFormule , libFormule , prixMensuel )
- Abonne ( numAbonne , nomAbonne , telAbonne , emailAbonne , codeFormule# )
- Trajet ( idTrajet , dateTrajet , dureeMin , montant , idVelo# , numAbonne# )
- Reparation ( idVelo# , dateRep , panne , cout )
| Champ | Description |
|---|---|
| idStation | Identifiant d'une station, entier. |
| nomStation | Nom d'une station, chaîne de 20 caractères. |
| quartier | Quartier où se trouve une station, chaîne de 30 caractères. |
| capacite | Nombre maximal de vélos d'une station, entier. |
| codeModele | Code d'un modèle de vélo, chaîne de 4 caractères. |
| libModele | Libellé d'un modèle, chaîne de 30 caractères. |
| typeModele | Type d'un modèle, « Classique » ou « Electrique », chaîne de 10 caractères. |
| tarifMinute | Prix d'une minute de trajet, en dinars, réel. |
| idVelo | Identifiant d'un vélo, entier. |
| dateService | Date de mise en service d'un vélo. |
| codeFormule | Code d'une formule d'abonnement, chaîne de 3 caractères. |
| libFormule | Libellé d'une formule (Journalier, Mensuel, Annuel…), chaîne de 20 caractères. |
| prixMensuel | Prix mensuel d'une formule, en dinars, réel. |
| numAbonne | Numéro d'un abonné, entier. |
| nomAbonne | Nom et prénom d'un abonné, chaîne de 40 caractères. |
| telAbonne | Téléphone d'un abonné, chaîne de 8 caractères. |
| emailAbonne | Adresse mail d'un abonné, chaîne de 50 caractères. |
| idTrajet | Identifiant d'un trajet, entier. |
| dateTrajet | Date d'un trajet (sans heure). |
| dureeMin | Durée d'un trajet, en minutes, entier. |
| montant | Montant payé pour un trajet, en dinars, réel. |
| dateRep | Date d'une réparation. |
| panne | Description de la panne réparée, chaîne de 50 caractères. |
| cout | Coût d'une réparation, en dinars, réel. |
Les clés étrangères ont été déclarées sans l'option ON DELETE CASCADE. Seuls les champs emailAbonne, dureeMin et montant peuvent rester vides ; tous les autres sont obligatoires. On donne l'extrait suivant de la table Formule :
| codeFormule | libFormule | prixMensuel |
|---|---|---|
| F1 | Journalier | 3.000 |
| F2 | Mensuel | 15.000 |
| F3 | Annuel | 150.000 |
Écrire les requêtes SQL permettant de répondre aux situations suivantes :
- Le 12 avril 2026, la municipalité inaugure la station d'identifiant 14, nommée « Port de pêche », située dans le quartier « Sidi Mansour », d'une capacité de 20 vélos. Le même jour, elle reçoit un nouveau modèle de code « M7 », de libellé « VéloCargo », de type « Electrique », au tarif de 0,120 dinar la minute ; le vélo d'identifiant 305, de ce modèle, est mis en service et stationné dans la nouvelle station. Écrire, dans un ordre d'exécution correct, les requêtes permettant d'enregistrer ces informations.
- Le 13 avril 2026, l'abonné numéro 1024, déjà enregistré, emprunte le vélo 305 ; le trajet reçoit l'identifiant 90871. Le vélo n'étant pas encore restitué, la durée et le montant du trajet ne sont pas connus. Écrire la requête permettant d'enregistrer ce trajet.
- Une erreur du système de paiement a surfacturé les trajets effectués en mars 2026 avec un vélo de type « Electrique ». On se propose de réduire de 15 % le montant de ces trajets.
- Pour renouveler le parc, on se propose de supprimer de la base toutes les données relatives aux vélos mis en service avant le 1er janvier 2019. Écrire l'ensemble des requêtes correspondantes.
- Pour chacune des requêtes a), b), c) et d) ci-dessous, dire si elle sera exécutée ou refusée par le SGBD ; en cas de refus, préciser la contrainte non respectée.
-- a)
INSERT INTO Formule
VALUES ('F2', 'Etudiant', 12.000);
-- b)
INSERT INTO Abonne
VALUES (2051, 'Sami Ben Salah', '98123456',
'sami.bs@mail.tn', 'F9');
-- c)
INSERT INTO Station
VALUES (15, 'Cité El Habib Entrée Nord',
'El Habib', 25);
-- d)
INSERT INTO Abonne (numAbonne, nomAbonne,
telAbonne, codeFormule)
VALUES (2052, 'Rim Trabelsi', '55001122', 'F3');Voir la correction commentéeAprès avoir posé votre démarche
1. Idée : Velo référence Station (idStation#) et Modele (codeModele#) : ces deux lignes mères doivent exister avant l'insertion du vélo ; leur ordre entre elles est libre.
INSERT INTO Station
VALUES (14, 'Port de pêche', 'Sidi Mansour', 20);
INSERT INTO Modele
VALUES ('M7', 'VéloCargo', 'Electrique', 0.120);
INSERT INTO Velo
VALUES (305, '2026-04-12', 'M7', 14);Exécutée en premier, l'insertion du vélo serait refusée : la station 14 et le modèle M7 n'existent pas encore (intégrité référentielle).
2. Idée : deux valeurs manquent : on nomme les colonnes renseignées, les autres (dureeMin, montant) prennent la valeur NULL, ce que la description autorise.
INSERT INTO Trajet (idTrajet, dateTrajet,
idVelo, numAbonne)
VALUES (90871, '2026-04-13', 305, 1024);Équivalent : INSERT INTO Trajet VALUES (90871, '2026-04-13', NULL, NULL, 305, 1024);. Sans liste de colonnes et avec quatre valeurs seulement, la requête serait refusée : la table a six colonnes.
3. Idée : le critère « type Electrique » est dans Modele, pas dans Trajet : une sous-requête sélectionne les vélos concernés, YEAR et MONTH fixent la période ; réduire de 15 % revient à multiplier par 0,85.
UPDATE Trajet
SET montant = montant * 0.85
WHERE YEAR(dateTrajet) = 2026
AND MONTH(dateTrajet) = 3
AND idVelo IN (
SELECT idVelo FROM Velo V, Modele M
WHERE V.codeModele = M.codeModele
AND typeModele = 'Electrique');Par exemple, un trajet de mars 2026 facturé 4,800 D sur un vélo électrique passe à ; un trajet de mars sur un vélo classique, ou d'avril sur un vélo électrique, ne change pas.
4. Idée : sans ON DELETE CASCADE, supprimer un vélo encore référencé est refusé : on supprime d'abord les lignes filles (Reparation et Trajet, dans un ordre quelconque), puis les vélos.
DELETE FROM Reparation
WHERE idVelo IN (SELECT idVelo FROM Velo
WHERE dateService < '2019-01-01');
DELETE FROM Trajet
WHERE idVelo IN (SELECT idVelo FROM Velo
WHERE dateService < '2019-01-01');
DELETE FROM Velo
WHERE dateService < '2019-01-01';5. Idée : pour chaque insertion, vérifier la clé primaire (valeur déjà présente ?), les clés étrangères (la ligne mère existe-t-elle ?), la taille et le caractère obligatoire des valeurs.
- a) Refusée : le code « F2 » existe déjà dans Formule (formule Mensuel) ; la contrainte de clé primaire interdit un doublon.
- b) Refusée : aucune formule « F9 » n'existe ; la clé étrangère codeFormule viole l'intégrité référentielle.
- c) Refusée : « Cité El Habib Entrée Nord » compte 25 caractères alors que nomStation en admet 20 au maximum (valeur trop longue pour le domaine du champ ; refus en mode strict, mode par défaut de MySQL).
- d) Exécutée : la liste de colonnes omet emailAbonne, qui peut rester vide et prend la valeur NULL ; la formule F3 existe.