Sunteți pe pagina 1din 43

Introducere in PL/SQL

Florin Vasilache Specializarea: MSR

Cuprins
Introducere in PL/SQL.............................................................................................1 Cuprins................................................................................................................... 2 Introducere............................................................................................................. 4 1.1 Definirea mediului PL/SQL............................................................................4 1.2 Caracteristici generale:.................................................................................5 Blocuri PL/SQL........................................................................................................5 2.1 Componentele unui bloc PL/SQL....................................................................5 2.3 Operatori in PL/SQL.......................................................................................6 Operator........................................................................................................... 6 2.4 Funcii SQL suportate n PL/SQL....................................................................7 2.5 Comenzi SQL suportate n PL/SQL.................................................................7 VARIABILE............................................................................................................... 8 3.1 Declarare i iniializare..................................................................................8 3.2 Tipuri de variabile:........................................................................................8 3.3 Atributul %TYPE.............................................................................................9 ..........................................................................................................................10 3.4 Variabile de mediu sau variabile de legtur ale aplicaiilor gazd (BIND VARIABLES)....................................................................................................... 10 3.5 Variabile de substituie................................................................................11 STRUCTURI FUNDAMENTALE DE PROGRAMARE.................................................11 4.1 Structuri alternative ...................................................................................11 4.2 Structuri repetitive......................................................................................13 4.3 Tipuri de date compuse...............................................................................14 CURSORUL N PL/SQL............................................................................................15 5.1 CURSORUL IMPLICIT....................................................................................16 5.2 CURSORUL EXPLICIT ...................................................................................16 5.3 Gestiunea implicit a cursorului prin utilizarea unui ciclu FOR....................18 5.4 Utilizarea unui cursor direct n cadrul instruciunii FOR...............................18 5.5 Utilizarea cursorului cu parametru..............................................................19 TRATAREA EXCEPIILOR.......................................................................................21 6.1 Tipuri de excepii.........................................................................................21 6.2 Tratarea excepiilor predefinite ale Serverului Oracle.................................22 6.3 Tratarea excepiilor non-predefinite Oracle Server.....................................23 6.4 Tratarea excepiilor definite de utilizator....................................................24 2

6.5 Propagarea excepiilor................................................................................25 Subprograme PL/SQL............................................................................................26 7.1 Proceduri..................................................................................................... 26 7.2 Functii......................................................................................................... 28 7.3 Pachete de subprograme............................................................................29 7.4 Supraincarcarea subprogramelor................................................................30 Triggeri pe baza de date......................................................................................31 8.1 Clauzele INSERTING, UPDATING, DELETING................................................32 8.2 Clauza INSTEAD OF.....................................................................................33 8.3 Gestiunea triggerilor: .................................................................................34 Aplicatie................................................................................................................ 35

Introducere
SQL (Structured Query Language - Limbaj Structurat de Interogare) este un limbaj de programare specific pentru manipularea datelor in sistemele de manipulare a bazelor de date relationale (RDBMS), iar la origine este un limbaj bazat pe algebra relationala. Acesta are ca scop inserarea datelor, interogatii, actualizare si stergere, modificarea si crearea schemelor, precum si controlul accesului la date. A devenit un standard n domeniu (standardizat ANSIISO), fiind cel mai popular limbaj utilizat pentru creearea, modificarea, regsirea i manipularea datelor de ctre SGBD-urile (Sistemele de Gestiune a Bazelor de Date) relaionale. Pe lng versiunile standardizate ale limbajului, exist o mulime de dialecte i variante, unele proprietare, fiind specifice anumitor SGBD-uri i de asemenea coninnd extensii pentru a suporta SBD-urile (Sistemele de Baze de Date) obiectuale (obiectualrelaionale). SQL permite att accesul la coninutul bazelor de date, ct i la structura acestora.

1.1 Definirea mediului PL/SQL


Utilizarea SQL pentru manipularea datelor are anumite limite, mai ales atunci cnd sunt necesare prelucrri complexe. n acest scop Oracle a creat mediul propriu de dezvoltare a aplicaiilor, PL/SQL, care permite definirea unor blocuri de prelucrare individual a nregistrrilor din tabele. PL/SQL este software de dezvoltare a aplicaiilor care ofer faciliti avansate cum ar fi ncapsularea datelor, interceptarea i tratarea excepiilor, utiliznd programarea orientat pe obiecte. Ofer toate construciile procedurale disponibile n generaia 3-a de limbaje de programare (3GL). Un bloc PL/SQL conine instruciuni executate procedural i instruciuni SQL. Motorul PL/SQL transmite procedurile unui modul de execuie, iar instruciunile SQL sunt transmise, individual bazei de date Oracle. Motorul PL/SQL poate fi n baza de date sau poate funciona pe un server de aplicaii separat.

Figura 1 - Funcionarea mediului PL/SQL Principalele avantaje ale PL/SQL sunt: Integrarea construciilor procedurale cu SQL
4

Creterea performanelor prin nglobarea ntr-un singur bloc a mai multor instruciuni SQL. Aplicaia poate trimite blocul o singur dat ctre baza de date sau ctre serverul de aplicaii, reducnd semnificativ traficul n reea i numrul de apeluri ctre baza de date. Modularizarea programelor prin utilizarea de blocuri de program care pot fi secveniale sau mbricate. Este integrat n uneltele de dezvoltare Oracle, cum sunt Oracle Forms i Oracle Reports. Portabilitate Modulele PL/SQL pot fi executate pe toate platformele n care sunt instalate baze de date Oracle (WINDOWS, LINUX, UNIX). Se pot crea biblioteci de programe reutilizabile pe orice platform. Suport toate tipurile de date din SQL (cu cteva extensii), precum i toate funciile SQL. Interceptarea eficient a erorilor.

