TD 3 corrigé
Transcription
TD 3 corrigé
Exercice 3 : Enregistrements Université Lumière – Lyon 2, Faculté de Sciences Économiques et de Gestion Master d’Informatique M2 spécialité IUP IDS – Année 2005-2006 Bases de données et programmation – TD n° 3 J. Darmont (http://eric.univ-lyon2.fr/~jdarmont/), 25/10/05 1. Nous allons réutiliser la relation PILOTE du TD n° 1. Si ce n’est pas déjà fait, recopier la table PILOTE de l’utilisateur DARMONT sur votre compte. 1. Dans un bloc PL/SQL anonyme, définir un type collection de réels VARRAY de taille 10 qui contiendra des notes d’examen. 2. Dans un bloc PL/SQL anonyme, définir un type enregistrement composé des champs suivants : • nom, du même type que l’attribut PLNOM de PILOTE ; • prénom, du même type que l’attribut PLPRENOM de PILOTE ; • ville, du même type que l’attribut VILLE de PILOTE ; • salaire, du même type que l’attribut SALAIRE de PILOTE. 2. Dans la section déclaration, définir une variable de ce type et l’initialiser avec trois notes. 2. Définir une variable de ce type. 3. Dans la section de code, terminer l’initialisation avec les 7 notes manquantes. Tester. 3. Dans la section de code, définir une requête paramétrée (en utilisant le caractère &) permettant de lire le nom, le prénom, la ville et le salaire d’un pilote de la dont le numéro de pilote est saisi au clavier et de le stocker dans la variable enregistrement préalablement définie. Afficher le résultat au format suivant : Prénom NOM (Ville) : Salaire. Exercice 1 : Collections VARRAY 4. Calculer et afficher la moyenne des notes. 5. Ajouter encore une note dans la collection. Que se passe-t-il ? 6. Afficher la taille maxi et la taille réelle du tableau. Exercice 4 : Sous-programmes et collections 7. À l’aide de la méthode trim, effacer une note du tableau, puis afficher de nouveau la taille maxi et la taille réelle du tableau. 1. Dans un bloc PL/SQL anonyme, définir une fonction de nom « MonMax » prenant en paramètres d’entrée deux réels et renvoyant un réel égal au plus grand des deux paramètres. 8. À l’aide de la méthode delete, effacer le tableau, puis afficher de nouveau la taille maxi et la taille réelle du tableau. 2. Dans le programme principal, déclarer deux variables réelles « a » et « b » et leur affecter une valeur. Appeler la fonction « MonMax » pour « a » et « b » et afficher le résultat. Exercice 2 : Collections TABLE 3. Dans le même bloc PL/SQL, définir un type collection de réels TABLE nommé « TabReels », ainsi qu’une variable « tab » de ce type. Initialiser cette variable avec plusieurs valeurs. 1. Dans un bloc PL/SQL anonyme, définir un type collection de réels TABLE qui contiendra les notes de contrôle continu stockées dans la relation NOTATION du TD n° 2. 2. Définir une variable de ce type l’initialiser à vide. 4. Définir une fonction de nom « MultiMax » prenant en paramètre d’entrée un « TabReels » et renvoyant le plus grand nombre contenu dans ce tableau. Faire appel à la fonction « MonMax » pour effectuer le traitement. Dans le programme principal, appeler la fonction « MultiMax » pour « tab » et afficher le résultat. 3. Dans la section de code, charger en mémoire dans la collection les notes de contrôle continu contenues dans la relation NOTATION à l’aide d’un curseur. Afficher les notes au fur et à mesure. Tester. Ce traitement aurait-il été possible avec un VARRAY ? 5. Ajouter à la fonction « MultiMax » un traitement d’exception déclenchant une erreur fatale lorsque la table passée en paramètre est vide. Tester en initialisant « tab » à vide. 4. Calculer et afficher la moyenne des notes contenues dans la collection. 6. Toujours dans le même bloc PL/SQL, définir une procédure de nom « Tri » permettant de trier par ordre croissant le contenu d’un « TabReels » passé en paramètre. On pourra programmer un simple tri par permutation. 5. Vérifier que votre calcul est bon en affichant le résultat d’une requête SQL utilisant la fonction d’agrégat AVG(). 7. Écrire une procédure de nom « Affiche » permettant d’afficher le contenu d’un « TabReels ». 6. Afficher à l’écran l’indice du premier élément de la collection, l’indice du dernier élément et le nombre d’éléments dans la collection. 8. Dans le programme principal, faire appel aux procédures « Tri » et « Affiche » pour « tab ». Quel doit être le mode de passage de ce paramètre dans caque cas ? 7. Supprimer les éléments d’indice 1, 10 et 16, puis répéter la question 6 (copier/coller). 8. Afficher tous les éléments de la collection. BD et programmation – TD n° 3 1/3 BD et programmation – TD n° 3 2/3 Questions complémentaires : Correction 9. Toujours dans le même bloc PL/SQL, définir une procédure de nom « Tri_conserve » prenant en entrée un « TabReels » non trié et fournissant en sortie un « TabReels » trié. Le « TabReels » en entrée doit conserver son ordre d’éléments initial (c’est-à-dire, ne pas être modifié en sortie). Faire appel à la procédure « Tri » pour effectuer le traitement. 10. Dans le programme principal, déclarer une seconde variable « tab_tri » de type « TabReels » et l’initialiser à vide. Mettre en commentaire l’appel aux procédures « Tri » et « Affiche » des questions 6 et 7 et faire appel à la procédure « Tri_conserve » pour « tab » et « tab_tri », puis à la procédure « Affiche » deux fois pour « tab », puis « tab_tri ». -- Ex. 1 : VARRAY DECLARE TYPE TabReels IS VARRAY(10) OF REAL; notes TabReels := TabReels(10.5, 15, 13); i INTEGER; m REAL := 0; BEGIN notes.EXTEND(7); notes(4) := 8.5; notes(5) := 18.5; notes(6) := 16; notes(7) := 4; notes(8) := 9.5; notes(9) := 12; notes(10) := 11; FOR i IN 1..notes.COUNT LOOP m := m + notes(i); END LOOP; m := m / notes.COUNT; DBMS_OUTPUT.PUT_LINE('Moyenne = '||TO_CHAR(m)); -- notes.EXTEND; NE FONCTIONNE PLUS (taille maxi = 10) -- notes(11) := 20; DBMS_OUTPUT.PUT_LINE('Taille actuelle / Taille limite = ' ||notes.COUNT||' / '||notes.LIMIT); notes.TRIM; DBMS_OUTPUT.PUT_LINE('Taille actuelle / Taille limite = ' ||notes.COUNT||' / '||notes.LIMIT); notes.DELETE; DBMS_OUTPUT.PUT_LINE('Taille actuelle / Taille limite = ' ||notes.COUNT||' / '||notes.LIMIT); END; / -- Ex. 2 : TABLE DECLARE TYPE TabReels IS TABLE OF REAL; notes TabReels := TabReels(); CURSOR notes_stockees IS SELECT notecc FROM notation WHERE notecc IS NOT NULL; t notes_stockees%ROWTYPE; i INTEGER; m REAL := 0; BEGIN FOR t IN notes_stockees LOOP notes.EXTEND; notes(notes.COUNT) := t.notecc; DBMS_OUTPUT.PUT_LINE('notes('||notes.count||') = '||t.notecc); END LOOP; BD et programmation – TD n° 3 3/3 BD et programmation – TD n° 3 4/3 FOR i IN 1..notes.COUNT LOOP m := m + notes(i); END LOOP; m := m / notes.COUNT; DBMS_OUTPUT.PUT_LINE('Moyenne = '||m); -- Fonction max entre deux nombres FUNCTION MonMax(a IN REAL, b IN REAL) RETURN REAL IS BEGIN IF a > b THEN RETURN a; ELSE RETURN b; END IF; END; SELECT AVG(notecc) INTO m FROM notation; DBMS_OUTPUT.PUT_LINE('AVG(notecc) = '||m); DBMS_OUTPUT.PUT_LINE('Indice premier : '||notes.FIRST); DBMS_OUTPUT.PUT_LINE('Indice dernier : '||notes.LAST); DBMS_OUTPUT.PUT_LINE('Nombre elements : '||notes.COUNT); -- Fonction max dans un tableau notes.delete(1); notes.delete(10); notes.delete(16); DBMS_OUTPUT.PUT_LINE('Indice premier : '||notes.FIRST); DBMS_OUTPUT.PUT_LINE('Indice dernier : '||notes.LAST); DBMS_OUTPUT.PUT_LINE('Nombre elements : '||notes.COUNT); FUNCTION MultiMax(t IN TabReels) RETURN REAL IS -- Déclarations locales i INTEGER; m REAL; vide EXCEPTION; i := notes.FIRST; WHILE i<=notes.LAST LOOP DBMS_OUTPUT.PUT_LINE('notes('||i||') = '||notes(i)); i := notes.NEXT(i); END LOOP; BEGIN IF t.COUNT = 0 THEN RAISE vide; END IF; m := t(1); FOR i IN 2..t.COUNT LOOP m := MonMax(m, t(i)); END LOOP; RETURN m; END; / -- Ex. 3 : RECORD DECLARE TYPE Personne IS RECORD( nom pilote.plnom%TYPE, prenom pilote.plprenom%TYPE, ville pilote.ville%TYPE, salaire pilote.salaire%TYPE); pl Personne; EXCEPTION WHEN vide THEN RAISE_APPLICATION_ERROR(-20500, 'MultiMax error : table vide'); END; -- Procédure tri d'un tableau BEGIN SELECT plnom, plprenom, ville, salaire INTO pl FROM pilote WHERE plnum = &Numéro_de_pilote; PROCEDURE Tri(t IN OUT TabReels) IS -- Déclarations locales i INTEGER; j INTEGER; temp REAL; DBMS_OUTPUT.PUT_LINE(pl.prenom||' '||UPPER(pl.nom)||' ('||pl.ville||') : ' ||pl.salaire); END; / BEGIN FOR i IN 1..t.COUNT-1 LOOP FOR j IN i+1..t.COUNT LOOP IF t(j) < t(i) THEN temp := t(i); t(i) := t(j); t(j) := temp; END IF; END LOOP; END LOOP; -- Ex. 4 : SOUS-PROGRAMMES ET COLLECTIONS DECLARE -- Déclarations du programme principal a REAL := 4.5; b REAL := 3.14; END; TYPE TabReels IS TABLE OF REAL; tab TabReels := TabReels(-3.25, 6.5, 10.2, 9.55, 15.2, 0.255); tab_tri TabReels := TabReels(); BD et programmation – TD n° 3 5/3 BD et programmation – TD n° 3 6/3 -- Procédure tri sans perdre l’ordre initial PROCEDURE Tri_conserve(t_in IN TabReels, t_out OUT TabReels) IS BEGIN t_out := t_in; Tri(t_out); END; -- Procédure affichage d’un tableau PROCEDURE Affiche(t IN TabReels, etiquette VARCHAR) IS -- Déclarations locales i INTEGER; chaine VARCHAR(255) := ''; BEGIN FOR i IN 1..t.COUNT LOOP chaine := chaine || ' ' || t(i); END LOOP; DBMS_OUTPUT.PUT_LINE(etiquette || ' =' || chaine); END; -- Programme principal BEGIN DBMS_OUTPUT.PUT_LINE('MonMax(' || a || ' ; ' || b || ') = ' || MonMax(a,b)); DBMS_OUTPUT.PUT_LINE('MultiMax = ' || MultiMax(tab)); --- Tri(tab); Affiche(tab, 'Tableau trié'); Tri_conserve(tab, tab_tri); Affiche(tab, 'Tableau non trié'); Affiche(tab_tri, 'Tableau trié'); END; / BD et programmation – TD n° 3 7/3