Sunteți pe pagina 1din 7

Facultatea de Cibernetic, Statistic i Informatic Economic SGBD Oracle seminarul 8

Subprograme PL/SQL

Blocuri PL/SQL care au nume Pot fi proceduri /functii Se pot stoca la nivel de Oracle Server (proceduri/functii stocate) sau de aplicatie (Developer Suite) Se pot grupa in pachete de programe (PACKAGE) Variabilele declarate in zona declarativa a procedurii se numesc parametri formali (formal parameters). Pentru acestia se pot specifica valori implicite (DEFAULT) Variabilele utilizate in apelul procedurii/functiei se numesc parametri actuali (actual parameters) Cnd procedura/functia e apelata, variabilele din procedura sunt incarcate cu valorile variabilelor definite in zona declarativa a blocului anonim In corpul procedurilor/functiilor nu se pot utiliza variabile globale sau de substitutie, acestea vor fi transmise in subprograme cu ajutorul parametrilor Pentru afisarea erorilor aparute la compilare se utilizeaza SHOW ERRORS

1. PROCEDURI
Parametrii utilizati in procedura (parametri formali) pot fi de tip: IN (valoarea parametrului actual este transferata in variabila definita in procedura. Aceasta variabila este considerata read-only). Cnd procedura se ncheie, controlul revine mediului apelant. Parametrul actual nu se modifica. Este modul implicit. OUT (valoarea parametrului formal este transferata in parametrul actual cnd procedura se incheie) IN OUT (valorile sunt transferate de la un tip de variabil la cellalt (la lansarea n execuie/terminarea procedurii)) un parametru IN poate apare numai n partea dreapta a (:=) un parametru OUT poate apare numai n partea stnga a (:=) un parametru IN OUT poate apare n ambele pri ale (:=)

Sintaxa pentru crearea unei proceduri: CREATE [OR REPLACE] PROCEDURE NUME_PROC [(param1 [IN|OUT|IN OUT] TIP1, Param2[IN|OUT|IN OUT] TIP2, ....) ] -- tipul variabilelor este precizat fara dimensiune (ex: NUMBER sau VARCHAR2) IS|AS -- zona de declarare a variabilelor utilizate in subprogram -- NU se utilizeaza DECLARE BEGIN ---[EXCEPTION] -----END [NUME_PROC]; Pentru a sterge procedura: DROP PROCEDURE NUME_PROC;
1

Facultatea de Cibernetic, Statistic i Informatic Economic SGBD Oracle seminarul 8

Apelul unei proceduri se poate realiza in urmatoarele moduri: prin nume dintr-un bloc PL/SQL anonim sau un alt subprogram; prin apel direct cu EXECUTE nume_proc sau EXEC nume_proc sau CALL nume_proc; din alt mediu Oracle (Oracle Developer Suite) Parametrii de tip IN Exemplu: Procedura modifica_salariul primete doi parametrii: p_id_angajat i procent i majoreaz cu procentul specificat salariul angajatului cu id_angajat=p_id_angajat: CREATE OR REPLACE PROCEDURE modifica_salariul_procent (p_id_angajat IN angajati.id_angajat%type, procent IN number) IS v_salariul angajati.salariul%type; BEGIN Select salariul into v_salariul from angajati where id_angajat=p_id_angajat; dbms_output.put_line('Angajatul are salariul de '||v_salariul); Update angajati Set salariul=salariul*(1+procent/100) Where id_angajat=p_id_angajat; Select salariul into v_salariul from angajati where id_angajat=p_id_angajat; Dbms_output.put_line('Angajatul are acum salariul de '||v_salariul); END; / show errors; EXECUTE modifica_salariul_procent(176, 10) Rollback; Parametrii de tip OUT Exemplu: Procedura primete ca parametru de tip IN id_ul unui angajat i returneaz prin parametrii de tip OUT numele i salariul acestuia: CREATE OR REPLACE PROCEDURE cauta_angajat (p_id_angajat IN angajati.id_angajat%type, p_nume OUT angajati.nume%type, p_salariul OUT angajati.salariul%type) IS BEGIN Select nume, salariul into p_nume, p_salariul from angajati where id_angajat=p_id_angajat; DBMS_OUTPUT.PUT_LINE(' Angajatul '||p_nume||' are salariul de: '||p_salariul); END; / --apelul procedurii intr-un bloc anonim SET SERVEROUTPUT ON DECLARE v_nume angajati.nume%type;
2