1.2 Caracteristici generale:


Construciile PL/SQL conin structuri de control procedurale i comenzi descriptive SQL; PL/SQL este un limbaj procedural structurat pe bloc, programele putnd fi mprite n blocuri logice; Blocurile PL/SQL sunt procesate de motorul PL/SQL care poate fi rezident pe ORACLE SERVER sau pe un instrument de dezvoltare (ex.: Oracle Forms, Reports, JDeveloper etc.); Multe instrumente ORACLE au propriul motor PL/SQL (ex.: Oracle Forms, Reports, JDeveloper etc.); Tipurile de date din SQL pot fi folosite n PL/SQL; Programarea n PL/SQL este modularizat se utilizeaz blocurile care grupeaz instruciunile.

Blocuri PL/SQL
Orice unitate PL/SQL conine unul sau mai multe blocuri, complet separate sau imbricate.

2.1 Componentele unui bloc PL/SQL


Un bloc PL/SQL este compus din pn la 3 seciuni: declarativ (opional), executabil (obligatorie) i de tratare a excepiilor (opional). DECLARE (Opional) variabile, cursori, excepii BEGIN (Obligatoriu) comenzi SQL (asigur accesul la baza de date) structuri de programare procedural PL/SQL EXCEPTION (Opional) aciuni ce se execut cnd apare o eroare END; (Obligatoriu) Observaii: comenzile SQL asigur accesul la baza de date;
5

operaiile efectuate cu variabilele PL/SQL n cadrul instruciunilor procedurale nu presupun accesarea bazei de date; se folosete (;) dup fiecare instruciune SQL sau instruciune de control PL/SQL; blocul PL/SQL se termin cu (;); se folosete (/) pentru a lansa un bloc anonim n bufferul SQL; o eroare n PL/SQL este tratat ca o excepie;

2.2 Tipuri de blocuri PL/SQL:


Blocuri anonime; Funcii stocate i funcii de aplicaii; Proceduri stocate i proceduri de aplicaii; Pachete; Declanatoare (triggeri) pe baza de date / de aplicaii.

Blocurile anonime sunt nedenumite, nu sunt stocate in baza de date. Acestea se declara inline, in locul in care se doreste executia lor si se executa in momentul rularii. Blocurile anonime imbricate constau in imbricarea mai multe blocuri si se pot eticheta cu <<eticheta_bloc>> , iar variabilele din cadrul blocurilor se pot utiliza astfel: eticheta_bloc.variabila. Procedurile si functiile sunt blocuri PL/SQL cu un nume. Acestea se pot stoca la nivel de ORACLE SERVER(proceduri/funcii stocate) sau la nivel de aplicaie (DEVELOPER Forms si Reports). Pachete de programe - grupeaz proceduri, funcii. Declanatori pe baza de date - blocuri PL/SQL asociate tabelelor (de baz sau virtuale) i lansate automat n execuie cnd are loc o comanda de manipulare. Declanatori de aplicaie - blocuri PL/SQL asociate unor evenimente din cadrul aplicaiei (de exemplu: deplasarea mouse-ului, apsarea unui buton) i lansate n execuie automat.

2.3 Operatori in PL/SQL


Operator +, -, *, /, ** (op. exponenial) AND, OR, NOT <, >, =, >=, <=, <>, != BETWEEN ... AND ... IN(list) LIKE IS NULL || @ & sau && := Caracteristici Operatori aritmetici Operatori logici Operatori de comparaie Operator de verificare a apartenenei la un interval Operator de verificare a apartenenei la o list de valori Operator de comparare cu un ablon % - oricte caractere; _ - un caracter; Operator care verific dac o variabil are valoarea NULL Operator de concatenare Operator de conectare la distan Operatori pentru adresarea variabilelor de substituie Operator de atribuire

2.4 Funcii SQL suportate n PL/SQL


n cadrul instruciunilor descriptive sunt suportate toate tipurile de funcii SQL (inclusiv funciile de grup n cadrul instruciunii SELECT); Instruciunile PL/SQL: Suport funcii la nivel de nregistrare (single-row): numerice, caracter, data, de conversie etc.; Nu suport funcii de grup (SUM, MIN, MAX, AVG, COUNT, STDDEV) sau funcia DECODE. De exemplu nu se pot utiliza construcii de forma: IF DECODE(...) THEN ... sau IF AVG(...) THEN ...

Conversii n blocurile PL/SQL PL/SQL convertete tipurile de date dinamic (de exemplu: o valoare numeric la o variabil char); conversii implicite: caracter <-> numeric si caracter <->data; conversii explicite: se utilizeaz funciile TO_DATE, TO_NUMBER, TO_CHAR.

2.5 Comenzi SQL suportate n PL/SQL

PL/SQL permite folosirea comenzilor de manipulare a datelor (LMD): SELECT INSERT UPDATE DELETE PL/SQL permite folosirea comenzilor de control al tranzaciilor: COMMIT ROLLBACK SAVEPOINT

Not: Un bloc PL/SQL nu este o tranzacie. Comenzile Commit/ Rollback/ Savepoint sunt independente de bloc, dar pot s apar n cadrul acestuia. PL/SQL NU suport comenzile de definire a datelor (LDD) CREATE ALTER DROP RENAME TRUNCATE PL/SQL NU suport comenzile din cadrul limbajului pentru controlul datelor (Data Control Language - DCL) GRANT REVOKE

