100% ont trouvé ce document utile (1 vote)
3K vues8 pages

TP Corrige PLSQL

Transféré par

Hanen Brahmi
Copyright
© © All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd
100% ont trouvé ce document utile (1 vote)
3K vues8 pages

TP Corrige PLSQL

Transféré par

Hanen Brahmi
Copyright
© © All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd
Vous êtes sur la page 1/ 8

NFA011 – Développement d’applications avec les bases de données

TP PL/SQL
(Corrigé)

Exercices SQL (optionnel)


Donnez les commandes SQL suivantes :

1. Les pilotes qui gagnent plus de 20000 euros.

Solution :
select * from pilote
where salaire >= 20000;

2. Le nombre de vols arrivant à Paris.

Solution :
select count(*) from vol
where ville_arrivee = 'Paris';

3. Les pilotes qui gagnent le plus (salaire le plus grand).

Solution :
select nom, salaire from pilote
where salaire = (select max(salaire) from pilote);

4. Les villes classés en ordre décroissant du nombre de vols départ ?

Solution :
select ville_depart, count(*) as nb_vols from vol
group by ville_depart
order by nb_vols desc;

5. Noms de paires de pilotes qui ont le même age mais salaire différent.

Solution :
select p1.nom, p2.nom
from pilote p1, pilote p2
where p1.age = p2.age and
p1.salaire <> p2.salaire and
p1.nom < p2.nom;

6. Combien de vols arrivent dans une ville d’où il n’y a pas de vol départ.

Solution :
select ville_arrivee, count(*)
from vol
where ville_arrivee in
((select ville_arrivee from vol) minus
(select ville_depart from vol))
group by ville_arrivee;

NFA011
NFA011 – Développement d’applications avec les bases de données

7. Villes à partir desquelles il y au moins un vol de départ vers toutes les autres villes.

On utilise seulement la table Vol, car la table Escales ne contient


forcement toutes les villes. Cette requête donne la liste de toutes les
villes dans la table Vol :

create table ListeVilles as


select * from ((select ville_depart as ville from vol) union
(select ville_arrivee as ville from vol));

Une ville candidat (C) fait partie de la réponse s’il n’existe pas une
autre ville (différente de C) vers laquelle il n’y a pas de vol a partir du
C : c.t.d. la liste des villes vers lesquelles il n’y a pas de vols à
partir de C est vide. Cette liste est égale a ListeVilles (toutes les
villes) moins la liste des villes vers lesquelles il y a un vol à partir de
C.

select lv1.ville from ListeVilles lv1 -- lv1.ville est le candidat


where not exists
(select lv2.ville from ListeVilles lv2
where lv2.ville <> lv1.ville and lv2.ville not in
(select ville_arrivee from vol
where ville_depart = lv1.ville));

DROP TABLE ListeVilles purge;

Généralités SQL et PLSQL

Exercice 1. Exécutez sous SQL*PLUS les solutions des exercices 1, 2, 3, 4, 5, 6 de la partie ED.
Si des tables sont nécessaires il faut aussi les créer.

Solution : Voir corrigé ED.

Exercice 2. Écrire une fonction PL/SQL qui retourne le n-ème numéro de Fibonacci :
x n= x n−1 + x n−2 où x 0=1 et x 1=1
Écrire une version récursive et une version itérative.

Solution :
CREATE OR REPLACE FUNCTION FIBOREC (N INTEGER)
RETURN INTEGER
IS
BEGIN
IF (N<1) THEN
RETURN -1;
ELSIF(N=1) THEN
RETURN 1;
ELSIF(N=2) THEN
RETURN 1;
ELSE
RETURN FIBOREC(N-1) + FIBOREC(N-2);
END IF;
END FIBOREC;

NFA011
NFA011 – Développement d’applications avec les bases de données

CREATE OR REPLACE FUNCTION FIBOITER (N INTEGER)


