Sunteți pe pagina 1din 4

Université Lumière – Lyon 2, Faculté de Sciences Économiques et de Gestion pourra la réduire la table COMMANDE à l’unique attribut QUANTITE.

Master d’Informatique M2 spécialité IUP IDS – Année 2005-2006


Bases de données et programmation – TD n° 2 Exemple :
J. Darmont (http://eric.univ-lyon2.fr/~jdarmont/), 19/10/05 QUANTITE
5
NULL
Exercice 1 10 Résultat attendu = ( |10 – 5| + |8 – 10| + |9 – 8| + |13 – 9| ) / 4 = 3
8
9
1. Sous SQL, créer une table nommée TEST_DBL contenant un seul attribut numérique. Ne pas 13
spécifier de clé primaire. Peupler cette table en incluant des doublons et des triplets.
Cas particuliers à traiter :
2. Écrire un bloc PL/SQL anonyme permettant d’afficher les valeurs présentes au moins en double
dans la table TEST_DBL. • La table COMMANDE contient moins de deux commandes valuées.

3. Intégrer dans le programme PL/SQL la suppression les doublons. Indications :


• Créer la table COMMANDE et la remplir à l’aide de SQL.
4. Est-il possible d’ajouter une clé primaire à la table TEST_DBL depuis un bloc PL/SQL ? • Créer un curseur contenant les quantités des commandes valuées.
• À l’aide d’un parcours de curseur personnalisé, lire la première quantité puis, pour toutes les
quantités suivantes, cumuler la valeur absolue de quantité courante – quantité précédente
Exercice 2
(fonction ABS).
On souhaite appliquer une règle d’échantillonnage à la table DARMONT.EMP (Empno, Ename…).
Écrire un programme PL/SQL (bloc PL/SQL anonyme) permettant de lire la table EMP et
Exercice 4 : Application
d’afficher les noms des employés dont les rangs d’apparition dans la table sont : 1, 3, 6, 10, 15…
On souhaite gérer les résultats d’examens de la Faculté de Sciences Économiques et de Gestion. Il
Règle de calcul des rangs successifs :
s’agit de définir un programme PL/SQL permettant l’insertion automatique d’informations dans les
1 = 0 + 1 relations « résultats » RESULTAT et CLASSEMENT, à partir des données des relations
3 = 1 + 2 « sources » ETUDIANT, NOTATION et MATIERE, qui contiennent respectivement des
6 = 3 + 3 renseignements sur les étudiants, les notes obtenues par les étudiants et les coefficients affectés aux
10 = 6 + 4 matières.
15 = 10 + 5

Pour définir ce programme, suivre les étapes suivantes.
Résultat attendu :
1) À l’aide du langage SQL, recopier les relations ETUDIANT, NOTATION et MATIERE de
1 : SMITH l’utilisateur DARMONT sur votre propre compte. Utiliser la commande DESC pour en
3 : WARD consulter le schéma.
6 : BLAKE
10 : TURNER 2) Définir en SQL la structure des relations RESULTAT et CLASSEMENT :

Indication : Utiliser un parcours personnalisé de curseur dans lequel n-1 n-uplets sont lus avant • la relation RESULTAT a pour attributs un numéro d’étudiant, un nom d’étudiant, un
d’afficher un nom d’employé (n = 1, 2, 3… ; c’est le nombre en italiques dans la règle de calcul des code matière, ainsi qu’un attribut note globale pour cet étudiant ;
rangs). • la relation CLASSEMENT a pour attributs un numéro d’étudiant, un nom d’étudiant,
une moyenne générale et un rang (place au classement).