VARIABILE
3.1 Declarare i iniializare
Declararea variabilelor se realizeaz n zona declarativ (delimitat prin DECLARE) a blocului (sau sub-blocului) iar iniializarea se poate face la declarare sau n zona de execuie (ntre BEGIN i END). Variabilele vor fi vizibile n restul blocului, respectiv i n blocurile incluse n el, mai puin n sub-blocurile n care numele lor este redefinit (ca n majoritatea limbajelor de programare structurate, semnificaia unui nume definit de utilizator ntr-un bloc/sub-bloc este dat de cea mai apropiat declaraie anterioar locului folosirii). Toate variabilele PL/SQL au un tip de dat, restricii i un ir valid de valori; Declararea si initializarea se face astfe: nume_variabila [CONSTANT] TIP_DATA [NOT NULL] [:= | DEFAULT expresie] _Constantele trebuie obligatoriu iniializate, iar ulterior nu i vor putea schimba valoarea; variabilele NOT NULL trebuie obligatoriu iniializate, iar ulterior nu vor putea primi valoarea NULL;

3.2 Tipuri de variabile:


Variabile PL/SQL Scalare Compozite Referin LOB (Large Objects): NCLOB, CLOB, BLOB, BFILE Obiect Tipurile scalare conin valori simple (o variabila scalar poate conine la un moment dat o singur valoare simpl) i corespund n principal tipurilor pe care le pot avea coloanele tabelelor. char (lung_max) - lungime fix de max 32.767 bytes varchar2 (lung_max) lungime variabil de max 32.767 bytes long [ir de caractere de lungime variabil 2GB] number (precizie,scal) boolean (true, false, null) date binary_integer i pls_integer (numere ntregi ntre -2147483647 i 2147483647) binary_float i binary_double (pentru numere reale n varianta Oracle 10g) timestamp (pentru fraciuni de secund) Afiarea variabilelor PL/SQL se realizeaz prin intermediul funciei PUT_LINE din pachetului DBMS_OUTPUT. Se poate utiliza operatorul de concatenare ( || ) pentru a afia mai multe mesaje sau variabile pe aceeai linie. DBMS_OUTPUT.PUT_LINE ('VALOAREA VARIABILEI ESTE:' ||variabila); Popularea variabilelor cu valori din tabelele bazei de date
8

Se utilizeaz comanda SELECT cu clauza INTO pentru popularea variabilelor PL/SQL cu valori ale atributelor din tabele; cererile SELECT din cadrul blocurilor PL/SQL trebuie s furnizeze o singur linie rezultat (n caz contrar se semnaleaz eroare).

Exemplul de mai jos este replicat pe baza tabelelor realizate si mentionate la sfarsitul lucrarii. In acest caz am creat un bloc anonim in care rezultatul unei operatii efectuate asupra bazei de date Clienti este stocat intr-o variabila de tip varchar2:

3.3 Atributul %TYPE


Atributul %TYPE atribuie unei variabile tipul altei variabile sau tipul de date specific unei coloane din tabel. Declararea unei variabile cu %TYPE: variabila sau variabila1 variabila2 tabel.nume_coloan%TYPE; tip_dat; variabila1%TYPE;

3.4 Variabile de mediu sau variabile de legtur ale aplicaiilor gazd (BIND VARIABLES)
sunt variabile de legtur cu aplicaia n care ruleaz motorul PL/SQL; trebuie declarate n aplicaie (n mediul gazd) i pot fi accesate i modificate n cadrul blocurilor PL/SQL; dup terminarea execuiei blocului PL/SQL, variabila rmne n mediul gazd cu valoarea primit n urma rulrii blocului (i poate fi pasat altui bloc, realiznd astfel transmiterea de valori ntre blocurile PL/SQL); nu pot fi utilizate n cadrul procedurilor, funciilor sau pachetelor; se declar n afara blocului PL/SQL cu ajutorul cuvntului cheie VARIABLE: VARIABLE g_numevariabil TIP pentru declararea unei variabile host de tip NUMBER nu se specific precizia i scala; pentru utilizarea lor n cadrul unui bloc PL/SQL sau ntr-o fraz SQL din afara blocului se prefixeaz cu : :host_variabila:=v_variabila; se afieaz n afara blocului cu ajutorul comenzii PRINT (la afiare variabila nu se va prefixa cu :) PRINT numevariabila

10

3.5 Variabile de substituie


de regul, variabilele de substituie sunt folosite pentru a transmite valori dinspre mediul SQL*Plus spre comenzile SQL sau blocurile PL/SQL, n timp ce variabilele de legtur (bind variables) sunt folosite pentru a transmite valori n sens invers sau pentru a transfera valori ntre blocuri PL/SQL lansate succesiv (primul bloc seteaz variabila, urmtorul o consult); prin variabile de substituie se pot transmite valori comenzilor SQL sau blocurilor PL/SQL lansate (folosind "&" sau "&&"); se pot invoca din comenzile SQL sau din blocurile PL/SQL prin "&nume_variabila" sau "&&nume_variabila"; sunt locale sesiunii SQL n care au fost declarate; n mediul SQL variabilele de substituie pot fi uor citite prin introducerea de valori de la tastatur (utiliznd ACCEPT), se pot defini (cu DEFINE) sau afia pe ecran (cu PROMPT);

STRUCTURI FUNDAMENTALE DE PROGRAMARE


4.1 Structuri alternative
Structura IF..THEN..END IF IF cond1 THEN secvcom1 ELSE
11

secvcom2 END IF; IF cond1 THEN secvcom1 ELSE IF cond2 THEN secvcom2 END IF; END IF;

Structura CASE ... WHEN... THEN... Sunt 2 variante: expresii CASE (CASE Expressions) care intorc un rezultat intr-o variabila. Se termina cu END sintaxa CASE (CASE Statement) care executa o anumita instructiune. Se termina cu END CASE, iar fiecare rand se termina cu ; CASE Expressions: Variabila:= CASE [Selector]
12

