Sunteți pe pagina 1din 37

37

Capitolul IV Limbajul PL/SQL


Generaliti
Limbajul SQL (Structured Query Language) este un limbaj declarativ orientat pe obinerea de mulimi de selecie ntr-o aplicaie n arhitectur client-server. Eficiena sa este remarcabil dar n cazul n care elementele unei mulimi de selecie trebuie accesate pe rnd, nu n grup, utilizarea sa nu mai este posibil. Pe de alt parte SQL nu ofer nici suportul necesar realizrii interfeei unei aplicaii. n contrast cu SQL, limbajele procedurale pot manipula linii individuale dintr-o mulime de selecie. Ele dispun de funcii care permit trecerea de la o linie la alta i ramificarea codului n funcie de rezultatul testrii valorilor preluate din tabelele bazei de date. Limbajul PL/SQL (Procedural Language extensions to SQL) a fost dezvoltat de compania Oracle ca extensie a limbajului declarativ SQL. PL/SQL este un limbaj de programare procedural care poate fi folosit pentru descrierea unor prelucrri complexe sau pentru programarea unor secvene de cod care trebuie executate automat la apariia unui eveniment (triggere). O caracteristic remarcabil a limbajului PL/SQL este faptul c procedurile sau funciile scrise vor fi memorate n baza de date. Aceleai prelucrri pot fi realizate de regul i n cadrul aplicaiilor client care acceseaz datele din baz, dar n cazul modificrii unei metode de calcul trebuie refcute aplicaiile client afectate i suportate toate costurile pe care le implic redistribuirea unor noi versiuni ale aplicaiilor client. Avnd n vedere faptul c de multe ori aplicaiile din domeniul bazelor de date sunt n arhitectur client-server i aplicaia client acceseaz aplicaia server (Oracle XE) prin intermediul unei reele, utilizarea pe ct posibil a procedurilor scrise n PL/SQL poate ameliora semnificativ viteza de prelucrare. n cazul unei proceduri care ar implica transferul spre aplicaia client a unui volum mare de date (rezultatul unei interogri de exemplu), ntrzierile cauzate de reeaua prin care se acceseaz serverul de baze de date pot fi mari. Dac prelucrarea datelor nu presupune afiarea acestora n aplicaia client, mult mai eficient este soluia prelucrrii datelor pe server, ntr-o procedur scris n PL/SQL. PL/SQL este bazat pe limbajul ADA, o parte dintre construciile sale sintactice provenind din Pascal.

Scrierea unui bloc anonim


De regul programarea n PL/SQL nseamn definirea unor proceduri sau funcii, n sensul pe care acestea le au n oricare dintre limbajele procedurale

38
cunoscute. O procedur sau o funcie poate fi introdus folosind fereastra SQL Plus sau folosind interfaa grafic, n SQL Command sau Script Editor. O succesiune de instruciuni n PL/SQL care nu sunt destinate definirii unei funcii sau proceduri formeaz un bloc anonim care va fi executat doar o singur dat. Exemplu:
begin dbms_output.put_line('Hello World'); end; /

n fereastra SQL*Plus secvena de cod scris va fi precedat de comanda set serveroutput on Aceasta trebuie dat la nceputul sesiunii de lucru i realizeaz activarea afirii la consol a rezultatului operaiilor de ieire.

Dac se folosete interfaa grafic nu mai este necesar comanda set serveroutput on.

39

Exemplul urmtor conine declaraia unei variabile, nr. Pentru a afia valoarea acesteia se realizeaz conversia ei n ir de caractere folosind funcia to_char():

40 Elementele limbajului PL/SQL

Codul PL/SQL poate fi coninut n blocuri anonime sau n blocuri care conin subprograme memorate n baza de date (proceduri sau funcii). Un bloc anonim se introduce n fereastra n care se introduc comenzi SQL. El nu este memorat n mod normal n baza de date n vederea reutilizrii ulterioare. Interfaa serverului Oracle XE permite totui memorarea unui bloc, ntocmai ca i memorarea unei comenzi SQL orecare. Cele dou exemple anterioare sunt blocuri anonime. Un subprogram memorat (denumit uneori stocat) este un subprogram PL/SQL pe care serverul Oracle l compileaz i l memoreaz n baza de date. Subprogramul memorat poate fi ulterior apelat dintr-o aplicaie sau dintr-un alt bloc PL/SQL. Subprogramele pot fi proceduri sau funcii. Diferena dintre cele dou este faptul c o funcie returneaz o valoare. Un pachet (engl. package) este format dintr-un un grup de subprograme i de declaraii de variabile. Serverul Oracle memoreaz elementele coninute ntr-un pachet, acestea putnd fi apelate din alte pachete sau subprograme.

