Sunteți pe pagina 1din 5

Laborator 4 PL/SQL

Subprograme (proceduri, funcţii)

Sintaxa simplificată de creare a unei proceduri


[CREATE [OR REPLACE] ]
PROCEDURE nume_procedură [ (lista_parameteri) ]
{IS | AS}
[declaraţii locale]
BEGIN
partea executabilă
[EXCEPTION
partea de tratare a excepţiilor]
END [nume_procedură];
Sintaxa simplificată de creare a unei funcţii
[CREATE [OR REPLACE] ]
FUNCTION nume_funcţie [ (lista_parameteri) ]
RETURN tip_de_date
{IS | AS}
[declaraţii locale]
BEGIN
partea executabilă
[EXCEPTION
partea de tratare a excepţiilor]
END [nume_funcţie];
Lista de parametri conţine specificaţii de parametri separate prin virgulă:
nume_parametru mod_parametru;
Mod_parametru poate fi:
- de intrare (IN) – singurul care poate avea o valoare iniţială;
- de intrare / ieşire (IN OUT);
- de ieşire (OUT);
- are valoarea implicită IN.
Funcţiile acceptă numai parametrii de tip IN şi numai tipuri de date SQL (nu şi PL/SQL).
În cazul în care se modifică un obiect (vizualizare, tabel etc) de care depinde un subprogram,
acesta este invalidat. Revalidarea se face ori prin recrearea subprogramului ori prin comanda:
ALTER PROCEDURE nume_proc COMPILE;
ALTER FUNCTION nume_functie COMPILE;
Ştergerea unei funcţii sau proceduri se realizează prin comenzile:
DROP PROCEDURE nume_proc;
DROP FUNCTION nume_functie;
Informaţii despre procedurile şi funcţiile deţinute de utilizatorul curent se pot obţine interogând
vizualizarea USER_OBJECTS.
SELECT *
FROM USER_OBJECTS
WHERE OBJECT_TYPE IN ('PROCEDURE','FUNCTION');
Codul complet al unui subprogram poate fi vizualizat folosind următoarea sintaxă:
SELECT TEXT
FROM USER_SOURCE
WHERE NAME =UPPER('nume_subprogram');
Eroarea apărută la compilarea unui subprogram poate fi vizualizată folosind următoarea sintaxă:
SELECT LINE, POSITION, TEXT
FROM USER_ERRORS
WHERE NAME =UPPER('nume');
1. Să se declare o procedură într-un bloc PL/SQL anonim prin care să se introducă în tabelul
emp_*** o nouă înregistrare de forma: employee_id, last_name, email, hire_date, job_id
(procedură locală).
DECLARE
PROCEDURE p1
(v_cod emp_***.employee_id%TYPE,
v_nume emp_***.last_name%TYPE,
v_email emp_***.email%TYPE,
v_data emp_***.hire_date%TYPE,
v_job emp_***.job_id%TYPE)
IS
BEGIN
INSERT INTO emp_***
(employee_id,last_name,email,hire_date, job_id)
VALUES (v_cod, v_nume, v_email, v_data, v_job);
END;

BEGIN
p1(700, 'Aly' , 'aly@k.ro', SYSDATE, 'economist');
END;
/
SELECT employee_id, last_name, email, hire_date, job_id
FROM emp_***;
ROLLBACK;
2. Să se creeze o procedură stocată care măreşte salariile angajaţilor ce îşi desfăşoară activitatea în
departamentul 10 cu o valoare dată ca parametru (procedură stocată cu parametru de tip IN).
SET SERVEROUTPUT ON
CREATE OR REPLACE PROCEDURE p2_***(val IN NUMBER)
AS
BEGIN
UPDATE emp_***
SET salary=salary+val
WHERE department_id=10;
END;
/
SELECT salary FROM emp_*** WHERE department_id=10;
EXECUTE p2_***(1000);
SELECT salary FROM emp_*** WHERE department_id=10;
ROLLBACK;
3. Să se creeze o procedură stocată care calculează salariul maxim al angajaţilor (procedură
stocată cu parametru de tip OUT).
CREATE OR REPLACE PROCEDURE p3_*** (sal OUT employees.salary%TYPE)
AS
BEGIN
SELECT MAX(salary)
INTO sal
FROM employees;
END;
/
VARIABLE val NUMBER
EXECUTE p3_*** (:val)
PRINT val
4. Să se creeze o procedură stocată care primeşte printr-un parametru codul unui angajat şi
returnează prin intermediul aceluiaşi parametru codul managerului corespunzător acelui angajat
(procedură stocată cu parametru de tip IN OUT).
VARIABLE ang_man NUMBER
BEGIN
:ang_man:=200;
END;
/
PRINT ang_man
CREATE OR REPLACE PROCEDURE p4_*** (nr IN OUT NUMBER)
IS
BEGIN
SELECT manager_id
INTO nr
FROM employees
WHERE employee_id=nr;
END;
/
EXECUTE p4_*** (:ang_man)
PRINT ang_man
5. Să se creeze o funcţie stocată care determină numărul de salariaţi din employees angajaţi în
2000, într-un departament dat ca parametru. Să se apeleze această funcţie:
a. printr-o variabilă de legătură;
b. folosind comanda CALL;
c. printr-o comandă SELECT;
d. într-un bloc PL/SQL.