WHEN expression1 THEN result1 WHEN expression2 THEN result2 ----------------------------------------WHEN expressionN THEN resultN [ELSE result N+1] END;

4.2 Structuri repetitive


Structura LOOPEND LOOP LOOP Secventa comenzi; EXIT [WHEN cond]; END LOOP; Structura WHILE..LOOP.END LOOP WHILE cond LOOP Secventa comenzi 1; Secventa comenzi 2; EXIT [WHEN cond]; END LOOP; Structura FOR..LOOP.END LOOP FOR var IN [REVERSE] valmin..valmax LOOP
13

Secventa comenzi; EXIT [WHEN cond]; END LOOP;

4.3 Tipuri de date compuse


Tipul RECORD Reprezint un grup de date logic corelate (de exemplu, datele despre un client: codc, nume, adresa sunt diferite ca tip dar corelate logic); Cnd se declar un PL/SQL record pentru aceste cmpuri, ele pot fi manipulate ca o unitate; Fiecare cmp (element al structurii) are un nume i un tip de dat; Cmpurile unui record sunt referite nume_record.nume_cmp.

TYPE nume_record IS RECORD TIP_DATA:=|DEFAULT valoare]...); Variabil NUME_RECORD;

(nume_cmp

TIP_DATA

[,nume_cmp

14

Pentru a defini un record pe baza coloanelor unei tabele se folosete %rowtype . In acest caz numele elementelor din record au acelai nume ca i coloanele tabelei, acelai tip de date i se gsesc n aceeai ordine. Tipuri de tabele INDEX BY TYPE nume_tab IS TABLE OF {TIP_DATA [variabila%type | tabela.coloana%type [NOT NULL]| tabela%rowtype} INDEX BY PLS_INTEGER|BINARY_INTEGER|VARCHAR2(dimensiune); v_tab nume_tab; Adresarea se realizeaz cu v_tab(index).cmp; Indexul este unic, dar n ordine aleatorie i poate fi negativ. Intervalul pt PLS_INTEGER este (-2147483647, 2147483647) Se pot utiliza urmatoarele proprieti i metode: v_tab.EXISTS(i) v_tab.COUNT v_tab. FIRST i v_tab.LAST v_tab. PRIOR(i) i v_tab.NEXT(i) v_tab.DELETE sau v_tab.DELETE(i) sau v_tab.DELETE(i,j)

CURSORUL N PL/SQL
Atunci cnd se execut o comand SQL, Oracle Server deschide o zon de memorie (context area) n care comanda este executat. Cursorul este un pointer ctre aceast zon n PL/SQL se utilizeaz dou tipuri de cursoare: implicit: declarat pentru toate instruciunile PL/SQL de tip LMD (INSERT/UPDATE/DELETE);

15

explicit: declarat i gestionat de programator.

5.1 CURSORUL IMPLICIT


este declarat de PL/SQL implicit pentru toate comenzile de manipulare a datelor (INSERT, UPDATE, DELETE); dac o instruciune LMD nu afecteaz nici o linie a tabelei nu se genereaz eroare, ns excepia trebuie tratat folosind atributele speciale ale cursorilor; atributele cursorului implicit: SQL%ROWCOUNT SQL%FOUND SQL%NOTFOUND

Exemplu: Se sterg intrari din tabelul Costuri si se contorizeaza numarul de randuri stere:

5.2 CURSORUL EXPLICIT


se folosete pentru a procesa individual fiecare linie (nregistrare) returnat de o instruciune SELECT ce returneaz mai multe nregistrri. mulimea nregistrrilor returnate de o instructiune SELECT este numit mulime rezultat. cursorul pstreaz un pointer ctre linia curent n cadrul unei mulimi rezultat. Verificarea strii unui cursor explicit se realizeaz prin intermediul urmtoarelor atribute:

16

nume_cursor%ISOPEN - evaluat la TRUE n cazul n care cursorul este deschis; nume_cursor %NOTFOUND - evaluat la TRUE n cazul n care cel mai recent FETCH nu a returnat nici o linie; nume_cursor %FOUND - complementul lui %NOTFOUND; nume_cursor %ROWCOUNT - are ca valoare numrul liniilor returnate pn n momentul curent. Prelucrarea cursorului explicit presupune parcurgerea urmtoarelor etape:

se declar variabilele n care vor fi ncrcate valorile corespunztoare unei linii din cursor; se declar cursorul explicit, specificndu-se un nume pentru acesta i definindu-se interogarea de procesat n cadrul lui: DECLARE nume_cursor IS SELECT........................;

se deschide cursorul prin intermediul instruciunii OPEN, care execut interogarea i legarea tuturor variabilelor referite. nregistrrile returnate de interogare sunt desemnate drept set activ de date, care pot fi de acum ncrcate. OPEN nume_cursor; utilizndu-se instruciunea FETCH, se ncarc linia curent din cursor n variabile. Fiecare ncrcare determin mutarea pointerului cursorului la linia urmtoare din setul activ de date. FETCH nume_cursor INTO var1, var2,..............;

este nchis cursorul prin instructiunea CLOSE, care dezafecteaz setul activ de linii. Cursorul poate fi din nou deschis pentru a stabili un nou set activ de linii. CLOSE nume_cursor; Pentru a procesa liniile unui cursor explicit se definete de obicei o bucl pentru executarea unui FETCH n fiecare iteraie. n final, toate liniile din setul activ sunt procesate i un FETCH executat fr succes poziioneaz atributul %NOTFOUND pe TRUE. naintea primului FETCH, %NOTFOUND se evalueaz la NULL, ca i n cazul n care FETCH nu se execut niciodat cu succes. Un exemplu de cursor explicit se poate observa in figura de mai jos in care un tabel nou creat este populat cu valori stocate in cursor:

17

5.3 Gestiunea implicit a cursorului prin utilizarea unui ciclu FOR


FOR nume_record IN nume_cursor LOOP -------------------------------------------------------END LOOP; n acest caz, tipul RECORD nu trebuie declarat. Se realizeaz n mod implicit deschiderea, ncrcarea i nchiderea cursorului.

5.4 Utilizarea unui cursor direct n cadrul instruciunii FOR


n acest caz cursorul nu este declarat, nu are nume, este reprezentat doar de interogarea SELECT din cadrul instruciunii FOR, astfel: FOR NUME_RECORD IN (SELECT......) LOOP
18

..................................................................................... END LOOP; Dezavantajul n acest caz este ca nu se pot utiliza atributele cursorului din cauza faptului c acesta nu are nume.

5.5 Utilizarea cursorului cu parametru


Pentru o flexibilitate mai mare se pot declara i utiliza cursori cu parametru care transmit valorile parametrilor actuali n cererile SQL. Declararea cursorului cu parametru se face astfel: Cursor nume_cursor (parametru1 tip_data,.....) Is select .................; Deschidere: Open nume_cursor(valoare_parametru1,......); Cursoarele parametrizate nu ofer o funcionalitate suplimentar ci doar o modalitate simpl i clar de a specifica valori de intrare. Tipurile parametrilor sunt scalare, dar nu li se precizeaz dimensiunea; ele fiind referite n interogare.

19

Actualizarea nregistrrilor returnate de cererea cursorului. Clauza FOR UPDATE

se blocheaz setul de nregistrri ale cursorului n 2 variante: NOWAIT i WAIT n:

CURSOR C IS SELECT .... FROM.... FOR UPDATE [OF COLUMN_NAME] [NOWAIT|WAIT n]; se adaug clauza FOR UPDATE n interogarea asociat cursorului pentru a bloca liniile afectate atunci cnd cursorul este deschis. clauza NOWAIT - determin apariia unei erori dac liniile sunt blocate de o alt sesiune. cnd mai multe tabele sunt implicate n interogare, se poate folosi FOR UPDATE pentru a impune blocarea liniilor unei tabele anume. Liniile unei tabele sunt blocate numai n cazul n care clauza FOR UPDATE face o referire la o coloan din acea tabel.

Pentru manipularea ct mai uoar a comenzilor LMD UPDATE i DELETE se poate utiliza clauza WHERE CURRENT OF care permite actualizarea nregistrrilor pe baza liniei curente din cursor. UPDATE tabela SET camp=.... WHERE CURRENT OF nume_cursor; se poate referi linia din tabela originar, pentru actualizare sau tergere, prin intermediul liniei curente a cursorului (cea procesat de ultima instruciune FETCH). clauza FOR UPDATE trebuie inclus n definiia cursorului pentru a bloca liniile n momentul execuiei instruciunii OPEN.

20

TRATAREA EXCEPIILOR
O excepie este un identificator PL/SQL asociat unei condiii anormale aprute n timpul execuiei unui bloc PL/SQL. Invocarea unei excepii are ca efect terminarea blocului, deci ieirea din blocul PL/SQL. Pentru evitarea unor situaii de ntrerupere anormal, excepia poate fi captat si poate fi specificat o rutin de tratare a acesteia. O excepie poate fi invocata in doua moduri: a. Apare o eroare Oracle si excepia asociata ei este automat invocat b. Excepia poate fi invocat n mod explicit prin instruciunea RAISE in cadrul blocului. Captarea unei excepii Daca excepia este invocat n seciunea executabil a unui bloc se caut n cadrul seciunii de tratare a excepiilor o rutin de tratare asociata. Daca PL/SQL poate trata excepia, ea nu este propagat n blocul exterior sau n mediul apelant, caz n care se consider c execuia blocului s-a desfurat cu succes.

Propagarea unei excepii Daca nu exist o rutin pentru tratarea ei, excepia este propagat n mediul apelant, caz n care execuia blocului se termin cu eec.

6.1 Tipuri de excepii


Sunt trei tipuri de excepii: Tipul Mod de manipulare

Excepii pre-definite asociate erorilor care apar cel mai Nu trebuie declarate, serverul Oracle le frecvent n blocurile PL/SQL (de exemplu invoc n mod automat, dar trebuie NO_DATA_ FOUND, TOO_MANY_ROWS, tratate n seciune EXCEPTION. INVALID_CURSOR, ZERO_DIVIDE) Excepii non-predefine recunoscute de Oracle dar tratate de utilizator cu ajutorul codului de eroare returnat (de exemplu ORA- 01400). Trebuie declarate n seciunea declarativ. Serverul Oracle le invoc n mod automat, dar trebuie tratate n seciune EXCEPTION.

Excepii definite de utilizator, asociate unor condiii Trebuie declarate n seciunea specifice de prelucrare (de exemplu cazul n care declarativ, invocate de ctre utilizator valoarea stocului unui anumit produs este zero) i tratate n seciunea EXCEPTION.

Tratarea tuturor excepiilor se realizeaz n seciunea EXCEPTION a blocurilor PL/SQL astfel: EXCEPTION
21

WHEN exception1 [OR exception2 ] THEN statement1 ; statement2 ; [WHEN exception3 [OR exception4 ] THEN statement1 ; statement2 ; ] [WHEN OTHERS THEN statement1 ; statement2 ; ]

6.2 Tratarea excepiilor predefinite ale Serverului Oracle


Acestea nu trebuie declarate, fiind definite de ctre Oracle Server si invocate implicit. Lista complet a excepiilor predefinite Oracle va fi consultat din PL/SQL Reference, capitolul 10, pagina 10-4. Cteva exemple de excepii predefinite sunt prezentate mai jos:

Numele NO_DATA_FOUND TOO_MANY_ROWS INVALID_CURSOR i CURSOR_ALREADY_ OPEN

Numrul erorii ORA-01403 ORA-01422 ORA-01001

Descriere O instruciune SELECT care ar fi trebuit sa ntoarc o singura linie nu a returnat nici o linie. O instruciune SELECT care ar fi trebuit sa ntoarc o singura linie a returnat mai multe linii. Apariia unei operaii ilegale asupra unui cursor (de exemplu ncercarea de a deschide un cursor deja deschis).

Exemplul de mai jos trateaza eroarea in cazul afisarii unui client pe baza identificatorului de circuit. In cazul in care CID-ul respectiv nu exista se va afisa: Nu exista circuit cu acest identificator!

22

6.3 Tratarea excepiilor non-predefinite Oracle Server


Se poate capta o eroare a Serverului Oracle ce nu are asociata o excepie predefinit asociindu-i un nume codului de eroare returnat sau folosind clauza WHEN OTHERS. In PL/SQL, directiva EXCEPTION_INIT determin compilatorul sa asocieze un nume de excepie unui numr (cod) de eroare standard a Serverului Oracle. Aceasta permite referirea erorii standard prin nume i scrierea unei rutine de tratare a ei. Tratarea acestor erori se realizeaz in 3 pai: 1) Declararea excepiei: se face n zona DECLARE a blocului NUME_EXCEPTIE EXCEPTION; 2) Asocierea codului erorii cu excepia declarat anterior: se realizeaz tot n zona DECLARE prin utilizarea directivei de compilare EXCEPTION_INIT: PRAGMA EXCEPTION_INIT(NUME_EXCEPTIE, COD_EROARE); Unde COD_EROARE este un cod de eroare standard Oracle; 3) Tratarea excepiei n zona EXCEPTION a blocului: EXCEPTION WHEN NUME_EXCEPTIE THEN .........; Se pot utiliza 2 atribute pentru a gestiona erorile aprute: SQLCODE returneaz codul numeric al erorii. Poate avea urmtoarele valori:
23