Sintaxa unui bloc PL/SQL


Un bloc anonim PL/SQL se compune din seciuni i are sintaxa urmtoare:

Bloc anonim DECLARE declaratii de variabile BEGIN cod program EXCEPTION cod tratare exceptii END;
Dac blocul conine o procedur memorat n baza de date, sintaxa sa este urmtoarea:

41

Subprogram memorat de tip procedur CREATE OR REPLACE PROCEDURE "nume" (lista_parametri) IS declaratii variabile BEGIN cod program EXCEPTION cod tratare exceptii END;
Seciunea de declaraii (DECLARE n cazul blocului anonim) cuprinde declaraii de variabile simple, variabile structurate, variabile tip cursor, funcii sau proceduri ajuttoare. Zona de declaraii este opional. Pentru funcii, proceduri i triggere cuvntul DECLARE lipsete, blocul de declaraii fiind implicit cuprins ntre linia de declarare a funciei sau a procedurii i BEGIN. Blocul introdus prin EXCEPTION este opional i realizeaz tratarea erorilor aprute n timpul execuiei codului programului. Caracterul ';' se folosete pentru a marca sfritul unei instruciuni sau a unui bloc, dac apare dup END. Codul poate cuprinde blocuri interioare. Exemplu:

DECLARE declaraii variable BEGIN -- cod program BEGIN codul blocului inclus EXCEPTION tratare exceptii END; -- cod program (continuare) END;
Pentru transformarea exemplelor din urmtoarele subcapitole n exemple executabile, naintea declaraiilor de variabile va fi introdus fie numele seciunii de date, DECLARE fie secvena de declarare a unei proceduri stocate (CREATE OR REPLACE PROCEDURE "nume" IS).

42 Comentarii
n PL/SQL comentariile n linie se introduc prin dou caractere '-' iar comentariile pe mai multe linii sunt cuprinse ntre /* respectiv */, ca n limbajul C. Exemplu:

Tipuri de date n PL/SQL


Tipurile de date folosite n PL/SQL pot fi: cele folosite n SQL (VARCHAR2, NVARCHAR2, CHAR, NCHAR, NUMBER, BINARY_FLOAT, BINARY_DOUBLE, DATE, TIMESTAMP, CLOB i BLOB), tipuri specifice limbajului PL/SQL : BOOLEAN, NUMBER (scris simplu, fr dimensiune) i PLS_INTEGER (pentru variabile avnd valori ntregi), tipuri specifice structurate: TABLE, VARRAY i RECORD.

43
Exemplu:
-- Declaratii de variabile nume VARCHAR2(30); prenume VARCHAR2(25); marca NUMBER(6); activ BOOLEAN; salar_lunar NUMBER(6); nb_zile_lucrate NUMBER(2); salar_zilnic NUMBER(6,2); medie_zile_lucr CONSTANT NUMBER(2) := 21; -- o cconstanta BEGIN NULL; END; / -- NULL indica lipsa corpului. Este permisa pt. testare.

Obs. Pentru a defini constanta medie_zile_lucr s-a folosit cuvntul rezervat CONSTANT i imediat s-a atribuit valoarea corespunztoare. Variabilele declarate servesc de multe ori la memorarea unor valori din tabelele bazei de date, obinute folosind comenzi SELECT. n astfel de cazuri este esenial ca tipul declarat pentru o astfel de variabil s coincid cu tipul coloanei tabelului din care va primi valori. Pentru a evita erorile greu de depistat cauzate de declararea eronat a acestor variabile, PL/SQL ofer soluia simpl a prelurii tipului cmpului care va furniza valori folosind %TYPE, astfel:
coded edituri.cod_edit%TYPE;

Variabila coded va fi NUMBER(5), de acelai tip cu cmpul cod_edit din tabelul edituri. O situae asemntoare apare n cazul variabilelor structurate (de tipul RECORD). O astfel de variabil va avea mai multe cmpuri. Dac variabila trebuie s preia valorile coninute ntr-o linie a unui tabel, la declararea ei se va folosi %ROWTYPE, astfel: editura edituri%ROWTYPE;

44
Variabila editura va fi de tip RECORD i va avea aceleai cmpuri cu tabelul edituri. Accesul la cmpuri se realizeaz folosind operatorul '.' (punct). Exemplu: editura.cod_edit, editura.nume etc.