RETURN INTEGER
IS
R1 INTEGER := 1;
R2 INTEGER := 1;
RESULTAT INTEGER;
BEGIN
IF (N<1) THEN
RETURN -1;
ELSIF(N=1) THEN
RETURN 1;
ELSIF(N=2) THEN
RETURN 1;
ELSE
FOR I IN 3..N LOOP
RESULTAT := R1 + R2;
R2 := R1;
R1 := RESULTAT;
END LOOP;
RETURN RESULTAT;
END IF;
END FIBOITER;

Exercice 3. Écrire une fonction qui prend in paramètre un nombre entier N et qui retourne la
somme de tous le multiples de 3 ou de 5 plus petits que N.

Solution :
CREATE OR REPLACE FUNCTION SOMMEDIV(N INTEGER)
RETURN INTEGER
IS
S INTEGER := 0;
BEGIN
FOR i IN 1..N LOOP
IF (MOD(i, 3) = 0) OR (MOD(i, 5) = 0) THEN
S := S + i;
END IF;
END LOOP;
RETURN S;
END;
/

Exercice 4. Écrivez un programme PL/SQL qui affiche tous les vols arrivant à Paris. Utilisez un
curseur.

Solution :
DECLARE
CURSOR c IS SELECT * FROM vol WHERE ville_arrivee = 'Paris';
v VOL%ROWTYPE;
BEGIN
OPEN c;
LOOP
FETCH c INTO v;
EXIT WHEN (c%NOTFOUND OR c%NOTFOUND IS NULL);
DBMS_OUTPUT.PUT_LINE(v.numvol);

END LOOP;
CLOSE c;
END;

NFA011
NFA011 – Développement d’applications avec les bases de données

Exercice 5. Écrivez un programme PL/SQL qui calcule la moyenne des trois plus grands salaires
de pilote.

Solution :
DECLARE
CURSOR c IS select salaire from pilote order by salaire desc;
somme NUMBER := 0;
sal pilote.salaire%TYPE;
BEGIN
OPEN c;
FOR i IN 1..3 LOOP
FETCH c into sal;
somme := somme + sal;
END LOOP;
CLOSE c;
DBMS_OUTPUT.PUT_LINE('Moyenne 3 plus grands salaires de pilote: ' ||
somme/3);
END;
/

Exercice 6. Expliquez les résultats obtenus par l’exécution du programme PL/SQL suivant :
DECLARE
n NUMBER := 10;
PROCEDURE etudeNocopy
(n1 IN NUMBER, n2 IN OUT NUMBER, n3 IN OUT NOCOPY NUMBER) IS
BEGIN
n2 := 20;
DBMS_OUTPUT.PUT_LINE(n1);
n3 := 30;
DBMS_OUTPUT.PUT_LINE(n1);
END etudeNocopy;
BEGIN
etudeNocopy(n, n, n);
DBMS_OUTPUT.PUT_LINE(n);
END;

Solution :
Le programme affiche 10 30 20. Ceci est expliqué par le fait que par défaut les paramètres IN sont
transmis par référence et les paramètres OUT et IN OUT sont transmis par valeur. NOCOPY
c'est une indication pour l’interpréteur de faire, si possible, une transmission par référence et non
par valeur.

Exercice 7. Exécutez sous SQL*PLUS les solutions des exercices 18, 19, 20 de la partie ED. Si
des tables sont nécessaires il faut aussi les créer.

Solution : Voir corrigé ED.

Exercice 8. Écrivez un déclencheur qui vérifie pour chaque nouveau vol inséré dans la table VOL
que la ville de départ est bien différente de la ville d'arrivée. Si c'est le cas, on affiche un message
d'erreur et l'insertion ne doit pas être faite. Vérifiez que le trigger fonctionne.

Solution :
drop trigger TriggerVol;
CREATE TRIGGER TriggerVol
BEFORE INSERT ON Vol FOR EACH ROW

NFA011
NFA011 – Développement d’applications avec les bases de données