Facultatea de Cibernetic, Statistic i Informatic Economic SGBD Oracle seminarul 8

v_salariul angajati.salariul%type; BEGIN Cauta_angajat(150, v_nume, v_salariul); END; / Exemplu: Procedura calculeaz salariul mediu i l returneaz printr-un parametru de tip OUT: CREATE or REPLACE PROCEDURE sal_mediu (p_sal_mediu OUT number) IS BEGIN Select AVG(salariul) into p_sal_mediu from angajati; END; / show errors; --apelul prin EXECUTE VARIABLE v_sal_mediu NUMBER EXECUTE sal_mediu(:v_sal_mediu) Print v_sal_mediu Parametrii de tip IN OUT Exemplu: Procedura modific salariul unui angajat doar n cazul n care este mai mic dect media prin apelarea procedurii create mai sus, MODIFICA_SALARIUL_PROCENT. Procedura primete id-ul angajatului ca parametru de intrare i salariul mediu actual i prin returneaz prin parametrul de tip IN OUT salariul mediu modificat prin apelul procedurii SAL_MEDIU. CREATE or REPLACE PROCEDURE modifica_salariul_med (p_id_angajat IN angajati.id_angajat%type, p_sal_mediu IN OUT number) IS nume angajati.nume%type; sal angajati.salariul%type; BEGIN Select nume, salariul into nume, sal from angajati where id_angajat= p_id_angajat; IF sal<p_sal_mediu then MODIFICA_SALARIUL_PROCENT (p_id_angajat, 15); END IF; SAL_MEDIU (p_sal_mediu); End; / Apelul procedurii intr-un bloc anonim: SET SERVEROUTPUT ON DECLARE v_id_angajat angajati.id_angajat%type; v_nume angajati.nume%type;
3

Facultatea de Cibernetic, Statistic i Informatic Economic SGBD Oracle seminarul 8

v_salariul angajati.salariul%type; v_sal_mediu number; BEGIN --apelul cu id valid =105 v_id_angajat:=105; --apelul procedurii pentru vizualizarea datelor angajatului CAUTA_ANGAJAT(v_id_angajat, v_nume, v_salariul); --apelul procedurii pentru aflarea salariului mediu SAL_MEDIU (v_sal_mediu); DBMS_OUTPUT.PUT_LINE('Salariul mediu este acum: '||v_sal_mediu); --apelul procedurii pentru modificarea salariului modifica_salariul_med (v_id_angajat, v_sal_mediu); CAUTA_ANGAJAT(v_id_angajat, v_nume, v_salariul); --apelul cu id invalid v_id_angajat:=1230; CAUTA_ANGAJAT(v_id_angajat, v_nume, v_salariul); modifica_salariul_med (v_id_angajat, v_sal_mediu); Exception When NO_DATA_FOUND then DBMS_OUTPUT.PUT_LINE('Angajat inexistent! ID invalid'); END; / rollback; Stergerea unei proceduri se realizeaza prin comanda: DROP PROCEDURE nume_procedura; Vizualizarea procedurilor in dictionarul metadatelor se realizeaza prin: Select object_name From user_objects Where object_type='PROCEDURE'; Iar pentru a vizualiza corpul procedurii: Select text From user_source Where name='NUME_PROC' and type='PROCEDURE';

2. FUNCII:
Sintaxa pentru crearea unei functii: CREATE [OR REPLACE] FUNCTION nume_functie [(param1 [IN] TIP1, Param2[IN] TIP2, ....) ]
4

Facultatea de Cibernetic, Statistic i Informatic Economic SGBD Oracle seminarul 8

RETURN TIP_DATA -- tipul variabilelor este precizat fara dimensiune (ex: NUMBER sau VARCHAR2) IS|AS -- zona de declarare a variabilelor utilizate in subprogram -- nu se utilizeaza DECLARE BEGIN ---RETURN VALOARE; [EXCEPTION] -----END [NUME_FUNCTIE]; Pentru vizualizarea tipului returnat se utilizeaza: DESCRIBE nume_functie; Pentru a sterge functia: DROP FUNCTION nume_functie; Exemplu: Returneaz true/false daca salariatul are salariul mai mare/mai mic sau egal cu salariul mediu si null daca salariatul nu exista CREATE OR REPLACE FUNCTION verifica_salariul (p_id_angajat IN angajati.id_angajat%type, p_sal_mediu IN number) RETURN Boolean IS v_salariul angajati.salariul%type; BEGIN SELECT salariul into v_salariul from angajati where id_angajat=p_id_angajat; IF v_salariul > p_sal_mediu then return true; ELSE return false; end if; EXCEPTION WHEN no_data_found THEN return NULL; end; / show errors -- vizualizarea tipului returnat:
describe verifica_salariul;