Cursoare
Cursoarele permit programatorului s preia date dintr-o mulime de selecie, linie cu linie, n vederea prelucrrii lor. n PL/SQL un cursor poate fi implicit sau explicit. Cursorul implicit presupune utilizarea unei mulimi de selecie avnd o singur linie i este folosit pentru a atribui valori unui set de variabile. Exemplu:
SELECT cont, data, valoare into cnt, dt, val from operatii where cod_op = 3;

n vederea selectrii unei singure linii se impune valoarea cheii primare. Cursorul explicit are nume i este declarat n seciunea de declaraii a blocului (procedurii, funciei), astfel: CURSOR c1 IS SELECT ... ; Exemplu:

CURSOR c1 IS SELECT nume, prenume FROM angajati WHERE functia = 'zidar';


Comanda SQL SELECT va fi executat n momentul deschiderii cursorului folosind instruciunea OPEN. Liniile mulimii de selecie coninute n cursor vor fi prelucrate individual, accesul la linia curent realizndu-se folosind instruciunea FETCH. Dup terminarea prelucrrii datelor coninute ntr-un cursor, acesta trebuie nchis folosind instruciunea CLOSE. Cteva exemple privind folosirea cursoarelor vor fi nserate dup prezentarea instruciunilor repetitive.

Identificatori
Numele unei variabile const dintr-un ir avnd maximum 30 caractere i format dintr-o liter urmat opional de alte litere, cifre, $, _. Caracterele '&', '-', '/'

45
i ' ' (spaiu) nu sunt permise. PL/SQL nu este sensibil la tipul literelor - majuscule sau litere mici. Exemple:
-- Declaratii de variabile numeprenume VARCHAR2(30); -- identificator acceptat nume_prenume VARCHAR2(30); -- identificator acceptat, _ permis nume$prenume VARCHAR2(30); -- identificator acceptat, $ permis nume#prenume VARCHAR2(30); -- identificator acceptat, # permis -- nume-prenume identificator neacceptat, minus nepermis -- nume/prenume identificator neacceptat, / nepermis -- nume prenume identificator neacceptat, spatiu nepermis -- NUMEPRENUME identif. neacceptat, acelasi cu numeprenume si NumePrenume -- NumePrenume identif. neacceptat, acelasi cu numeprenume si NUMEPRENUME BEGIN NULL; END; /

Operatori
La scrierea codului n PL/SQL se folosesc urmtoarele tipuri de operatori:
-

aritmetici: + - * / logici : '=' '>' '<' '>=' '<=', '!=' (sau '<>') de concatenare a irurilor '||' de atribuire: ':='

Exemple:
-- Declaratii de variabile salar NUMBER(6,2); ore_lucrate NUMBER := 40; salar_orar NUMBER := 22.50; bonus NUMBER := 150;

46
tara VARCHAR2(128); numarator NUMBER := 0; gata BOOLEAN := FALSE; id_valid BOOLEAN; BEGIN salar := (ore_lucrate * salar_orar) + bonus; -- calcul salar tara := 'Suedia'; -- atrib. un literal de tip string tara := UPPER('Canada'); -- idem, caracterele transf in majuscule gata := (contor > 100); -- atrib. BOOLEAN, literalul FALSE id_valid := TRUE; -- atrib. BOOLEAN END; /

Literali
Exemple:
-- Declaratii de variabile number1 PLS_INTEGER := 32000; -- literal numeric, val ntreag number2 NUMBER(8,3); BEGIN number2 := 3.125346e3; -- literal numeric number2 := -8300.00; -- literal numeric number2 := -14; -- literal numeric END;

char1 VARCHAR2(1) := 'x'; -- literal caracter char2 VARCHAR2(1); BEGIN char2 := '5'; -- literal caracter END; /

-- Declaratii de variabile string1 VARCHAR2(1000);

47
string2 VARCHAR2(32767); BEGIN string1 := '555-111-2323'; -- daca un sir contine apostrof, acesta se dubleaza string2 := 'Here''s an example of two single quotation marks.'; END; /

-- Declaratii de variabile gata BOOLEAN := TRUE; -- BOOLEAN literal complet BOOLEAN; true_or_false BOOLEAN; BEGIN gata := FALSE; -- literal BOOLEAN complet := NULL; -- literal BOOLEAN (valoare nedefinita) true_or_false := (3 = 4); true_or_false := (3 < 4); END; /

