Académique Documents
Professionnel Documents
Culture Documents
Correction SERIE DE TD N° 4
Langage PL/SQL
Exercice 1 :
Réponse :
Set serveroutput on ;
DECLARE
Cursor C_emp is select P.Matr, P.CodeP, Pr.NomP from Participation P, Projet Pr
Where P.CodeP = Pr.CodeP order by P.Matr;
E_emp Exception;
rec C_emp%rowtype;
BEGIN
Open C_emp;
DBMS_output.put_line(RPAD('Matr.Emp.',15) || RPAD('Code Projet',15) || RPAD('Nom
Projet',15));
loop
Fetch C_emp into rec;
exit when C_emp%notFound;
DBMS_output.put_line(RPAD(rec.Matr,15) || RPAD(rec.CodeP,15) ||
RPAD(rec.NomP,15));
end loop;
if(C_emp%rowcount = 0) then
raise E_emp;
Page 1/15
end if;
close C_emp;
EXCEPTION
when E_emp then
DBMS_output.put_line('Aucun Projet trouvé...');
--when others then
--DBMS_output.put_line('Exception non reconnue...');
END;
/
2. Définir un bloc PL/SQL anonyme, en prévoyant les exceptions que vous jugez nécessaire,
permettant de lire les détails de tous les employés ainsi que le nombre de projets effectués
par chacun d’eux.
Set serveroutput on ;
DECLARE
Cursor C_emp is select E.Matr, E.NomE, E.Poste, E.NumDept from EMP E order
by E.Matr;
Cursor C_NBProjets(P_Matr EMP.MATR%type) is select count(P.CodeP) from
Participation P, EMP E
Where P.Matr = E.Matr and E.Matr = P_Matr group by P.Matr;
E_emp Exception;
rec C_emp%rowtype;
nbPr Number :=0;
BEGIN
Open C_emp;
DBMS_output.put_line(RPAD('Matr Emp',15) || RPAD('Nom EMP',15) ||
RPAD('Poste EMP',15) || RPAD('Dept EMP',15) || RPAD('nb Projets',15));
loop
Fetch C_emp into rec;
exit when C_emp%notFound;
Open C_NBProjets(rec.Matr);
nbPr:=0;
Fetch C_NBProjets into nbPr;
DBMS_output.put_line(RPAD(rec.Matr,15) || RPAD(rec.NomE,15) ||
RPAD(rec.Poste,15) || RPAD(rec.NumDept,15) || RPAD(nbPr,15));
close C_NBProjets;
end loop;
if(C_emp%rowcount = 0) then
raise E_emp;
end if;
close C_emp;
EXCEPTION
when E_emp then
DBMS_output.put_line('Aucun Employé trouvé...');
Page 2/15
--when others then
--DBMS_output.put_line('Exception non reconnue...');
END;
/
b. En utilisant un curseur explicite et un curseur implicite.
Réponse :
Set serveroutput on ;
DECLARE
Cursor C_emp is select E.Matr, E.NomE, E.Poste, E.NumDept from EMP E order
by E.Matr;
E_emp Exception;
rec C_emp%rowtype;
nbPr Number :=0;
BEGIN
Open C_emp;
DBMS_output.put_line(RPAD('Matr Emp',15) || RPAD('Nom EMP',15) ||
RPAD('Poste EMP',15) || RPAD('Dept EMP',15) || RPAD('nb Projets',15));
loop
Fetch C_emp into rec;
exit when C_emp%notFound;
nbPr:=0;
begin
select count(P.CodeP) into nbPr from Participation P
Where P.Matr = rec.Matr group by P.Matr;
exception
when no_data_found then
nbPr:=0;
end;
DBMS_output.put_line(RPAD(rec.Matr,15) || RPAD(rec.NomE,15) ||
RPAD(rec.Poste,15) || RPAD(rec.NumDept,15) || RPAD(nbPr,15));
end loop;
if(C_emp%rowcount = 0) then
raise E_emp;
end if;
close C_emp;
EXCEPTION
when E_emp then
DBMS_output.put_line('Aucun Employé trouvé...');
when too_many_rows then
DBMS_output.put_line('Commande Select retourne plusieurs lignes...');
END;
/
3. Soit une fonction max_sal_dept(p_deptno emp.deptno%TYPE) qui retourne le salaire
le plus élevé des employés d'un département donné dont le numéro est fourni comme
paramètre :
a. Ecrire cette fonction sous forme d’une fonction non stockée dans un bloc
anonyme.
Réponse :
Page 3/15
Set serveroutput on ;
DECLARE
SalaireMax Number :=0;
function max_sal_dept(p_deptno in emp.numdept%TYPE) return Number is
Cursor C_salaire is select max(salaire) from EMP where numdept = p_deptno;
E_salaire Exception;
MaxSal Number :=0;
BEGIN
Open C_salaire;
Fetch C_salaire into MaxSal;
if(C_salaire%rowcount = 0) then
raise E_salaire;
end if;
close C_salaire;
return MaxSal;
EXCEPTION
when E_salaire then
DBMS_output.put_line('Aucun Employé trouvé...');
return NULL;
END;
BEGIN
SalaireMax:= max_sal_dept(10);
DBMS_output.put_line(RPAD('Le Salaire Maximal est : ',30) || SalaireMax);
END;
/
b. Ecrire cette fonction sous forme d’une fonction stockée.
Réponse :
Page 4/15
La fonction non stockée est définie est appelée dans le même bloc anonyme (ou autre
bloc nommé), alors elle n’est pas visible ailleurs. Cependant, la fonction stockée est
définie d’une manière indépendante, c’est un bloc nommé indépendant. Elle est
appelée dans un autre bloc nommé/anonyme. Voilà un exemple :
Set serveroutput on ;
DECLARE
SalaireMax Number :=0;
BEGIN
SalaireMax:= max_sal_dept(10);
DBMS_output.put_line(RPAD('Le Salaire Maximal est : ',30) || SalaireMax);
END;
/
4. Dans un bloc PL/SQL anonyme, déclarer et tester une procédure « ListeProjets1 » qui
affiche la liste des projets effectués par tous les employés.
Réponse :
Set serveroutput on ;
DECLARE
procedure ListeProjets1 is
Cursor C_Projets is select distinct P.CodeP, NomP from Participation P, Projet Pr
where P.CodeP = Pr.CodeP order by P.CodeP;
E_Projets Exception;
rec C_Projets%rowtype;
BEGIN
Open C_Projets;
DBMS_output.put_line(RPAD('Code Projet',20) || RPAD('Nom Projet',20));
Loop
Fetch C_Projets into rec;
exit when C_Projets%notfound;
DBMS_output.put_line(RPAD(rec.Codep,20) || RPAD(rec.NomP,20));
end Loop;
if(C_Projets%rowcount = 0) then
raise E_Projets;
end if;
close C_Projets;
EXCEPTION
when E_Projets then
DBMS_output.put_line('Aucun Projet trouvé...');
END;
BEGIN
Page 5/15
-- appel de la procédure :
ListeProjets1;
END;
/
5. Dans un package nommé « Package1 », définir une procédure nommée « ListeProjets2 »
qui affiche la liste des projets qui ne sont pas effectués par les employés de département
20.
Page 6/15
E_Projets Exception;
begin
dbms_output.put_line(Rpad('Code Projet',20)|| Rpad('Nom Projet',20));
open C_Projets;
loop
fetch C_Projets into rec;
exit when C_Projets%notfound;
if(C_Projets%rowcount = 0) then
raise E_Projets;
end if;
dbms_output.put_line(Rpad(rec.codeP,20)|| Rpad(rec.NomP,20));
end loop;
close C_Projets;
exception
when E_Projets then
DBMS_output.put_line('Aucun Projet trouvé...');
end listeProjets2;
Page 7/15
t(i).nom:=rec1.nomP;
i:=i+1;
end loop;
close C_Projets;
exception
when E_Projets then
DBMS_output.put_line('Aucun Projet trouvé...');
end listeProjets3;
Page 8/15
return t;
end ListeEmployes;
end Package1;
/
/*
dbms_output.put_line('Appel de la procédure listeProjets3 : ');
Package1.listeProjets3(t);
if t.count = 0 then
raise E_NoData;
end if;
dbms_output.put_line(Rpad('Code Projet',30)|| Rpad('Nom Projet',30));
for i in t.first..t.last
loop
dbms_output.put_line(Rpad(t(i).num,30)|| Rpad(t(i).nom,30));
end loop;
exception
when E_NoData then
dbms_output.put_line('Aucun élément trouvé');
*/
/*
dbms_output.put_line('Appel de la fonction ListeEmployes : ');
t := Package1.ListeEmployes(10);
if t.count = 0 then
Page 9/15
raise E_NoData;
end if;
dbms_output.put_line(Rpad('Code Projet',30)|| Rpad('Nom Projet',30));
for i in t.first..t.last
loop
dbms_output.put_line(Rpad(t(i).num,30)|| Rpad(t(i).nom,30));
end loop;
exception
when E_NoData then
dbms_output.put_line('Aucun élément trouvé');
*/
end;
/
Page 10/15
Exercice 2 :
Réponse :
Set serveroutput on ;
DECLARE
TYPE refCursor IS REF CURSOR;
C_Projets refCursor;
rec projet%rowtype;
E_Projets Exception;
function ListeProjets1 return refCursor is
resultat refCursor;
BEGIN
OPEN Resultat FOR
select distinct P.CodeP, NomP from Participation P, Projet Pr
where P.CodeP = Pr.CodeP order by P.CodeP;
return Resultat;
end;
BEGIN
-- appel de la fonction :
C_Projets := ListeProjets1;
--Open C_Projets;
DBMS_output.put_line(RPAD('Code Projet',20) || RPAD('Nom Projet',20));
Loop
Fetch C_Projets into rec;
exit when C_Projets%notfound;
DBMS_output.put_line(RPAD(rec.Codep,20) || RPAD(rec.NomP,20));
Page 11/15
end Loop;
if(C_Projets%rowcount = 0) then
raise E_Projets;
end if;
close C_Projets;
EXCEPTION
when E_Projets then
DBMS_output.put_line('Aucun Projet trouvé...');
END;
/
2. Définir un déclencheur (Trigger) « Department_Inserted » qui, après toute adjonction d’un
département, affiche le numéro de département à ajouter.
Réponse :
Réponse :
Page 12/15
Begin
DBMS_output.put_line('Le departement modifié est : ' );
DBMS_output.put_line(RPAD('Ancien directeur',20) || RPAD('Nouveau directeur',20));
DBMS_output.put_line(RPAD(:Old.directeur,20) || RPAD(:New.directeur,20));
END;
/
4. Définir un déclencheur (Trigger) « Department_Deleted » qui, avant toute suppression
d’un département, affiche le numéro de département à supprimer.
Réponse :
Réponse :
Page 13/15
before insert or delete or update on Participation
Declare
NoAcces_On_Weekends Exception;
Begin
If ( TO_char(sysdate,'DY') = 'MAR.' OR TO_char(sysdate,'') = 'MER.') then
RAISE NoAcces_On_Weekends;
end if;
Exception
When NoAcces_On_Weekends then
RAISE_APPLICATION_ERROR(-20324,'Vous ne pouvez pas modifier les données des
Participation pendant le Weekend.');
END;
/
6. Désactiver les déclencheurs crées puis les réactiver une autre fois.
Réponse :
Réponse :
Page 14/15
DBMS_output.put_line(RPAD('Ancien Salaire',20) || RPAD('Nouveau Salaire',20));
DBMS_output.put_line(RPAD(:Old.Salaire,20) || RPAD(:New.Salaire,20));
END;
/
8. Définir un déclencheur (Trigger) BEFORE « Salary_ERROR » permettant d’afficher,
avant toute modification du salaire d’un employé, un message d’erreur si le nouveau
salaire est inférieur à 500.
Réponse :
Page 15/15