--apelul functiei: SET SERVEROUTPUT ON DECLARE v_sal_mediu number; BEGIN --apelul procedurii pentru calculul salariului mediu: SAL_MEDIU (v_sal_mediu);
5

Facultatea de Cibernetic, Statistic i Informatic Economic SGBD Oracle seminarul 8

--primul apel al functiei IF (verifica_salariul(11, v_sal_mediu) IS NULL) then dbms_output.put_line('Angajat cu ID invalid!'); elsif (verifica_salariul(11, v_sal_mediu)) then dbms_output.put_line('Salariatul are salariul mai mare decat media!'); else dbms_output.put_line(' Salariatul are salariul mai mic decat media!'); end if; --al doilea apel IF (verifica_salariul(110, v_sal_mediu) IS NULL) then dbms_output.put_line('Angajat cu ID invalid!'); elsif (verifica_salariul(110, v_sal_mediu)) then dbms_output.put_line('Salariatul are salariul mai mare decat media!'); else dbms_output.put_line(' Salariatul are salariul mai mic decat media!'); end if; --al treilea apel IF (verifica_salariul(104, v_sal_mediu) IS NULL) then dbms_output.put_line('Angajat cu ID invalid!'); elsif (verifica_salariul(104, v_sal_mediu)) then dbms_output.put_line('Salariatul are salariul mai mare decat media!'); else dbms_output.put_line(' Salariatul are salariul mai mic decat media!'); end if; END; / Utilizarea functiilor PL/SQL in expresii SQL Exemplu: CREATE OR REPLACE FUNCTION taxa (value IN NUMBER, proc IN NUMBER) RETURN NUMBER IS BEGIN RETURN (value*proc); END taxa; / --apelul funciei SELECT id_produs, cantitate, pret, taxa (pret, 0.19) as tva FROM rand_comenzi; Pot fi utilizate in toate clauzele SELECT: Exemplu: SELECT id_produs, cantitate, pret, taxa (pret, 0.19) FROM rand_comenzi
6

Facultatea de Cibernetic, Statistic i Informatic Economic SGBD Oracle seminarul 8

WHERE taxa(pret, 0.19)>(select avg(taxa(pret, 0.19)) from rand_comenzi) ORDER BY taxa(pret, 0.19) DESC; Observatii! Functiile utilizate in expresii SQL trebuie sa accepte doar parametrii de tip IN si sa returneze numai tipuri de date specifice PL/SQL. Functiile nu trebuie sa contina comenzi DML (update, delete, insert) sau comenzi DDL si nici comenzi pentru controlul tranzactiilor (commit, rollback) si nici nu trebuie sa apeleze alte subprograme care sa incalce aceste restrictii. Functiile apelate in cadrul expresiilor SQL pot fi continute in pachete. Exemplu: Apelul urmatoarei functii dintr-o instructiune SQL va returna o eroare: ORA04091: table [nume_tabela] is mutating, trigger/function may not see it CREATE OR REPLACE FUNCTION produs_nou (pret_min NUMBER) RETURN NUMBER IS BEGIN INSERT INTO produse values (1, 'cafea', 'kg', pret_min); RETURN (pret_min+100); END; / --apelul din instructiuni SQL: UPDATE produse SET pret_min= produs_nou(2000) WHERE id_produs=111; Stergerea unei functii se realizeaza utilizand comanda: DROP FUNCTION nume_functie; Vizualizarea functiilor in dictionarul metadatelor se realizeaza prin: Select object_name From user_objects Where object_type='FUNCTION'; Iar pentru a vizualiza corpul functiei: Select text From user_source Where name='NUME_FUNCTIE' and type=' FUNCTION ' ORDER BY line; Exemplu: Select text From user_source Where name='TAXA' and type='FUNCTION' ORDER BY line;