-- Declaratii de variabile date1 DATE := '11-AUG-2005'; -- literal DATE time1 TIMESTAMP; BEGIN time1 := '11-AUG-2005 11:01:01 PM'; -- literal TIMESTAMP END; /

Atribuirea folosind SELECT ... INTO


Dac valoarea unei variabile se determin n funcie de valori dintr-o linie a unui tabel al bazei de date, PL/SQL permite atribuirea valorii acesteia folosind un cursor implicit, respectiv o construcie SELECT expresie INTO variabil FROM tabel WHERE condiie_selectare_linie

48

Expresia folosit poate corespunztoare din tabel. Exemplu:


-- Declaratii de variabile

folosi

variabile,

literali

valori

din

linia

procent_bonus CONSTANT NUMBER(2,3) := 0.05; bonus NUMBER(8,2); ang_id NUMBER(6) := 120; -- atribuie o val. pt testare BEGIN /* preia salar din tabelul angajati, calculeaza bonusul i atribuie rezultatul -> variabila bonus */ SELECT salar * procent_bonus INTO bonus FROM angajati WHERE angajat_id = ang_id; -- listeaza codul angajat_id, bonusul si procent_bonus DBMS_OUTPUT.PUT_LINE ( 'Angajat: ' || TO_CHAR(ang_id) || ' Bonus: ' || TO_CHAR(bonus) || ' Procent bonus: ' || TO_CHAR(procent_bonus*100)); END; /

n aceeai fraz SELECT pot fi atribuite valori mai multor variabile. Exemplu: SELECT Nume, Prenume, salar*procent_bonus INTO m_nume, m_prenume, m_salar FROM angajati WHERE angajat_id = ang_id;

Funcii uzuale
PL/SQL cuprinde un numr mare de funcii. n tabelul de mai jos sunt incluse cele mai des folosite. Funcia Funcii pentru prelucrarea irurilor upper(s), lower(s) ltrim(s), rtrim(s) convertete s n majuscule/minuscule nltura spaiile de la stnga / dreapta Descriere

49
substr(s, start, lungime) length(s) returneaz un subir definit prin poz. start i lungime returneaz lungimea irului s

Funcii pentru prelucrarea datei calendaristice sysdate to_date(data, format) data din sistem returneaza o dat formatat conform formatului Ex. : to_date('31-12-2007', 'dd-mm-yyyy') to_char(data, format) Convertete o dat calendaristic n ir, conform formatului format. Exemplu: to_date(d, 'dd-mm-yyyy') Funcii pentru date numerice round(x) mod(n, p) abs(x) power(x,n) dbms_random.random() Conversii de tip to_char(n) to_number(s) Alte funcii user returneaz numele utilizatorului serverului Oracle convertete n n ir de caractere convertete irul s n numr rotunjete x returneaz restul mpririi ntregi n/p returneaz val. absolut returneaz xn genereaz un numr aleator ntreg

Instruciuni
Secvenele de cod scrise n PL/SQL pot conine comenzi SQL (CREATE, INSERT, DELETE, DROP sau ALTER). Exemplu:

Insert into deponent values (124, 'Ionescu Valer', 'Str. Crinilor Nr. 7, Craiova', '0743123989');
Pe lng comenzile SQL sau atribuirile de valori limbajul PL/SQL dispune de un set complet de instruciuni necesare controlului execuiei programului, ca oricare limbaj procedural.

50

Instruciunea de decidere - IF
n limbajul PL/SQL instruciunea IF poate prezenta trei forme.

a. IF-THEN Exemplu:
-- Declaratii de variabile vanzari NUMBER(8,2) := 10100; cota NUMBER(8,2) := 10000; bonus NUMBER(6,2); ang_id NUMBER(6) := 120; BEGIN IF vanzari > (cota + 200) THEN bonus := (vanzari - cota)/4; UPDATE angajati SET salar = salar + bonus WHERE angajat_id = ang_id; END IF; END; /

Astfel scris IF servete la condiionarea unei aciuni. Aciunea este declanat dac expresia logic are valoarea adevrat. Secvena de cod care descrie aciunea este plasat ntre THEN i END IF. b. IF-THEN-ELSE Exemplu:
-- Declaratii de variabile vanzari NUMBER(8,2) := 12100; cota NUMBER(8,2) := 10000; bonus NUMBER(6,2); ang_id NUMBER(6) := 120;

51
BEGIN IF vanzari > (cota + 200) THEN bonus := (vanzari - cota)/4; ELSE bonus := 50; END IF; UPDATE angajati SET salar = salar + bonus WHERE angajat_id = ang_id; END; /

