Vous êtes sur la page 1sur 11

Corrections

A. TRIGGERS [Connectez-vous au compte exemple SCOTT et copier toutes les tables dans votre compte].

Exercice 0 :
Trigger qui affiche un message après chaque manipulation de la table Emp
create or replace trigger alert after insert or update or delete on emp
begin
dbms_output.put_line('Operation terminée');
end;
/
1- Créer un trigger qui -avant de mettre à jour l’âge- d’un étudiant donné, le nouvel âge saisi
doit être supérieur à l’ancien (on utilisera une exception).

create or replace trigger update_age before update on etudiant


for each row
declare
exc exception;
begin
if :new.ageet<:old.ageet
then raise exc;
end if;
exception
when exc then
Raise_Application_error(-20001, 'le ouveau age doit etre superieur a l
anciene');
end;
/
2-Définir un trigger en insertion permettant d’implémenter une numérotation automatique de la
cléNumEt de la table Etudiant. Le premier numéro doit être égal à 1.

create or replace trigger inc before insert on etudiant


for each row
declare
id number;
begin
select count(*) into id from etudiant;
if id = 0 then :new.numet := 1 ;
else
select max(numet) into id from etudiant;
:new.numet := id + 1;
end if;
end;
/

3- Donner un trigger qui interdit toute opération lundi sur la table DEPT (compte scott)

create or replace trigger nowork before insert or update or


delete on departments
declare v number;
begin
select to_char(sysdate,'d') into v from dual;
if v=1 then
raise_application_error(-20500, 'no work');
end if;
end;
/
Déclencheur créé.

Delete from departments

ORA-20500: no work

B.PLSQL
On dispose d’une table BUDGET qui a été créée de la manière suivante :
CREATE TABLE BUDGET ( NUM_OPERATION NUMBER (4,2) PRIMARY KEY,
NOM_OPERATION VARCHAR2 (15),
CATEGORIE VARCHAR2 (10),
DATE_OPERATION DATE,
MONTANT NUMBER (6, 2),
SOLDE NUMBER (7, 2) ) ;
Il vous faut créer la table BUDGET à partir de la table BUDGET.
Remarque : les montants des opérations effectuées ainsi que les soldes sont exprimés en Dirhams .
1- On souhaite insérer un nouvel enregistrement dans la table budget sans avoir à saisir le
numéro de l’opération et le nouveau solde. Écrire un programme PL/SQL qui ajoute un nouvel
enregistrement à la table BUDGET avec les valeurs suivantes :
- Num_Operation : calculé automatiquement en ajoutant 1 à la plus grande valeur de
Num_Operation présent dans la table BUDGET.
- Nom_Operation : Courses
- Categorie : Débit
- Date_Operation : 14/01/2002
- Montant : 500 (en dirhams)
- Solde : calculé automatiquement en fonction du dernier solde de la table BUDGET (celui
pour lequel Num_Operation est le plus grand).
-
DECLARE
max_operation budget.num_operation;
new_solde budget.solde%TYPE;
Begin
select max(num_operation)+1 into max_operation from budget;
select solde-500 into new_solde from budget where
num_operation=(select max(num_operation) from budget);
INSERT INTO BUDGET
VALUES(max_operation,'Courses','Ddebit','14/01/2002',500,new_sol
de);

End;
/

2- Utilisation des curseurs


On souhaite à présent effectuer des traitements sur plusieurs colonnes en même temps.
L’objectif de cet exercice est de construire une table COURSES, qui contient toutes les
opérations pour lesquelles le nom de l’opération est ‘Courses’, à partir de la table BUDGET.
La table COURSES doit contenir les champs suivants : Num_operation, Nom_operation,
Categorie, Date_operation et Montant. Pour cela, il faut définir un curseur qui va parcourir
toute la table BUDGET. Pour chaque enregistrement que va traiter le curseur, le programme
devra déterminer si il doit être inséré dans la table BUDGET ou non.
DECLARE
lbudget budget%ROWTYPE;
CURSOR req1 IS SELECT * FROM BUDGET WHERE
nom_operation='Courses';
BEGIN
OPEN req1;
LOOP
FETCH req1 INTO lbudget;
EXIT WHEN req1%NOTFOUND;
INSERT INTO COURSES VALUES
(lbudget.num_operation, lbudget.nom_operation,
lbudget.categorie, lbudget.date_operation, lbudget.montant);
END LOOP;
CLOSE req1;
END;
2ème variante:

DECLARE ----de préférence V_BUDGET BUDGET%ROWTYPE


i NUMBER;
Num_op BUDGET.Num_operation%TYPE := 0 ;
Type_op BUDGET.Type_operation%TYPE;
Categorie_op BUDGET.Categorie%TYPE;
Date_op BUDGET.Date_Operation%TYPE;
Montant_op BUDGET.Montant%TYPE;
Solde_op BUDGET.Solde%TYPE;
CURSOR Curseur_2 IS SELECT Type_operation, Categorie, Date_operation, Montant, Solde
FROM BUDGET WHERE Date_operation>’01/01/2002’;
BEGIN
I:=0;
OPEN Curseur_2;
LOOP
I:= i+1;

FETCH Curseur_2 INTO Type_op, Categorie_op, Date_op, Montant_op, Solde_op;

INSERT INTO BUDGET_EURO VALUES (Num_op, Type_op, Categorie_op,


Date_op, Montant_op/6.55957, Solde_op/6.55957);
Num_op := Num_op + 1 ;
EXIT WHEN Curseur_2%NOTFOUND ;
END LOOP ;
CLOSE Curseur_2;
END;
/
SELECT * FROM BUDGET_EURO ;
DROP TABLE BUDGET_EURO;

C. FONCTIONS/ PROCEDURES/PACKAGES

1- Ecrire une fonction qui permet de retourner le nom du département, prenant en


paramètre le numéro du département.

create or replace function nom_dept(numero dept.deptno%type)


return VARCHAR2 is
nom dept.dname%type ;
begin
select dname into nom from dept where deptno =
numero;
return nom;
exception
when no_data_found then
DBMS_OUTPUT.PUT_LINE('le département n''existe
pas');
end nom_dept;
/

2- Refaire la même question en utilisant une procédure, prenant en paramètre le numéro du


département et le nom du département.

create or replace procedure nom_dept2(numero IN dept.deptno%type, nom


OUT dept.dname%type) is
begin
select dname into nom from dept where deptno = numero ;
exception
when no_data_found then
DBMS_OUTPUT.PUT_LINE('le département n''existe pas');
end nom_dept2;
/

--appel de la procédure
declare
pnom VARCHAR2(100);
begin
nom_dept2(1,pnom); -- appel de la procedure
dbms_output.put_line(pnom);
end;
/
3- Ecrire une procédure (en utilisant les curseurs et la fonction de l'exercice 1) qui permet
d'afficher les noms des employés sous la forme suivante:
L'employé <<Nom employé>> a la profession <<Profession>> dans le département <<Nom
département >>.

create or replace procedure affiche is


cursor s is select ENAME, JOB, DEPTNO from EMP;
ligne s%rowtype;
begin
open s;
loop
fetch s into ligne;
dbms_output.put_line('L''employé '|| ligne.ename|| ' à la profession ' || ligne.job || ' dans le
département ' || nom_dept(ligne.deptno));
exit when s%notfound;
end loop;
close s;
end affiche;
/

4- Ecrire une fonction, prenant en paramètre le numéro de l'employé, qui permet d'afficher et de
retourner le nom de l'employé (l'affichage est de même forme que la question 1).

create or replace function rname(nemp in emp.empno%type) return


emp.ename%type is
nom emp.ename%type;
fonction emp.job%type;
no emp.deptno%type;
begin
select ename,job,deptno into nom, fonction,no from emp where
empno=nemp;
dbms_output.put_line('L''employé '|| nom || ' à la profession ' || fonction|| '
dans le département ' || nom_dept(no));
return nom;
exception
when no_data_found then
dbms_output.put_line('cet employé n''existe pas');
end rname;
/

5-Ecrire une fonction prenant en paramètre le numéro de l'employé et


retournant le nom de son chef, si il s'agit du chef, la fonction retourne
"Aucun".

create or replace function nchef(no emp.empno%type)


return emp.ename%type is
NumC emp.empno%type;
NomC emp.ename%type;
begin
select mgr into NumC from emp where empno=no;
dbms_output.put_line(NumC);
if NumC is null then
NomC:='Aucun';
else
NomC:=nchef(NumC);
end if;
return NomC;
exception
when no_data_found then
dbms_output.put_line('cet employé n''existe pas');
return null;
end nchef;
/

6- Ecrire une procédure qui permet d'augmenter les salaires (sans tenir compte la commission)
des employés selon leurs grades.
- 10% pour le grade 1 et grade 2.
- 15% pour le grade 3.
- 20% pour le grade 4 et grade 5.
create or replace procedure augmentation is
cursor c is
select empno,sal,grade from emp, SalGrade where
EMP.SAL between SalGrade.LOSAL and SalGrade.HISAL FOR UPDATE
of SAL;
ligne c%rowtype;
begin
open c;
loop
fetch c into ligne;
exit when c%notfound;
if ligne.grade in (1,2) then
dbms_output.put_line(ligne.sal || ' avec grade de ' || ligne.grade);
update emp set sal=sal*1.1 where empno=ligne.empno;
elsif ligne.grade=3 then
dbms_output.put_line(ligne.sal || ' avec grade de ' || ligne.grade);
update emp set sal=sal*1.15 where empno=ligne.empno;
else
dbms_output.put_line(ligne.sal || ' avec grade de ' || ligne.grade);
update emp setselect sal=sal*1.2 where empno=ligne.empno;

end if ;
end loop;
close c;
end augmentation;
/

7-Donner une fonction qui permet de retourner le salaire maximum pour un département donné
(compte SCOTT)

create or replace function getmaxsal(vdept dept.deptno%type)


return number is
v1 number;
begin
select max(sal) into v1 from emp where
deptno=vdept;
return v1;
exception when no_data_found then return -1;
end;
Appel de la function: select getmaxsal(20) from dual;

8-Donner une procédure qui permet de majorer le salaire des employés d’un département donné
avec un taux donné (compte SCOTT)

create or replace procedure setsal


(vdept dept.deptno%type,taux number) is
begin
update emp set sal=sal*taux where deptno=vdept;
commit;
end;
/
Appel de la procedure : execute setsal (20,1.2);
Sql> select object_name from user_objects where
object_type='PROCEDURE';
Sql> select text from user_source where
name='SETSAL' order by line;

9-Donner une procédure qui permet de créer un utilisateur donné (paramètre nom utilisateur et
password)

create or replace procedure creuser(name varchar2,pwd


varchar2) is
begin
execute immediate 'create user '|| name ||' identified by '|| pwd;
execute immediate 'grant connect,resource to ' || name ;
end;
/
execute creuser('test','test');

10-Créer une fonction qui permet de retourner la moyenne des salaires les plus
basses par département ; et qui permet d'afficher un message indiquant si la
moyenne des salaires d'un empolyé donné passé en paramètres à cette fonction est
> ou < ou = à la moyenne des salaires la plus basse

set serveroutput on

CREATE OR REPLACE FUNCTION F(nom emp.ename%type) RETURN


emp.sal%type
IS
moyen emp.sal%type ;
v emp.ename%type;
ndep emp.deptno%type;
cursor c is select avg(sal) from emp where deptno = ndep;
BEGIN
SELECT deptno INTO ndep FROM emp WHERE ename = nom ;
SELECT min(avg(sal)) INTO moyen FROM emp GROUP BY deptno;

open c;
fetch c into v;
if(v <= moyen)
then
DBMS_output.put_line('le salaire est inferieur');
end if;

if(v >= moyen)


then
DBMS_output.put_line('le salaire est superieur');
end if;

close c;
RETURN(moyen) ;
END ;

11-Créer un package contenant les spécifications des exercices 7-10 et tester

Create or replace package …


Create or replace package body……..

Appel : Nom_package.NomProc(parmEffectifs)

Vous aimerez peut-être aussi