Quiz blanc
Conditions réelles : 20 questions à travers les 6 chapitres. Calque le format du partiel.
Réponds à toutes les questions sans regarder le cours. À la fin, refais les chapitres concernés par tes erreurs. Le score t'indique ton niveau de prêt.
✎ Examen blanc · TAD complet
CREATE USER … IDENTIFIED BY … ?CREATE SESSION. Il faut au minimum lui donner CONNECT.statut avec 4 valeurs distinctes pour 2 millions de lignes, peu d'inserts. Quel index ?CREATE INDEX ON CLUSTER, aucune opération possible sur les tables clustérisées.:new et :old, il doit :RAISE_APPLICATION_ERROR ?INSTEAD OF s'applique :p_nom IN VARCHAR2(50) est :SELECT … INTO qui ne renvoie aucune ligne :★ Barème estimé
| Score | Niveau | À faire |
|---|---|---|
| 18-20 / 20 | Excellent | Tu peux passer le partiel sereinement. Polis les exos pratiques. |
| 14-17 / 20 | Solide | Refais les chapitres concernés par tes erreurs. Travaille les annales. |
| 10-13 / 20 | À renforcer | Reprends les flashcards et les Q/R des chapitres faibles. |
| < 10 / 20 | À travailler | Relire les CMs en profondeur. Commence par CM5/CM6 (PL/SQL pèse le plus). |
📝 Questions de réflexion
Format partiel : réponses courtes (1-2 phrases). Réfléchis avant de déplier.
Pourquoi passer par des rôles plutôt que par des droits directs ?
Pour la maintenance (un nouvel utilisateur = un GRANT du rôle), la cohérence (un seul endroit définit les permissions d'un profil), et la réversibilité (désactiver le rôle sans toucher aux autres droits).
Différence entre REFRESH ON COMMIT et REFRESH ON DEMAND pour une VM ?
ON COMMIT rafraîchit à chaque validation sur les tables sources : VM toujours à jour, mais coût à chaque commit. ON DEMAND rafraîchit à la demande (dbms_mview.refresh) : VM potentiellement désynchronisée mais coût d'écriture nul.
Pourquoi un index bitmap ne convient pas à une table OLTP ?
Parce que chaque mise à jour d'une ligne reconstruit l'index entièrement. Sur une table avec des milliers d'inserts/updates par seconde (OLTP), c'est un suicide en performance. Le bitmap est conçu pour des tables à faible activité de MAJ (data warehouse, reporting).
Justifier une fragmentation H ou V sur un cas multi-sites.
Si 80% des requêtes locales filtrent sur la même valeur d'attribut (ville, classe), fragmentation H sur cet attribut → trafic réseau minimisé.
Si certaines colonnes sont rarement consultées ensemble (paie vs administratif), fragmentation V avec la clé dans chaque fragment → réduction de la taille des accès locaux et confidentialité.
Pourquoi un cluster est-il utile pour une relation Maître/Détails ?
Parce qu'il colocalise physiquement les lignes maître et détails partageant la même clé sur le disque. Les jointures fréquentes deviennent des lectures séquentielles au lieu d'allers-retours aléatoires. Gain de performance significatif quand on requête souvent ces jointures.
🧪 Problème pratique type partiel
Soit le MLD simplifié d'un producteur de vin :
Vin(id_vin, nom, annee, qtetot)
Commande(id_cmde, #id_client, date_cmde, total)
LigneCommande(id_lc, #id_cmde, #id_vin, qte, prix_unitaire)
Client(id_client, nom, ca_cumule)
Q1 — Écris un trigger BEFORE INSERT sur LigneCommande qui auto-incrémente id_lc à partir d'une séquence seq_lc.
CREATE OR REPLACE TRIGGER trig_id_lc
BEFORE INSERT ON LigneCommande
FOR EACH ROW
BEGIN
:new.id_lc := seq_lc.NEXTVAL;
END;
Q2 — Écris un trigger AFTER INSERT qui décrémente Vin.qtetot à chaque ligne de commande insérée.
CREATE OR REPLACE TRIGGER trig_maj_qte_vin
AFTER INSERT ON LigneCommande
FOR EACH ROW
BEGIN
UPDATE Vin
SET qtetot = qtetot - :new.qte
WHERE id_vin = :new.id_vin;
END;
Q3 — Écris un trigger garde-fou : refuse une commande si qte > Vin.qtetot.
CREATE OR REPLACE TRIGGER trig_check_stock_vin
BEFORE INSERT ON LigneCommande
FOR EACH ROW
DECLARE
v_stock Vin.qtetot%TYPE;
BEGIN
SELECT qtetot INTO v_stock
FROM Vin WHERE id_vin = :new.id_vin;
IF :new.qte > v_stock THEN
RAISE_APPLICATION_ERROR(-20100, 'Stock insuffisant');
END IF;
END;
Q4 — Écris une procédure Cumul_Depenses_Client(p_id) qui parcourt les commandes du client et renvoie son ca_cumule mis à jour.
CREATE OR REPLACE PROCEDURE Cumul_Depenses_Client(p_id IN NUMBER)
IS
v_total NUMBER := 0;
CURSOR c_cmds IS
SELECT total FROM Commande WHERE id_client = p_id;
BEGIN
FOR r IN c_cmds LOOP
v_total := v_total + r.total;
END LOOP;
UPDATE Client SET ca_cumule = v_total WHERE id_client = p_id;
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('Client introuvable');
END;
Q5 — Soit 3 sites (Lille, Lyon, Toulouse). Comment fragmenter Client ? Comment écrire la vue de recomposition ?
Fragmentation horizontale de Client sur la ville :
Client_Lille = σ(Client; ville = 'Lille') @ Lille
Client_Lyon = σ(Client; ville = 'Lyon') @ Lyon
Client_Toulouse = σ(Client; ville = 'Toulouse') @ Toulouse
Vue de recomposition sur le site central :
CREATE VIEW Client_complet AS
SELECT * FROM Client@lille
UNION
SELECT * FROM Client@lyon
UNION
SELECT * FROM Client@toulouse;