n secvena anterioar prezena clauzei ELSE permite definirea a dou blocuri de instruciuni, unul cuprins ntre THEN i ELSE i al doilea cuprins ntre ELSE i END IF. n funcie de valoarea de adevr a expresiei logice va fi executat primul bloc sau al doilea.

c. IF-THEN-ELSIF Uneori este necesar alegerea unei secvene de cod din mai multe, fiecare fiind condiionat de cte o expresie logic. n acest caz se recomand folosirea structurii IF-THEN-ELSIF. Exemplu:
-- Declaratii de variabile vanzari NUMBER(8,2) := 20000; bonus NUMBER(6,2); ang_id NUMBER(6) := 120; BEGIN IF vanzari > 50000 THEN bonus := 1500; ELSIF vanzari > 35000 THEN bonus := 500; ELSE bonus := 100; END IF; UPDATE angajati SET salar = salar + bonus WHERE angajat_id = ang_id;

52
END; /

Instruciunea CASE
Instruciunea CASE permite impunerea blocului care va fi executat n funcie de valoarea unei expresii. De cele mai multe ori expresia se reduce la o variabil. Exemplu:
-- Declaratii de variabile grade CHAR(1); BEGIN nivel := 'B'; CASE nivel WHEN 'A' THEN DBMS_OUTPUT.PUT_LINE('Excelent'); WHEN 'B' THEN DBMS_OUTPUT.PUT_LINE('Foarte bun'); WHEN 'C' THEN DBMS_OUTPUT.PUT_LINE('Bun'); WHEN 'D' THEN DBMS_OUTPUT.PUT_LINE('Corect'); WHEN 'F' THEN DBMS_OUTPUT.PUT_LINE('Slab'); ELSE DBMS_OUTPUT.PUT_LINE('Nu ma pot pronunta'); END CASE; END; /

n exemplul prezentat valoarea variabilei nivel condiioneaz blocul care va fi executat. Valorile posibile sunt introduse prin clauze WHEN iar blocul de instruciuni care trebuie executat se scrie dup THEN. Dac valoarea variabilei nivel nu se regsete printre valorile introduse prin WHEN, se va executa blocul introdus prin clauza ELSE, plasat ultima. Instruciunea se ncheie cu END CASE.

Instruciuni de ciclare
n limbajul PL/SQL exist trei instruciuni de coclare: LOOP, WHILE-LOOP i FOR-LOOP

53
a. LOOP Un bloc LOOP - END LOOP permite definirea unui ciclu din care se iese prin executarea unei instruciuni EXIT. Instruciunea EXIT este de regul plasat ntr-un IF a crui condiie trebuie s ajung s fie satisfcut pentru a se evita rularea blocului LOOP n ciclu infinit. Exemplu:
credit_rating NUMBER := 0; BEGIN LOOP credit_rating := credit_rating + 1; IF credit_rating > 3 THEN EXIT; -- iesire imediata din loop END IF; END LOOP; -- dupa EXIT, executia se continu de aici DBMS_OUTPUT.PUT_LINE ('Credit rating: ' || TO_CHAR(credit_rating)); IF credit_rating > 3 THEN RETURN; -- n afara blocului LOOP se folosete RETURN, nu EXIT END IF; DBMS_OUTPUT.PUT_LINE ('Credit rating: ' || TO_CHAR(credit_rating)); END; /

Dac ieirea din ciclu se poate realiza printr-un simplu IF, se poate nlocui IF prin instruciunea EXIT WHEN conditie_iesire. Exemplu: IF count > 100 THEN EXIT; ENDIF; EXIT WHEN count > 100; Exemplu:
LOOP credit_rating := credit_rating + 1; EXIT WHEN credit_rating > 3 END LOOP;

54

b. WHILE - LOOP n PL/SQL pentru realizarea unei structuri repetitive condiionate anterior se utilizeaz instruciunea WHILE - LOOP. Sintaxa unei astfel de structuri repetitive este urmtoarea: WHILE condiie LOOP bloc de instruciuni END LOOP c. FOR - LOOP Ca i n alte limbaje, parcurgerea unui ir de valori se realizeaz folosind o instruciune FOR - LOOP. Exemplu de utilizare:
-- Declaratii de variabile p NUMBER := 0; BEGIN FOR k IN 1..500 LOOP -- calcul pi ca suma a 500 termeni p := p + ( ( (-1) ** (k + 1) ) / ((2 * k) - 1) ); END LOOP; p := 4 * p; DBMS_OUTPUT.PUT_LINE( 'pi este aproximativ : ' || p ); END; /