Exercice 3 Ne pas inclure de contrainte d’intégrité dans la définition de ces deux relations, qui sont
temporaires et ne servent qu’au stockage des résultats.
Pour tenter d’établir une corrélation, on souhaite connaître la différence de quantité moyenne entre
3) Définir un bloc PL/SQL anonyme permettant d’insérer dans RESULTAT tous les n-uplets
les commandes successivement enregistrées dans la table COMMANDE d’une base de données
constitués du numéro d’un étudiant, de son nom, du code d’une matière et de la note obtenue
CLIENT-COMMANDE-PRODUIT. La table COMMANDE est remplie de commandes valuées
par cet étudiant dans cette matière. Le calcul de cette note doit tenir compte des coefficients
(c’est-à-dire, pour lesquelles l’attribut QUANTITE n’est pas NULL) ou non. Les commandes non
de contrôle continu et d’examen définis pour la matière en question, ainsi que de la
valuées ne sont pas à prendre en compte. Écrire un programme PL/SQL (bloc PL/SQL anonyme)
possibilité d’avoir des valeurs nulles pour les notes des étudiants, qui sont alors assimilées à
permettant de calculer la différence de quantité moyenne entre les commandes. Pour simplifier, on

BD et programmation – TD n° 2 1/5 BD et programmation – TD n° 2 2/5


0 (utiliser la fonction NVL). Les n-uplets considérés doivent être extraits des tables Correction
ETUDIANT, NOTATION et MATIERE de manière itérative, grâce à un curseur adapté.

4) Terminer le traitement en réalisant l’insertion dans la relation CLASSEMENT des n-uplets -- Ex. 1
constitués du numéro d’un étudiant, de son nom, de son prénom, de la moyenne générale
DECLARE
obtenue dans toutes les matières par cet étudiant (ces informations doivent être extraites de CURSOR doublons IS SELECT dbl FROM test_dbl
la table RESULTAT) et de son rang (place), qui doit être calculé. Pour simplifier, on GROUP BY dbl
considère que toutes les matières sont équivalentes en termes de notes. Utiliser un curseur HAVING COUNT(*)>1;
dans lequel les enregistrements sont triés. nuplet doublons%ROWTYPE;

BEGIN
Questions complémentaires DBMS_OUTPUT.PUT_LINE('Valeurs en double dans TEST_DBL :');
FOR nuplet IN doublons LOOP
Modifier le programme afin de prendre en compte : DBMS_OUTPUT.PUT_LINE(nuplet.dbl);
DELETE FROM test_dbl WHERE dbl=nuplet.dbl;
• le cas où plusieurs étudiants ont le même rang (ex æquo) ; INSERT INTO test_dbl VALUES (nuplet.dbl);
END LOOP;
• le cas d’étudiants n’ayant aucune note (par défaut, leur moyenne générale est 0) ; DBMS_OUTPUT.PUT_LINE('Doublons supprimés !');
--ALTER TABLE test_dbl ADD CONSTRAINT test_dbl_pri PRIMARY KEY(dbl);
• la possibilité de n’avoir aucun n-uplet dans la relation ETUDIANT. Dans ce cas, un n-uplet de --Ne fonctionne pas
valeur (0, ’Aucun étudiant’, NULL, NULL) doit être inséré dans la relation RESULTAT et le END;
traitement doit s’arrêter. /

-- Ex. 2

DECLARE
CURSOR employes IS select ename from darmont.emp;
e employes%ROWTYPE;
i INTEGER;
n INTEGER := 1;

BEGIN
OPEN employes;
FETCH employes INTO e; -- 1er n-uplet
WHILE employes%FOUND LOOP
-- Lecture de n-1 n-uplets supplémentaires (on saute des lignes)
i := 1;
WHILE (i < n) AND (employes%FOUND) LOOP
FETCH employes INTO e;
i := i + 1;
END LOOP;
-- Affichage
IF employes%FOUND THEN -- Si on n’est pas en fin de curseur
DBMS_OUTPUT.PUT_LINE(employes%ROWCOUNT || ' : ' || e.ename);
n := n + 1;
FETCH employes INTO e; -- N-uplet suivant
END IF;
END LOOP;
CLOSE employes;
END;
/

BD et programmation – TD n° 2 3/5 BD et programmation – TD n° 2 4/5


-- Ex. 3 -- Edition des resultats et classement des etudiants (bloc PL/SQL)