BEGIN
IF :NEW.ville_depart = :NEW.ville_arrivee THEN
RAISE_APPLICATION_ERROR(-20000, 'La ville de depart est
la meme que la ville d''arrivee');
END IF;
END;
/
-- Executer dans sqlplus :
-- insert into vol values ('AF918', to_date('08:30', 'hh24:mi'),
to_date('10:57', 'hh24:mi'), 'Paris', 'Paris');

Exercice 9. Écrivez une procédure qui affiche les villes pour lesquelles le nombre de vols d’arrivée
(dans cette ville) est plus grand que les nombre de vols de départ (de cette ville). Utilisez un
curseur paramétré.

Solution :
CREATE OR REPLACE PROCEDURE AFFICHE_VILLE IS
CURSOR C IS select * from ((select ville_depart as ville from vol)
union
(select ville_arrivee as ville from vol));
n1 INTEGER;
n2 INTEGER;
BEGIN
FOR e in C LOOP
SELECT COUNT(*) INTO N1
FROM VOL WHERE ville_depart = e.ville;
SELECT COUNT(*) INTO N2
FROM VOL WHERE ville_arrivee = e.ville;
IF N2 > N1 THEN
DBMS_OUTPUT.PUT_LINE(e.ville);
END IF;
END LOOP;
END;
/

Exercice 10. Écrivez une procédure qui prend un paramétré pVille (le nom d’une ville) et qui
affiche les villes qui ont un vol direct et un vol de retour vers pVille.

Solution :
CREATE OR REPLACE PROCEDURE ALLER_RETOUR(pville vol.ville_depart%type) IS
CURSOR C IS select * from ((select ville_depart as ville from vol)
union
(select ville_arrivee as ville from vol));
n1 INTEGER;
n2 INTEGER;
BEGIN
FOR e in C LOOP
SELECT COUNT(*) INTO N1
FROM VOL WHERE ville_depart = e.ville AND ville_arrivee = pville;
SELECT COUNT(*) INTO N2
FROM VOL WHERE ville_arrivee = e.ville AND ville_depart = pville;
IF N1 > 0 AND N2 > 0 THEN
DBMS_OUTPUT.PUT_LINE(e.ville);
END IF;
END LOOP;
END;
/

NFA011
NFA011 – Développement d’applications avec les bases de données

Exercice 11. Écrire une procédure qui affiche les villes a partir desquelles il y au moins un vol de
de départ vers toutes les autres villes.

Solution :
CREATE OR REPLACE PROCEDURE toutesVilles IS
CURSOR C IS select * from ((select ville_depart as ville from vol)
union
(select ville_arrivee as ville from vol));
CURSOR C1(pville vol.ville_depart%type) IS
select ville from ((select ville_depart as ville from vol)
union
(select ville_arrivee as ville from vol))
WHERE ville <> pville;

OK BOOLEAN;
N INTEGER;
BEGIN
FOR dep in C LOOP
OK := TRUE;
FOR arr in C1(dep.ville) LOOP
SELECT COUNT(*) INTO N FROM VOL
WHERE ville_depart = dep.ville AND ville_arrivee = arr.ville;
IF N = 0 THEN
OK := FALSE;
END IF;
EXIT WHEN NOT OK;
END LOOP;
IF OK THEN
DBMS_OUTPUT.PUT_LINE(dep.ville);
END IF;
END LOOP;
END;
/

Exercice 12. Créez une nouvelle table VOLG qui, par rapport à la table VOL, a un attribut de
plus : OuestEst qui vaut vrai si un vol se déroule géographiquement de l'ouest vers l'est sur la
carte et faux autrement. Cette table nous permettra de trouver des vrais tours du monde dans les
exercices suivants. Peuplez cette table avec les mêmes vols que la table VOL mais avec la mis a
jour correspondante sur l’attribut OuestEst (reprendre les commandes correspondantes INSERT
du fichier tp_tables.sql et ajoutez l’attribut OuestEst).

Solution :
drop table VOLG purge;
create table VOLG(
numvol varchar2(8),
heure_depart date NOT NULL,
heure_arrivee date NOT NULL,
OuestEst INTEGER, -- = 0 vaut FAUX et != 0 vaut VRAI
-- (pas de BOOLEAN dans Oracle SQL)
-- par contre dans PL/SQL il y a bien un type BOOLEAN
ville_depart varchar2(20) NOT NULL,
ville_arrivee varchar2(20) NOT NULL,
constraint volgpk primary key (numvol));

insert into volg values ('AF118', to_date('08:30', 'hh24:mi'),

NFA011
NFA011 – Développement d’applications avec les bases de données

to_date('10:57', 'hh24:mi'), 1, 'Paris', 'Rome');


–– etc

Exercice 13. Reprendre l'exercice 20 de l'ED mais en utilisant la table VOLG crée dans l'exercice
précédent :
VOLG(Numvol, Heure_départ, Heure_arrivée, Ville_départ, OuestEst)
Écrivez une procédure PL/SQL capable de faire des propositions de tours du monde, prenant en
entrée la ville de départ (qui est aussi la destination finale) et deux bornes (supérieure et
inférieure) pour le nombre d’escales. Dans ce cas il n’y a pas de liste prédéfinie d’escales et on ne
s’intéresse pas à la durée des escales. La procédure doit afficher les vols pour chaque tour du
monde proposé. Utiliser une procédure ou fonction récursive. Un tour du monde valide contient
que des vols qui de déroulent dans la direction ouest vers est.

Solution :
CREATE OR REPLACE PROCEDURE trouverEscalesOE(villeBase IN Volg.ville_depart
%TYPE, nbMinEscales IN INTEGER, nbMaxEscales IN INTEGER)
IS
FUNCTION tourValideOE(destCourante IN Volg.Ville_depart%TYPE,
villeDepart IN Volg.Ville_depart%TYPE,
minEscales IN INTEGER, maxEscales IN INTEGER)
RETURN BOOLEAN
IS
valeurRetour BOOLEAN := FALSE;
quelVol Volg%ROWTYPE;
CURSOR curseurVol IS SELECT * FROM Volg
WHERE (Ville_arrivee = destCourante);
BEGIN
FOR quelVol IN curseurVol
LOOP
-- Si le vol n’est pas dans la bonne direction
IF (quelVol.OuestEst = 0) THEN NULL;
ELSIF (((quelVol.Ville_depart = villeDepart) AND (minEscales>0))
OR
((quelVol.Ville_depart != villeDepart) AND (maxEscales<1)))
THEN NULL;
ELSIF (quelVol.Ville_depart = villeDepart) THEN
DBMS_OUTPUT.PUT_LINE('Tour du monde propose: ');
DBMS_OUTPUT.PUT_LINE(' De ' || quelVol.Ville_depart ||
' a ' || destCourante || ' : ' || quelVol.Numvol);
valeurRetour := TRUE;
ELSIF tourValideOE(quelVol.Ville_depart, villeDepart, minEscales-
1, maxEscales-1) THEN
DBMS_OUTPUT.PUT_LINE(' De ' || quelVol.Ville_depart ||
' a ' || destCourante || ' : ' || quelVol.Numvol);
valeurRetour := TRUE;
END IF;
END LOOP;
RETURN valeurRetour;
EXCEPTION
WHEN OTHERS THEN RETURN FALSE;
END tourValideOE;
BEGIN
IF ((nbMinEscales > nbMaxEscales) OR (nbMaxEscales < 1)) THEN
DBMS_OUTPUT.PUT_LINE('Vérifier contraintes pour nombre d''escales');
ELSIF tourValideOE(villeBase, villeBase, nbMinEscales, nbMaxEscales)
THEN
DBMS_OUTPUT.PUT_LINE('Faites votre choix !');

NFA011
NFA011 – Développement d’applications avec les bases de données

ELSE
DBMS_OUTPUT.PUT_LINE('Aucun tour valide n''a pas été trouvé !');
END IF;
END trouverEscalesOE;
/

NFA011

Vous aimerez peut-être aussi