n exemplul dat variabila i va lua valori n intervalul de valori ntregi introdus prin IN. Valorile sunt de regul consecutive i cresctoare. Dac irul valorilor introduse prin IN trebuie parcurs n ordine invers se va folosi clauza REVERSE, ca n exemplul urmtor:
BEGIN FOR i IN REVERSE 1..5 LOOP DBMS_OUTPUT.PUT_LINE (TO_CHAR(i)); END LOOP; END;

55
Se interzice modificarea variabilei folosite la controlul ciclului n interiorul acestuia. Un exemplu tipic de utilizare a ciclului FOR n domeniul bazelor de date este cel n care se actualizeaz ntr-un ciclu nregistrrile dintr-un tabel. Exemple:
-- Declaratii de variabile CURSOR ang_cursor IS SELECT * FROM angajati; REC angajati%ROWTYPE; -- var. structurata de tip record BEGIN FOR REC IN ang_cursor LOOP UPDATE angajati SET salar = ... WHERE ang_id = REC.ang_id; END LOOP; END;

/
CREATE OR REPLACE PROCEDURE Afisez AS CURSOR c1 IS SELECT * FROM edituri order by nume; REC edituri%ROWTYPE; -- var. structurata de tip record BEGIN FOR REC IN c1 LOOP DBMS_OUTPUT.PUT_LINE (rec.nume); END LOOP; END; /

BEGIN OPEN c2; LOOP FETCH c2 INTO REC; EXIT WHEN c2%NOTFOUND; DBMS_OUTPUT.PUT_LINE( RPAD(REC.prenume, 25, ' ') || -- preia linia curenta in REC

56
REC.id_meserie ); END LOOP; CLOSE c2;

Not Funcia RPAD() construiete un ir de caractere avnd lungimea dat de al doilea argument. irul se obine prin completarea la dreapta a irului dat ca prim argument cu irul dat ca al treilea argument. n exemplul urmtor cursorul c1 conine doar dou valori din tabelul angajai. Instruciunea FETCH va prelua cele dou valori n dou variabile locale.
jobid angajati.job_id%TYPE; -- variabila pentru id_functie pren angajati.prenume%TYPE; -- variabila pentru prenume CURSOR c1 IS SELECT prenume, id_functie FROM angajati WHERE id_functie LIKE '%ZIDAR'; BEGIN OPEN c1; -- deschid cursorul - execut select LOOP FETCH c1 INTO pren, jobid; -- preiau 2 coloane in variabile EXIT WHEN c1%NOTFOUND; DBMS_OUTPUT.PUT_LINE( RPAD(pren, 25, ' ') || jobid ); END LOOP; CLOSE c1;

Definirea unei proceduri


De regul secvenele de cod PL/SQL sunt coninute n proceduri sau funcii. Blocurile anonime pot fi folosite eventual pentru testarea corectitudinii unei secvene de cod, dar dup ncheierea testrii ele vor fi transformate n proceduri sau funcii memorate n baza de date. Codul poate fi scris n fereastra destinat scrierii comenzilor SQL (SQL Command), n Script Editor sau folosind Object Browser / Create / Procedure. Indiferent de soluia adoptat, rezultatul va fi o procedur stocat n Oracle XE i accesibil folosind meniul Object Browser. Exemplul 1. Crearea unei proceduri folosind SQL Command:

57

Declararea unei proceduri folosind fereastra SQL Command sau SQL*Plus ncepe cu secvena : CREATE OR REPLACE PROCEDURE nume ... Pentru verificarea crerii procedurii se selecteaz Object Browser / Browse / Procedures i n fereastra care se afieaz se selecteaz procedura (SALUT).

Exemplul 2. Crearea unei proceduri folosind Object Browser / Create / Procedure:

58

Exemplu:

n pasul urmtor se definesc parametrii de intrare i de ieire ai procedurii, dac este cazul.

59
n continuare se introduce corpul procedurii:

Rezultat:

Astfel generat, procedurii i lipsete seciunea destinat declarrii variabilelor locale. Pentru adugarea acestora se selecteaz Edit i se insereaz declaraiile necesare. Apelul procedurii se poate realiza din fereastra destinat introducerii de comenzi SQL (SQL / SQL Commands) :

60

Din SQL*Plus apelul se poate face i folosind comanda SQL CALL :