DECLARE DECLARE
CURSOR valuees IS -- Calcul de la note globale par matiere
SELECT quantite FROM commande WHERE quantite IS NOT NULL; CURSOR etudiant_note IS
cde valuees%ROWTYPE; SELECT ETUDIANT.nume, nom, MATIERE.codemat,
prec REAL; -- quantite precedente ((NVL(notecc, 0) * coefcc) + (NVL(notexam, 0) *coefexam)) /
cour REAL; -- quantite courante (coefcc + coefexam) AS note
cumul REAL; FROM ETUDIANT, NOTATION, MATIERE
moyenne REAL; WHERE ETUDIANT.nume = NOTATION.nume
ncv INTEGER; AND NOTATION.codemat = MATIERE.codemat;
pas_assez EXCEPTION; en etudiant_note%ROWTYPE;
nbe INTEGER; -- Nombre d'etudiants a classer
BEGIN rg INTEGER; -- Place dans le classement general
-- Test nombre de commandes valuees moy NUMBER(5,2); -- Moyenne generale d'un etudiant
SELECT COUNT(*) INTO ncv FROM commande WHERE quantite IS NOT NULL; aucun_etudiant EXCEPTION;
IF ncv < 2 THEN
RAISE pas_assez; -- Calcul de la moyenne generale
END IF; -- Le tri permet de faciliter le traitement ulterieur du classement.
CURSOR etudiant_classe IS
-- Acces 1er n-uplet SELECT nume, nom, AVG(note) moyenne
OPEN valuees; FROM RESULTAT
FETCH valuees INTO cde; -- 1er n-uplet GROUP BY nume, nom
prec := cde.quantite; -- Initialisation du précédent ORDER BY moyenne DESC;
ec etudiant_classe%ROWTYPE;
-- Acces aux suivants et cumul
cumul:=0; -- Gestion des etudiants sans aucune note
WHILE valuees%FOUND LOOP CURSOR etudiant_non_note IS
cour := cde.quantite; SELECT nume, nom FROM ETUDIANT
cumul := cumul + ABS(cour - prec); WHERE nume NOT IN (SELECT DISTINCT nume FROM NOTATION);
prec := cour; enn etudiant_non_note%ROWTYPE;
FETCH valuees INTO cde; -- N-uplet uivant
END LOOP; BEGIN
CLOSE valuees; -- Destruction des donnees eventuelles des annees precedentes
DELETE FROM RESULTAT;
-- Calcul et affichage de la moyenne DELETE FROM CLASSEMENT;
moyenne := cumul / (ncv - 1);
DBMS_OUTPUT.PUT_LINE('Moyenne = '||TO_CHAR(moyenne)); -- Test de l'existance de n-uplets dans la relation ETUDIANT
SELECT COUNT(*) INTO nbe FROM ETUDIANT;
EXCEPTION IF nbe=0 THEN
WHEN pas_assez THEN RAISE aucun_etudiant;
RAISE_APPLICATION_ERROR(-20501,'Pas assez de commandes'); END IF;

END; -- Insertion des etudiants notes comme n-uplets dans RESULTAT


/ FOR en IN etudiant_note LOOP
INSERT INTO RESULTAT
VALUES (en.nume, en.nom, en.codemat, en.note);
-- Ex. 4 END LOOP;

-- RESULTAT -- Insertion des etudiants sans note comme n-uplets dans RESULTAT
FOR enn IN etudiant_non_note LOOP
create table resultat( INSERT INTO RESULTAT
nume number(2), VALUES (enn.nume, enn.nom, NULL, 0);
nom char(20), END LOOP;
codemat number(2),
note number(5,2)); -- Initialisation des variables locales
moy:=21;
-- CLASSEMENT rg:=-1;

create table classement( -- Insertion des n-uplets dans la relation CLASSEMENT


nume number(2), FOR ec IN etudiant_classe LOOP
nom char(20), IF moy>ec.moyenne THEN
moyenne number(5,2), rg:=etudiant_classe%ROWCOUNT;
rang number(2)); END IF;

BD et programmation – TD n° 2 5/5 BD et programmation – TD n° 2 6/5


INSERT INTO CLASSEMENT
VALUES (ec.nume, ec.nom, ec.moyenne, rg);
moy:=ec.moyenne;
END LOOP;

-- Validation de la transaction
COMMIT;

EXCEPTION
WHEN aucun_etudiant THEN
INSERT INTO RESULTAT
VALUES(0, 'Aucun etudiant', NULL, NULL);

END;
/

BD et programmation – TD n° 2 7/5

S-ar putea să vă placă și