CREATE OR REPLACE FUNCTION


f5_***(v_dept employees.department_id%TYPE)
RETURN NUMBER
IS
rezultat NUMBER;
BEGIN
SELECT COUNT(*) INTO rezultat FROM employees
WHERE department_id=v_dept
AND TO_CHAR(hire_date,'yyyy')=2000;
RETURN rezultat;
END f5_***;
/
a.
VARIABLE nr NUMBER
EXECUTE :nr := f5_***(80);
PRINT nr
b.
VARIABLE nr NUMBER
CALL f5_***(50) INTO :nr;
PRINT nr
c.
SELECT f5_***(80)
FROM dual;
d.
DECLARE
nr NUMBER;
BEGIN
nr := f5_***(80);
DBMS_OUTPUT.PUT_LINE('numarul salariatilor angajati in 2000 in
departamentul 80 este '|| nr);
END;
/
6. Să se creeze o procedură stocată care pentru un anumit cod de departament (dat ca parametru)
calculează prin intermediul unor funcţii locale numărul de salariaţi care lucrează în el şi numărul
managerilor salariaţilor care activează în departamentul respectiv.
CREATE OR REPLACE PROCEDURE p6_***
(v_dept employees.department_id%TYPE) AS
FUNCTION nr_sal
RETURN NUMBER IS
v_numar NUMBER(3);
BEGIN
SELECT COUNT(*) INTO v_numar
FROM employees
WHERE department_id = v_dept;
RETURN v_numar;
END nr_sal;

FUNCTION nr_mgr
RETURN NUMBER IS
v_numar NUMBER(3);
BEGIN
SELECT COUNT(DISTINCT manager_id)INTO v_numar
FROM employees
WHERE department_id = v_dept;
RETURN v_numar;
END nr_mgr;
BEGIN
DBMS_OUTPUT.PUT_LINE('Nr sal din '||v_dept||' este '|| nr_sal);
DBMS_OUTPUT.PUT_LINE('Nr man din '||v_dept||' este '|| nr_mgr);
END;
/
EXECUTE p6_***(80);
7. Să se calculeze recursiv factorialul unui număr dat (recursivitate).
CREATE OR REPLACE FUNCTION factorial_***(n NUMBER)
RETURN INTEGER IS
BEGIN
IF (n=0) THEN
RETURN 1;
ELSE
RETURN n*factorial_***(n-1);
END IF;
END factorial_***;
/
VARIABLE nr NUMBER
EXECUTE :nr := factorial_***(3);
PRINT nr
8. Să se afişeze numele şi salariul angajaţilor al căror salariu este mai mare decât media tuturor
salariilor din tabelul employees.
CREATE OR REPLACE FUNCTION medie_***
RETURN NUMBER IS
rezultat NUMBER;
BEGIN
SELECT AVG(salary)
INTO rezultat
FROM employees;
RETURN rezultat;
END;
/
SELECT last_name,salary
FROM employees
WHERE salary >= medie_***;

Exerciţii
1. Să se creeze o procedură stocată care măreşte salariile angajaţilor care nu au comision din
tabelul emp_*** cu o valoare dată ca parametru.

2. Să se declare o procedură locală prin care să se introducă în tabelul dept_*** o nouă înregistrare.

3. Să se creeze o funcţie stocată care determină numărul de salariaţi care au fost angajaţi după un
salariat al cărui cod este dat ca parametru. Să se apeleze această funcţie într-un bloc PL/SQL.

4. Să se creeze o procedură stocată care pentru un anumită grilă de salarizare (dată ca parametru)
calculează prin intermediul unor funcţii locale numărul de salariaţi care au salariul în grila
respectivă şi media salariilor câştigate de aceştia.

5. Să se calculeze recursiv al 10-lea termen al progresiei geometrice 1, 3, 9, 27….

6. Scrieţi o funcţie care să întoarcă, pentru un angajat dat prin id-ul său, comisionul exprimat în $.
Utilizaţi apoi această funcţie într-o comandă SELECT care să întoarcă numele angajaţilor, salariul şi
comisionul în $ al fiecăruia.

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