0 nu a aprut nici o excepie; 1 este o excepie definit de utilizator; +100 excepia NO_DATA_FOUND; un numr negativ o eroare Oracle Server; SQLERRM returneaz mesajul asociat erorii. Aceste atribute pot fi ncrcate n variabile i inserate ntr-o tabel de erori pentru vizualizare i verificare ulterioar. Exemplu: S se insereze n tabela Circuite un nou circuit cu ID-ul 555, fr a preciza Clientul. n acest caz va apare o eroarea cu codul ORA-01400 prin care programatorul este avertizat de nclcarea unei restricii de integritate. Aceast excepie poate fi tratat astfel:

6.4 Tratarea excepiilor definite de utilizator


In PL/SQL se pot defini excepii ale utilizatorului. Ele trebuie declarate n seciunea declarativa a blocului i invocate explicit prin instruciunea RAISE. Etape: 1. Se declara excepia n seciunea declarativ: nume_exceptie EXCEPTION;
2. Prin instruciunea RAISE se invoc n mod explicit, n cadrul seciunii executabile:

RAISE nume_exceptie; 3. Se trateaz n rutina corespunztoare din seciunea de tratare a excepiilor: WHEN nume_exceptie THEN......
24

Erorile definite de utilizator pot fi tratate la nivelul aplicaiilor ca i erorile Oracle Server prin atribuirea de coduri cu ajutorul funciei: RAISE_APPLICATION_ERROR (NR_EROARE, MESAJ); unde NR_EROARE poate fi un numr negativ cuprins ntre -20000 si -20999. In acest caz tratarea se realizeaz asemntor cu erorile non-predefinite Oracle Server. Exemplu: S se invoce o eroare n cazul n care utilizatorul ncearc s execute blocul PL/SQL dup ora 15:

6.5 Propagarea excepiilor


Odat excepia declanat n seciunea executabil a unui bloc, se caut n cadrul seciunii de tratare a excepiilor (EXCEPTION) o rutin de tratare asociat. Daca PL/SQL poate trata excepia, ea nu este propagat n blocul exterior sau n mediul apelant, caz n care se consider c execuia blocului s-a desfurat cu succes. Atunci cnd un sub-bloc trateaz o excepie, se termin normal iar execuia se reia n blocul ce-l cuprinde imediat dup instruciunea END a sub-blocului. Daca apare o excepie iar n blocul curent nu exist o rutin pentru tratarea sa, execuia blocului se termina cu eec, iar excepia se propag succesiv n blocurile exterioare pn este gsit ntr-unul din ele o rutin pentru tratarea ei. Daca nu se gsete nici una, n mediul
25

apelant apare o situaie de excepie nerezolvat, utilizator putnd observa mesajul de eroare care a ntrerupt execuia normal. Exemple de exceptii predefinite:

no_data_foundSingle row SELECT returned no data. too_many_rowsSingle row SELECT returned more than one row. invalid_cursorIllegal cursor operation was attempted. value_errorArithmetic, conversion, truncation, or constraint error occurred. invalid_numberConversion of a number to a character string failed. zero_divideAttempted to divide by zero. dup_val_on_indexAttempted to insert a duplicate value into a column that has a unique index. cursor_already_openAttempted to open a cursor that was previously opened. not_logged_onA database call was made without being logged into Oracle. transaction_backed_outUsually raised when a remote portion of a transaction is rolled back. login_deniedLogin to Oracle failed because of invalid username and password. program_errorRaised if PL/SQL encounters an internal problem. storage_errorRaised if PL/SQL runs out of memory or if memory is corrupted. timeout_on_resourceTimeout occurred while Oracle was waiting for a resource. value_errorArithmetic, conversion, truncation, or constraint error occurred. othersThis is a catchall. If the error was not trapped in the previous exception traps, the error will be trapped by this statement

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