Parametrii procedurilor PL/SQL Procedurile pot avea un numr de parametri de intrare (IN), parametri de ieire (OUT) sau de intrare / ieire (IN OUT). Exemple:
PROCEDURE maj ( v1 IN VARCHAR2, v2 IN VARCHAR2) IS ... ( v1 IN VARCHAR2, v2 OUT VARCHAR2) IS ... PROCEDURE majusc

PROCEDURE majuscule ( v1 IN VARCHAR2, v2 IN OUT VARCHAR2) AS ...

Dac un parametru este declarat de intrare (IN) modificarea sa n subprogram nu afecteaz valoarea eventualei variabile folosite ca parametru efectiv la apelarea funciei. La apelul unei proceduri avnd parametri de tip OUT sau IN OUT, pe poziiile corespunztoare acestora din lista de parametri efectivi trebuie utilizate variabile de acelai tip cu cel al parametrilor procedurii. Un bloc anonim sau o procedur poate avea n zona de declaraii o declaraie de procedur. Exemplu :
DECLARE -- declaratii de variabile si subprograme nume VARCHAR2(20) := 'ionescu'; prenume VARCHAR2(25) := 'marin'; PROCEDURE nume_maj ( v1 IN OUT VARCHAR2, v2 IN OUT VARCHAR2) AS BEGIN

61
v1 := UPPER(v1); -- trec sirurile in majuscule v2 := UPPER(v2); END; BEGIN DBMS_OUTPUT.PUT_LINE(nume || ' ' || prenume ); -- afisez val. initiale nume_maj (nume, prenume); -- apelez procedura cu parameteri DBMS_OUTPUT.PUT_LINE(nume || ' ' || prenume ); -- afisez noile valori END; /

Deoarece procedura nume_maj este cuprins ntr-un bloc executarea blocului nu va determina memorarea acesteia n baza de date.

anonim,

Definirea unei funcii


Funciile sunt subprograme care returneaz o valoare. Ca i n cazul procedurilor, o funcie poate fi scris n fereastra destinat scrierii comenzilor SQL (SQL Command), n Script Editor sau folosind interfaa afiat prin selectarea opiunii Object Browser / Create / Function. Exemplu:

Funcia salar poate fi apelat n mai multe moduri, cel mai simplu fiind n fraze select:

62
a.

b. Ca i procedura, o funcie poate avea parametri de intrare. este


CREATE OR REPLACE FUNCTION nume_prenume ( nume IN VARCHAR2, prenume IN VARCHAR2, casatorit IN VARCHAR2) RETURN VARCHAR2 AS nup VARCHAR2(45); -- variabila locala BEGIN -- Se construieste un sir cuprinzand numele si prenumele nup := upper(nume) || ' ' || prenume; -daca e casatorit, adaug casatorit

Lista acestora

if length(casatorit) > 0 THEN

nup := nup || ' ' || casatorit; END IF; RETURN nup; -- returneaza valoarea lui nup END; /

Laborator nr. 5

63

Relaii ntre tabele. SQL, Query. View


1. Pornii aplicaia Start -> Programs -> Oracle Database 10g Express Edition -> Go To DatabaseHome Page sau accesai adresa http://127.0.0.1:8080/apex/ n Internet Explorer. 2. Creai un utilizator nou, banca, avnd parola banca. 3. Creai o baz de date pentru gestionarea unor informaii dintr-o banc. Pentru asta creai urmtoarele tabele: DEPONENT cod_dep - cheie primar (number - 6,0) nume numele i prenumele deponentului (varchar2 - 60) adresa adresa deponentului (varchar2 - 100) telefon numrul de telefon al deponentului (number - 10) CONTURI cont numrul contului (number - 6,0 cheie primar) cod_dep codul deponentului (number - 6,0 cheie strin) OPERATII cod_op codul operaiunii (cheie primar number - 4) cont numrul contului (number - 6,0, cheie strin ) data data n care se efectueaz operaiunea (dat) valoare valoarea operaiunii, valoare pozitiv pentru depunere i valoare negativ pentru retragere (numr) Obs. Un deponent poate avea mai multe conturi; Pentru un cont pot exista mai multe operaii n tabelul de operaii; Depunerile vor fi pozitive (operatii.valoare >0) iar retragerile negative (operatii.valoare < 0) 4. Se cere: S se adauge 5 clieni (deponeni), 7 conturi i 11 operaii pentru diferite conturi;

64

DEPONENT

CONTURI

OPERATII

5. Creai cteva vederi (View) folosind Query Builder:

65