7.1 Proceduri
Parametrii utilizati in procedura (parametri formali) pot fi de tip:
26

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; 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) In exemplul de mai jos procedura primete doi parametrii: CID i procent i majoreaz cu procentul specificat costul_lunar:

27

7.2 Functii
Sintaxa pentru crearea unei functii: CREATE [OR REPLACE] FUNCTION nume_functie [(param1 [IN] TIP1, Param2[IN] TIP2, ....) ] 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:
28

DESCRIBE nume_functie; Pentru a sterge functia: DROP FUNCTION nume_functie; 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. Ex. Functia de mai jos returneaza true/false daca circuitul are un cost de instalare mai mare de 1000 (Euro) si null daca circuitul nu exista:

7.3 Pachete de subprograme


Grupeaza variabile, subprograme, tipuri de date PL/SQL care sunt corelate logic. Sunt formate din 2 parti:
-

specificatia pachetului zona publica corpul pachetului zona privata

Specificatia pachetului:
29

CREATE [OR REPLACE] PACKAGE nume_pachet IS|AS --declaratii de variabile si tipuri publice, sunt initializate cu NULL implicit --specificatii ale subprogramelor publice END [nume_pachet];

Corpul pachetului: CREATE [OR REPLACE] PACKAGE BODY nume_pachet IS|AS --declaratii de variabile si tipuri private --definitii ale subprogramelor publice si private [BEGIN -- Este optional si se executa o singura data la primul apel si la incarcarea pachetului in memorie END [nume_pachet];

Observatie: In cadrul pachetelor pentru a utiliza o functie/procedura in cadrul unui subprogram, aceasta trebuie declarata inainte (principiul forward declarations); In zona de specificatii a pachetului se pot declara:
proceduri; funcii; variabile; cursoare; excepii.

Corpul pachetului defineste complet procedurile, functiile si cursoarele.

7.4 Supraincarcarea subprogramelor


Se poate realiza numai pentru functii/proceduri din cadrul pachetelor, nu si pentru

subprograme singulare (stocate direct in baza de date); Nu se pot supraincarca 2 subprograme care au paramentrii de tipuri asemanatoare (ex: NUMBER si DECIMAL sau VARCHAR2 si VARCHAR); Stergerea pachetului se realizeaza cu comenzile:
DROP PACKAGE nume_pachet; DROP PACKAGE BODY nume_pachet; 30

Vizualizarea specificatiilor pachetelor in dictionarul metadatelor se realizeaza prin: Select text From user_source Where name='NUME_PACHET' and type='PACKAGE' Iar pentru a vizualiza corpul pachetului: Select text From user_source Where name='NUME_PACHET' and type='PACKAGE BODY

Triggeri pe baza de date


Sunt asociati cu o tabela, view, schema sau database Sunt stocai n baza de date Se execut cnd are loc un eveniment. Tipuri de evenimente: operatii LMD pe o tabela (insert/ update/ delete) operatii LMD pe o tabela virtuala (view) cu clauza INSTEAD OF operatii LDD (Create, Alter, Drop) la nivel de database sau schema evenimente la nivelul schemei sau bazei de date (shutdown sau logon/off) Se folosesc pentru gestionarea restriciilor de integritate complexe, monitorizare,

centralizarea operatiilor. Nu se recomanda construirea in exces a triggerilor. Pentru fiecare trigger se stabilete: comanda care-l declaneaz (insert| update| delete) - Un trigger poate fi declanat de mai multe comenzi momentul de timp la care se declaneaz (before| after| instead of). Pentru view se utilizeaza instead of, actiunile DML vor fi inlocuite de corpul triggerului si vor fi afectate tabelele din care este construit view-ul. nivelul (row| statement) - dac triggerul este la nivel de rnd se execut pentru fiecare rnd afectat de comenzile: insert| update| delete. Daca nu este afectat nici un rand triggerul nu se executa. Dimensiunea unui trigger nu poate depasi 32 kb! Se poate include apelul unei proceduri in corpul triggerului pentru a micsora dimensiunea acestuia. Pentru a vedea erorile la compilare: SHOW ERRORS TRIGGER nume_trigger;
Sintaxa de creare a unui trigger:

CREATE [OR REPLACE] TRIGGER nume_trigger [BEFORE| AFTER| INSTEAD OF] [INSERT| [OR] | UPDATE [OF coloana,]| [OR] | DELETE]
31

ON tabela [FOR EACH ROW ] [WHEN conditie] corp_trigger Corp_trigger poate fi un bloc PL/SQL (BeginEnd) sau un apel de procedura. Procedura poate fi implementata in PL/SQL, C sau JAVA, iar apelul se realizeaza: CALL nume_proc (fara ; dupa numele sau!!!) Ex: Se creeaza un trigger care se declanseaza inaintea fiecarei operatii de inserare in tabela clienti: CREATE OR REPLACE TRIGGER clienti_trig BEFORE INSERT ON clienti BEGIN dbms_output.put_line('triggerul clienti s-a executat'); END; / commit;

8.1 Clauzele INSERTING, UPDATING, DELETING


Triggeri la nivel de rand FOR EACH ROW In triggerul la nivel de rnd se poate accesa rndul curent procesat folosind doua pseudorecords ( :old, :new). Tipul lor este: nume_tabela_pe_care_actioneaza_triggerul%ROWTYPE Valorile pentru :old si :new Operatie INSERT UPDATE DELETE Valoare pt Old NULL Valoare pt New valoarea noua, inserata

valoare veche, anterioara lui valoare noua, modificata update valoare veche, anterioara lui NULL delete

(:OLD) nu este definit pentru INSERT i (:NEW) nu e definit pentru DELETE Dei sintactic sunt tratate ca tip de dat record, n realitate ele nu sunt i operaiile de

atribuire directa var_record:=:old ce sunt valide pentru record nu sunt valide pentru (:new) i (:old). Din acest motiv trebuie precizate exact campurile din pseudo-record :old.camp sau :new.camp.
32

Nu se recomanda realizarea de triggeri la nivel de rind care utilizeaza valori ale coloanelor

din tabele si care sunt supuse actualizarilor prin comenzile DML ce declanseaza triggerul (mutating table). Va apare aceeasi eroare ca la functii. Utilizarea clauzei WHEN pentru a conditiona executia unui trigger: clauza [when condiie] este valid pentru triggerii la nivel de rnd corpul triggerului va fi executat numai pentru acele rnduri ce indeplinesc condiia specificat Exemplu: Se creeaza un trigger care nu permite depasirea unei limite maxime a costului de instalare per circuit.

8.2 Clauza INSTEAD OF


Sunt triggeri realizati doar pentru view-uri Se utilizeaza pentru actualizarea tabelelor din care este construit un view neactualizabil. Realizeaza operatii DML pe aceste tabele, iar Oracle Server declanseaza triggerii pe tabelele respective. Daca un view este actualizabil, triggerii respectivi se declanseaza automat. Sunt triggeri la nivel de rand.
33

Nu permit utilizarea clauzelor BEFORE|AFTER Comparatie intre triggeri si proceduri Trigger codul sursa: USER_TRIGGERS Sunt declansati implicit de DML Nu sunt permise comenzile: COMMIT, ROLLBACK, SAVEPOINT, insa pot contine un apel de procedura in care apar aceste comenzi, dar nu se recomanda Procedure codul sursa: USER_SOURCE Sunt apelate in mod explicit Sunt permise comenzile: COMMIT, ROLLBACK, SAVEPOINT

cnd un trigger e creat, codul surs al triggerului este stocat n dicionarul de date in

user_triggers si se poate afisa: SELECT trigger_type, trigger_name, triggering_event FROM user_triggers WHERE table_name='PRODUSE';

8.3 Gestiunea triggerilor:


Un trigger poate fi dezactivat

ALTER TRIGGER nume_trigger DISABLE|ENABLE; Sau: ALTER TABLE nume_tabela DISABLE|ENABLE ALL TRIGGERS; Comparatie intre triggeri si proceduri Trigger codul sursa: USER_TRIGGERS Sunt declansati implicit de DML Nu sunt permise comenzile: COMMIT, ROLLBACK, SAVEPOINT, insa pot contine un apel de procedura in care apar aceste comenzi, dar nu se recomanda Procedure codul sursa: USER_SOURCE Sunt apelate in mod explicit Sunt permise comenzile: COMMIT, ROLLBACK, SAVEPOINT

cnd un trigger e creat, codul surs al triggerului este stocat n dicionarul de date in

user_triggers si se poate afisa: SELECT trigger_type, trigger_name, triggering_event FROM user_triggers WHERE table_name='PRODUSE

34

Aplicatie
Sa se implementeze o baza de date numita Data_BD ce va contine trei table: Circuite, Clienti si Costuri. Acestea vor fi create astfel incat sa reflecte informatii referitoare la circuitele de date, clientii companiei si costurile asociate fiecarui circuit in parte. Cerinte:
Crearea celor 3 tabele mentionate mai sus si popularea acestora cu date asupra carora

se vor desfasura urmatoarele activitati.


Crearea unui nou tabel intitulat tabel_log in care inregistrarile (tip operatie, utilizator

executant, data curenta) sunt declansate la operatiile INSERT, DELETE sau UPDATE pe tabela CLIENTI.
Sa se implementeze o procedura care realizeaza un discount cu 10% a facturilor ce

depasesc valorea de 3000 (Euro).

35

36

37

Vizualizarea tabelelor dupa introducerea unui numar de date conform printscreenurilor de mai sus:

38

2. Cerinta a fost realizata prin utilizarea unui trigger ce se declanseaza inaintea unei operatii de inserare, actualizare sau stergere asupra tabelei Clienti si va popula tabelul nou creat tabel_log cu informatiile solicitate.

Testarea cerintei am facut prin efectuarea unor astfel de operatii de catre diferiti utilizatori asupra tabelei respective. Oferirea de privilegii asupra acestei baze de date catre alti utilizatori am facut prin comanda: grant All on "CLIENTI" to ANGAJAT_1,ANGAJAT_2;
39

Rezultatul este crearea unui tabel in care sunt logate toate operatiile efectuate asupra tabelului in cauza:

40

3 . Vizualizarea tabelului Costuri la momentul intial:

41

Pentru exemplificarea procedurii am executat comenzile de mai jos pentru doua circuite diferite. Se observa aplicarea discount-ului in cazul unei facturi de valoarea mai mare de 3000.

select "Factura_lunara" from costuri where CID=1111; execute modifica_factura_2(1111,10); commit; select "Factura_lunara" from costuri where CID=1111; select "Factura_lunara" from costuri where CID=6666; execute modifica_factura_2(6666,10); commit; select "Factura_lunara" from costuri where CID=6666;

42

43

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