S se afieze , n ordine alfabetic, toi clienii bncii

Dup alegerea opnuii

rezultatul este

Dac dup compilare rspunsul este No Error, rezultatul va fi:

66

S se afieze toate operaiunile bancare n ordine cresctoare a datei.

S se afieze toate operaiunile bancare efectuate ntr-o zi.

S se afieze conturile unui deponent.

Obs. Adugai legturile persistente n fereastrta Query builder-ului

67

S se afieze toate operaiunile efectuate de un deponent ntr-un cont;

68

S se afieze toate conturile unui deponent precum i suma total pe care acesta o are n fiecare dintre conturi;

S se afieze toate retragerile efectuate n perioada 01-02-2007 31-03-2007.

69

Laborator nr. 6 PL/SQL


6. Pornii aplicaia Start -> Programs -> Oracle Database 10g Express Edition -> Go To Database Home Page sau accesai adresa http://127.0.0.1:8080/apex/ n Internet Explorer. 7. Conectai-v folosind contul banca, cu parola banca. 8. Creai o un bloc anonim care afieaz numele utilizatorului i data curent. Un bloc anonim nu este memorat n baza de date Oracle XE. El este destinat execuiei imediate. Introducerea blocului anonim se poate face n fereastra de editare afiat la selectarea opiunii SQL/SQL Commands/ Enter Command.

Blocul anonim scris apeleaz dou funcii, user i sysdate (vezi curs p. ). 9. PL/SQL permite scrierea de subprograme (funcii sau proceduri). Rescriei blocul anonim sub forma unei proceduri denumite "Salut_user". Pentru scrierea unei proceduri se selecteaz Object Browser / Create/Procedure. Dup primul pas, n care se introduce numele procedurii, se selecteaz Next i se introduce corpul acesteia (fr begin ... end!).

70

Rezultat:

n continuare se selecteaz Edit i se adaug declaraiile variabilelor utilizator i data_azi. Apoi se selecteaz Compile pentru a vedea eventualele erori. Rezultat:

Pentru testare scriei un bloc anonim care conine apelul procedurii.

71

10. Creai n domeniul curent tabelul SUPRAFETE(RAZA NUMBER(3), SUPRAFATA NUMBER(7,2)) i populati-l cu date folosind o procedur PL/SQL. Procedura va insera nregistrri coninnd raza unui cerc i aria acestuia. Raza va fi o valoare ntreag i va varia de la 1 la 20.

create or replace procedure ARIA is pi constant number(7,5) := 3.14159; raza number(5); suprafata number(14,2); Begin raza := 1; While raza <=20 Loop suprafata := pi* power(raza,2); Insert into suprafete values (raza, suprafata); raza:= raza+1; end loop; end; Adugai procedurii comanda SQL DELETE care trebuie s tearg nregistrrile naintea unei noi adugri de date:
DELETE FROM suprafete;

Modificai procedura astfel nct s admit doi parametri, r1 NUMBER i r2 NUMBER. Liniile inserate n tabelul suprafee vor conine ariile cercurilor avnd razele cuprinse ntre r1 i r2.

create or replace procedure ARIA (r1 IN number, r2 IN number) is pi constant number(4,2) := 3.14;

72 raza number(5); suprafata number(14,2); Begin delete from suprafete; raza := r1; While raza <=r2 Loop suprafata := pi* power(raza,2); Insert into suprafete values (raza, suprafata); raza:= raza+1; end loop; end; Pentru testare scriei un bloc anonim care va conine apelul procedurii.

11. Scriei o procedur care creaz un cursor coninnd numele i telefonul deponenilor i imprim numele primei nregistrri a acestuia. create or replace procedure DEPONENTI is CURSOR c_dep IS SELECT nume, telefon from deponent; num deponent.nume%TYPE; tel deponent.telefon%TYPE; begin OPEN c_dep; FETCH c_dep into num, tel; dbms_output.put_line(num ||' '|| tel); CLOSE c_dep; end; Pentru testare scriei un bloc anonim care va conine apelul procedurii.

73

12. Rescriei procedura DEPONENTI astfel nct s afieze toi deponenii.

create or replace procedure DEPONENTI is CURSOR c_dep IS SELECT nume, telefon from deponent; num deponent.nume%TYPE; tel deponent.telefon%TYPE; begin OPEN c_dep; LOOP FETCH c_dep into num, tel; EXIT WHEN c_dep%NOTFOUND; dbms_output.put_line(num ||' '|| tel); END LOOP; CLOSE c_dep; end;