Sunteți pe pagina 1din 20

Laboratoare SGBD Informatic anul II Instructor Vrlan Simona-Elena

Mini tutorial de PL/SQL


Laboratoarele se bazeaz pe cursurile online oferite de ctre Oracle Academy. Pentru testarea exerciiilor in
PL/SQL se vafolosi aplicaia proprietar Oracle: Oracle Application Express.
Accesul la cursurile online valabile studenilor de la Informatic anul II se face la adresa web:
http://academy.oracle.com/. Se alege linkul Introduction to computer science (stnga jos) -> Student Sign In (colul
din dreapta sus), iar pe pagina de iLearning se va scrie un user i o parola furnizate n cadrul orelor de laborator.

Pagina iLearning

Accesul la Oracle Application Express se face la adresa web:


https://iacademy3.oracle.com.
Conturile sunt:
Workspace: RO_P1268_S{useri de la 01 la 30}
User:
RO_P1268_S{nr folosit mai sus}_PLSQL
Password:
va fi comunicat
Exemplu:
School: RO_P1268_S03
User: RO_P1268_S03_PLSQL
Password: ******

Laboratoare SGBD Informatic anul II Instructor Vrlan Simona-Elena

Oracle Application Express

Pentru testarea exemplelor in PL/SQL se va folosi SQL Workshop -> SQL Commands.
Introducere n PL/SQL
Acest mini tutorial realizeaz o scurt introducere a limbajului de programare PL/SQL folosit n cadrul
laboratoarelor de SGBD conform leciilor virtuale oferite de Academy Oracle.
PL/SQL este un limbaj de programare procedural folosit de Oracle pentru bazele de date relaionale. Pe
scurt PL/SQL este:
o extensie pentru limbajul SQL ce permite combinarea declaraiilor SQL cu un limbaj de
programare;
este un limbaj proprietar Oracle i poate fi folosit doar cu o baz de date Oracle;
este un limbaj procedural;
este un limbaj de generaia a treia 3GL.
Exemplu:
Considerm tabela enrollments cu notele studenilor. Daca vrem s selectm notele atunci avem urmtoarea
interogare:
Select stu_id, final_numeric_grade, final_letter_grade
From enrollments;
Dac vrem n continuare s modificm datele n funcie de o anumit condiie dup principiul DAC este
adevrat expresia ATUNCI execut instruciunea1, ALTFEL execut instruciunea2, nu putem doar cu declaraii
SQL. Aici intervine PL/SQL care folosete variabile, costante, tipuri de date, cursoare, structuri de control i
proceduri i funcii. n continuare vom oferi drept exemplu de utilizare a limbajului PL/SQL pentru modificarea
notelor studenilor din valori numerice cu valori de tip caracter:
Declare
v_new_letter_grade varchar2(1);
Cursor c_enrollments IS

Laboratoare SGBD Informatic anul II Instructor Vrlan Simona-Elena


Begin

Select stu_id, final_numeric_grade from enrollments where class_id=1;

For c1 in c_enrollments
Loop
If c1.final_numeric_grade between 66 and 75 then v_new_letter_grade:= A:
Elsif c1.final_numeric_grade between 56 and 65 then v_new_letter_grade:= B;
Elsif c1.final_numeric_grade between 56 and 65 then v_new_letter_grade:= C;
Elsif c1.final_numeric_grade between 56 and 65 then v_new_letter_grade:= D;
Else
V_new_letter_grade:=F;
End if;
Update enrollments
Set final_letter_grade=v_new_letter_grade where class_id=1 and stu_id=c1.stu_id;
End loop;
Commit;
End;
Dup cum se poate observa limbajul folosete variabile definite n partea declarativ; folosete cursoare
pentru situaii cnd avem mai mult de o nregistrare n urma unui select; structuri de control: FOR, IF; i declaraii
SQL.
Prin urmare avantajele PL/SQL sunt:
integrarea construciilor procedurale cu SQL;
integrarea structurilor de control cu SQL ceea ce ofer un control mult mai bun al instruciunilor
SQL i al execuiilor acestora;
modularizarea programelor deoarece unitatea de baz ntr-un program PL/SQL este blocul
considerat a fi un modul iar programul poate fi alctuit dintr-o secven de astfel de blocuri sau
putem avea blocuri imbricate;
performan ridicat prin combinarea logic a declaraiilor SQL reducnduse numrul de apeluri la
baza de date;
portabilitate, programele PL/SQL pot rula oriunde un server Oracle funcioneaz indiferent de SO
i platforma folosit;
manipularea excepiilor, limbajul PL/SQL ofer posibilitatea captrii excepiilor eficient reducnd
astfel posibilitatea apariiei erorilor.
Crearea blocurilor PL/SQL
Reprezint unitatea de baz n PL/SQL. Exist 3 tipuri de blocuri: blocul anonim, procedura i funcia,
ultimele dou sunt subprograme.
Un bloc PL/SQL conine trei pri:
1.
Partea Declarativ (opional): ncepe cu DECLARE i se termin cnd partea executabil
ncepe. Conine declaraii de variabile, cursoare i excepii definite de utilizator (exist i
excepii predefinite).
2.
Partea Executabil (obligatorie): ncepe cu BEGIN i se termin cu END. End se termin cu
punct i virgul. Partea executabil poate conine oricte blocuri sunt necesare.
3.
Partea de captare a Excepiilor (opional): partea aceast este inclus n partea executabil.
ncepe cu EXCEPTION.
a. Blocul anonim

Laboratoare SGBD Informatic anul II Instructor Vrlan Simona-Elena


Exemplu:

[ Declare .......]
Begin ....................
[ Exception ............... ]
End;

Blocul anonim nu poate fi invocat deoarece nu are un nume i nu mai exist dup ce este executat.
Exemple de blocuri anonime:
Begin

DBMS_OUTPUT.PUT_LINE(un prim exemplu);

End;
-------------------------------------------------------------------------Declare
v_date DATE := sysdate;
Begin
DBMS_OUTPUT.PUT_LINE(v_date);
End;
------------------------------------------------------------------------Declare
v_country_id varchar2(2);
Begin
select country_id into v_country_id from countries
where country_id='a';
Exception
WHEN NO_DATA_FOUND THEN
Dbms_Output.Put_Line('eroare');
End;
-------------------------------------------------------------------------Observaii!
Pentru exemplul cu exception avem o excepie predefinit: NO_DATA_FOUND.
De asemenea se poate deduce ca i regul de declarare a variabilelor: folosirea literei v i apoi ct mai
explicit denumiri pentru variabile.
Funcia de afiare este DBMS_OUTPUT.PUT_LINE iar ca argumente pentru aceasta se folosesc variabile
declarate i NU cmpuri din baza de date.
De asemenea n cadrul codului PL/SQL rezultatul n urma unei interogri SQL se pstreaz tot ntr-o
variabil declarat.
Exe.:

Begin
End;

Select 2*2 from dual,

Este greit, iar eroarea va fi: PLS-00428: an INTO clause is expected in this SELECT statement.
Corect este:
Declare
nr
Begin

number;

Laboratoare SGBD Informatic anul II Instructor Vrlan Simona-Elena


End;

select 2*2

INTO nr

from dual;

b. Declararea subprogramelor: procedurilor i funciilor


Subprogramele sunt stocate n baza de date i pot fi invocate ori de cte ori este necesar.
1. Procedur pentru a afia data curent
CREATE PROCEDURE print_date IS
v_date varchar2(30);
BEGIN
Select to_char(sysdate, Mon DD, YYYY) into v_date from dual;
dbms_output.put_line(v_date);
END;
Cuvintele cheie sunt: CREATE PROCEDURE <nume> IS . Ea poate fi apoi apelat prin numele ei.
2. Funcie pentru a numra caracterele dintr-un string
CREATE FUNCTION num_characters (p_string IN VARCHAR2)
RETURN INTEGER IS
v_num_characters integer;
BEGIN
Select length(p_string) into v_num_characters from dual;
RETURN v_num_characters;
END;
Cuvintele cheie sunt: CREATE FUNCTION <nume> ( argument IN <tip data>) RETURN <tip> IS.
Funciile fa de proceduri returneaz o valoare de un anumit tip de dat.

Folosirea variabilele in PL/SQL


Variabilele pot fi folosite pentru a stoca temporar datele, pentru manipularea valorilor stocate i pentru
reutilizare.
Ele sunt folosite n cadrul declaraiilor SQL astel:
Select first_name, department_id INTO v_emp_fname, v_emp_deptno FROM ...
unde v_emp_fname i v_emp_deptno sunt variabilele n care se vor stoca numele i departamentul;
sau
pot fi folosite ca parametri n subprograme PL/SQL i pentru a reine output-ul subprogramelor:
CREATE FUNCTION num_characters (p_string IN VARCHAR2)RETURN INTEGER IS
v_num_characters integer
Toate variabilele trebuie declarate n seciunea declarativ a oricrui block PL/SQL!
Iniializarea variabilelor
Declare
count INTEGER := 0;
Begin

Laboratoare SGBD Informatic anul II Instructor Vrlan Simona-Elena


count :=count + 1;
DBMS_OUTPUT.PUT_LINE(count);
End;
Dup cum se poate vedea variabila count a fost declarat n seciunea declarativ i totodata iniializat cu
valoarea 0.
Alte exemple de declarare i iniializare a variabilelor:
data_azi
numr
constanta
nume

DATE;
NUMBER(2) NOT NULL :=2;
CONSTANT NUMBER :=10;
VARCHAR2(30) DEFAULT Ema;

Atribuirea valorilor n seciunea executabil


Declare
v_nume varchar2(20);
Begin
DBMS_OUTPUT.PUT_LINE(Numele meu este: || v_nume);
v_nume := Ema;
DBMS_OUTPUT.PUT_LINE(Numele meu este: || v_nume);
End;
Va afia:
Numele meu este:
Numele meu este: Ema
SAU
CREATE FUNCTION num_characters (p_string IN VARCHAR2)RETURN INTEGER IS
v_num_characters integer;
Begin
Select length (p_string) into v_num_characters from dual;
Return v_num_characters;
End;
Declare
v_length_of_string integer;
Begin
--atribuirea variabilei v_length_of_string valoarea returnat de funcie
v_length_of_string := num_characters(Oracle Academy);
DBMS_OUTPUT.PUT_LINE(v_length_of_string);
End;
! n cadrul blocurilor PL/SQL pentru comentariile pe o singur liniie se folosete -- , iar pentru cele pe mai
multe linii /* */
Variabilele au urmtoarele proprieti:
- pot avea maxim 30 de caractere
- trebuie s nceap cu o liter
- pot include simboluri precum $, _ i #
- nu pot conine spaii
- sunt case insensitive

Laboratoare SGBD Informatic anul II Instructor Vrlan Simona-Elena

Tipurile de date in PL/SQL


Exist cinci categorii de tipuri de date n PL/SQL.
Scalar - dein o singur valoare: character, number, date i boolean(Bacau, 234, 1-01-2010, true)
Compus - conin elemente interne care sunt fie scalare(recorduri) fie compuse(recorduri si tabele):
table, record, nested table(tabel imbricat), varray
obiecte mari(LOB) - valoarea lor specific adresa obiectelor (precum imaginile): CLOB character
large object(cri), BLOB binary large object(poze), BFILE binary file(filme), NCLOB national language
character large objec(caractere chinezeti)
referin: pointeri
obiect: similar clasei din C++ i Java
Folosirea tipul SCALAR
Pentru variabile de tip caracter
CHAR: v_dept CHAR(7)
VARCHAR2: v_emp_job VARCHAR2(9)
LONG: v_name LONG
Pentru variabile de tip numeric
NUMBER: v_dept_sal NUMBER(9,2) :=0
PLS_INTEGER
BINARY_INTEGER: v_count Constant Binary_Integer:= 0
BINARY_FLOAT
! INTEGER este acelai lucru cu NUMBER(38,0)
Pentru variabile de tip dat
DATE: v_data DATE := sysdate+1
TIMESTAMP: v_date TIMESTAMP
TIMESTAMP WITH TIMEZONE pentru zone cu diferene de fus orar
Pentru variabile boolean
- BOOLEAN cu cele trei valori posibile: true, false i NULL v_valid BOOLEAN:=true
Atributul %TYPE
Atrbutul poate fi folosit pentru a declara o variabil conform unei alte variabile declarate anterior sau a unei
coloane dintr-o tabel. Este folosit n special atunci cnd declarm variabile pentru a stoca valori rezultate dintr-o
tabel din baza de date. Variabila creat cu acest atribut va avea acelai tip de dat conform variabilei/coloanei
dup care este declarat.
Pentru a declara o variabil cu %TYPE atributul trebuie prefixat cu numele tabelei i numele coloanei
conform creia declarm variabila.
Exemplu:
create table salariat (nume varchar2(30), id_salariat number(6) );
Declare
v_id_salariat salariat.id_salariat%TYPE;
Begin
select id_salariat INTO v_id_salariat from salariat where nume like John
End;
SAU
Declare
v_cont NUMBER(7);

Laboratoare SGBD Informatic anul II Instructor Vrlan Simona-Elena


v_cont_debit v_cont%TYPE;
...
n aceste mod, variabila v_id_salariat va avea n mod automat acelai tip ca i coloana din tabela salariat.
Atributul %Type este folositor pentru cazurile cnd schimbm tipul de dat pentru o coloan anume, iar n acest
caz variabila creat pentru stocarea valorilor din coloana respectiv nu ar mai corespunde ca tip de dat(data type
mismatch). Astfel nu mai trebuie s modificm apoi i tipul variabilei respective. Acesta este preluat automat
indiferent de schimbare.

Funcii SQL n PL/SQL


Sunt disponibile n PL/SQL urmtoarele funcii:
single-row character
single-row number
date
data-type conversion
Nu sunt disponibile n PL/SQL:
funcia decode
funciile de grupare (group functions)
Exemple:
-- obinerea lungimii unui ir
v_lung INTEGER(5);
v_sir VARCHAR2(70):= exemplu;
v_lung := LENGTH(v_sir);
-- rotunjirea unui numr la 0 decimale
Declare
v_median_age NUMBER(6,2);
Begin
DBMS_OUTPUT.PUT_LINE(ROUND(v_median_age, 0));
End;
-- calcularea numrului de luni dintre dou date calendaristice
Declare
v_no_months PLS_INTEGER :=0;
Begin
v_no_months := MONTHS_BETWEEN(31-ian-09, 31-ian-10);
DBMS_OUTPUT.PUT_LINE(v_no_months);
End;
n PL/SQL se pot efectua dou tipuri de conversii, explicite i implicite.
!!NU uitai, conversiile implicite pot ncetini codul, putei pierde controlul asupra programului deoarece
prin conversie implicite facei doar presupuneri despre cum Oracle manipuleaz datele, iar n caz c Oracle
schimb regulile de conversie, codul nu va mai funciona. Este indicat s folositi conversii explicite:
TO_NUMBER(), TO_CHAR(), TO_DATE().

BLOCURI IMBRICATE I SCOPUL VARIABILELOR


Blocurile din PL/SQL pot conine oricte subblocuri.
Exemplu:

Laboratoare SGBD Informatic anul II Instructor Vrlan Simona-Elena


Declare
V_outer-variable VARCHAR2(20) :=global variable;
Begin
Declare
V_inner_variable VARCHAR2(20):=local variable;
Begin
DBMS_OUTPUT.PUT_LINE(v_inner_variable);
DBMS_OUTPUT.PUT_LINE(v_outer_variable);
End;
DBMS_OUTPUT.PUT_LINE(v_outer_variable);
End;
n exemplul de mai sus avem un bloc exterior printe i un bloc interior copil. Variabila
v_outer_variable este declarat n blocul printe i variabila v_inner_variable este declarat n blocul copil. Scopul
unei variabile este n cadrul blocului sau blocurilor n care ea este accesibil, i anume unde poate fi denumit i
folosit.
n PL/SQL scopul unei variabile este n blocul unde a fost declarat plus blocurile imbricate n cadrul
blocului.
O variabil este local pentru blocul unde a fost declarat i globale pentru toate subblocurile acelui bloc:
v_outer_variable este local pentru blocul outer i global pentru blocul inner.
Nu pot exista dou variabile cu acelai nume n cadrul aceluiai bloc ns dou variabile pot avea acelai
nume dac sunt din blocuri diferite.
Vizibilitatea unei variabile este poriunea de program unde variabila poate fi accesat fr a folosi un
calificator.
Un calificator este o etichet dat unui bloc. Acest calificator este folosit pentru a accesa variabilele care au
scop n cadrul altui bloc dar nu au vizibilitate.
<<outer>>
Declare
v_nume_tata VARCHAR2(20):=Filip;
v_zi_nastere DATE:=20-apr-1960;
Begin
Declare
v_nume_copil VARCHAR2(20):=Mihai;
v_zi_nastere DATE:=12-ian-1993;
Begin
DBMS_OUTPUT.PU_LINE(Tatal este || v_nume_tata);
DBMS_OUTPUT.PUT_LINE(Zi de nastere || outer.v_zi_nastere);
DBMS_OUTPUT.PU_LINE(Copilul este || v_nume_copil);
DBMS_OUTPUT.PUT_LINE(Zi de nastere || v_zi_nastere);
End;
End;
Se va afia: Tatal este Filip
Zi de nastere 20-apr-1960
Copilul este Mihai
Zi de nastere 12-ian-1993

Laboratoare SGBD Informatic anul II Instructor Vrlan Simona-Elena


Dup cum se poate observa din exemplul de mai sus, avem patru variabile, dou declarate n blocul
etichetat outer i dou declarate n blocul copil imbricat blocului outer.
Variabila v_nume_tata are scopul n ambele blocuri i vizibilitatea tot n ambele blocuri i este variabil
local pentru blocul outer i global pentru blocul imbricat copil.
Variabila v_nume_copil are scopul doar n blocul copil, unde a fost declarat i vizibilitatea la fel, i este
variabil local pentru blocul interior.
Variabila v_zi_nastere declarat n blocul outer are scopul n ambele blocuri dar are vizibilitate doar n
blocul outer deoarece n blocul copil exist o variabil cu acelai nume, iar variabila din outer nu poate fi accesat
decat prin calificatorul outer (pentru a ti exact c facem referire la aceat variabil). Este local pentru blocul
outer i global pentru blocul copil.
Variabila v_zi_nastere din blocul copil are scopul i vizibilitatea doar n blocul copil. Pentru a fi accesat
nu este nevoie de calificator. Este local pentru blocul unde a fost declarat.
Scopul excepiilor n blocurile imbricate
O excepie este o seciune de program care prinde erorile pentru a nltura afritul brusc al programului.
O excepie poate fi prins/manevrat sau propagat n mediul de execuie.
Putem avea seciuni de manevrare a aexcepiilor n cadrul blocurilor interioare i dac excepia este tratat
cu succes atunci blocul copil ii termin execuia iar blocul printe i-o continu n mod normal:
Begin -- outer
...
Begin -- inner
...
Exception
When exception_name Then -- excepia este tratat aici
End;
...
End;
Sau putem s lsm excepia s se propage n cadrul blocului printe (de fapt se caut n blocurile succesive
seciunea de tratare a erorii pn se gsete una):
Begin -- outer
...
Begin -- inner
...
End;
...
-- cum blocul interior nu a tratat eroarea, atunci aceasta este propagat n blocul exterior iar
-- codul rmas din blocul exterior este srit
Exception
When exception_name then -- blocul printe va trata eroarea
End;
!n continuare, pentru a nelege mai bine teoria, este necesar s recapitulai JOIN-urile, funciile din SQL i sintaxa
DML (data modeling language) pentru a insera, modifica, terge i reuni datele dintr-o baz de date i DDL (data
definition language) pentru cearea, modificarea i tergerea obiectelor din baza de date.

Regsirea i prelucrarea datelor n PL/SQL


Declaraii SQL care pot fi folosite n PL/SQL sunt:
- SELECT

Laboratoare SGBD Informatic anul II Instructor Vrlan Simona-Elena


- INSERT, UPDATE i DELETE
- COMMIT, ROLLBACK i SAVEPOINT
! Nu se poate folosi DDL create table, alter table, drop table i grant, revoke direct n PL/SQL.
Sintaxa SELECT n PL/SQL este:
SELECT lista_cmpuri INTO {variabil1, variabil2, . . . | nume_record}
FROM tabel
[WHERE condiie]
Clauza INTO este obligatorie i este folosit pentru a specifica numele variabilelor care vor deine valorile
returnate n urma selectului. Trebuie specificat cte o variabil pentru fiecare cmp din tabel selectat i ordinea
variabilelor trebuie s corespund cu ordinea cmpurilor din lista selectat.
De asemenea clauza select trebuie s returneze doar un rnd, cele care vor returna mai mult de un rnd din
tabel vor genera eroare.
Exemplu:
Declare
v_salary employees.salary%TYPE;
Begin
SELECT salary INTO v_salary FROM employees;
DBMS_OUTPUT.PUT_LINE(Salariul este || v_salary);
End;
Selectul de mai sus va returna mai mult de un rnd, i anume toate salariile pentru toi angajaii, iar
variabila v_salary nu poate reine dect o singur valoare. Prin urmare se va genera eroare.
! Nu uitai:
- s terminai fiecare instruciune SQL cu punct i virgul,
- fiecare valoare trebuie stocat n variabile folosind clauza INTO,
- specificai acelai numr de variabile cte cmpuri selectai,
- declarai variabilele corespunztoare cmpurilor din tabel folosind atributul %TYPE,
- nu folosii aceai denumire pentru variabile ca i cmpurile selectate (putei pune litera v n faa numelui).
Insert n PL/SQL este folosit astfel:
Begin
INSERT INTO copy_emp (employee_id, first_name, last_name, email, hire_date, job_id, salary)
VALUES (99, Ruth, Cores, RCORES,sysdate,AD-ASST, 4000);
End;
- o nou nregistrare este adugat n tabela copy_emp
Update:
Declare
v_sal_increase employees.salary%TYPE :=800;
Begin
UPDATE copy_emp
SET salary=salary + v_sal_increase
WHERE job_id = ST_CLERK;
End;

Laboratoare SGBD Informatic anul II Instructor Vrlan Simona-Elena


- modific salariul celor care sunt stock clerks
tergerea datelor:
Declare
v_deptno employees.department_id%TYPE := 10;
Begin
DELETE FROM copy_emp
WHERE department_id = v_deptno;
End;
- terge rndurile care aparin departamentului 10
Merge:
Begin
MERGE INTO copy_emp c
USING employees e
ON (e.employee_id = c.employee_id)
When MATCHED THEN
UPDATE SET
c.first_name = e.first_name,
c.last_name = e.last_name,
c.email
=e.email,
...
WHEN NOT MATCHED THEN
INSERT VALUES (e.employees_id, e.first_name, . . . e.department_id);
End;
Folosirea clauzelor de control a tranzaciilor(operaii n baza de date) n PL/SQL
Acestea sunt: COMMIT, ROLLBACK, SAVEPOINT.
Exemple:
Begin
INSERT INTO pairtable VALUES (1,2);
COMMIT;
End;
-- COMMIT este folosit pentru a face modificrile permanente
Begin

INSERT INTO pairtable VALUES (3,4);


ROLLBACK;
INSERT INTO pairtable VALUES (5,6);
COMMIT;

End;
-- ROLLBACK este folosit pentru a anula orice modificare realizat n baza de date dup ultimul
COMMIT realizat. n exemplul de mai jos doar ultimul insert are loc.
Begin

INSERT INTO pairtable VALUES (3,4);


SAVEPOINT my_sp_1;
INSERT INTO pairtable VALUES (9,10);
SAVEPOINT my_sp_2;
INSERT INTO pairtable VALUES (11,12);

Laboratoare SGBD Informatic anul II Instructor Vrlan Simona-Elena


ROLLBACK to my_sp_1;
INSERT INTO pairtable VALUES (13,14);
COMMIT;

End;
-- SAVEPOINT este folosit pentru a marca puncte intermediare n procesul tranzaciei. Doar ROLLBACK
poate fi folosit cu SAVEPOINT. n exemplu prin ROLLBACK se anuleaz toate tranzaciile pn la
savepoint my_sp_1. n final vor fi introduse doar primul insert i cel de dup rollback.

CURSORUL IMPLICIT
De fiecare dat cnd o instruciune SQL urmeaz s fie executat, serverul Oracle aloc o zon de memorie
privat pentru a stoca declaraia SQL i datele implicate. Aceast zon de memorie se numete cursor
implicit.
Cu ajutorul atributelor cursorului implicit putem afla cte rnduri au fost procesate de ctre declaraia SQL.
Exist dou tipuri de cursoare:
- cursorul implicit, este automatic denumit SQL
- cursorul explicit, definit de ctre programator pentru interogri ce returneaz mai mult de o nregistrare
Atributele pentru cursorul implicit sunt:
- SQL%FOUND atribut boolean evaluat cu true dac interogarea returneaz cel puin o nregistrare
- SQL%NOTFOUND atribut boolean evaluat la true dac interogarea nu returneaz nicio valoare
- SQL%ROWCOUNT este o valoare intreag ce reprezint numrul de nregistrri afectate de interogare
Exemplu:
Declare
v_deptno copy_emp.department_id%TYPE:=50;
Begin
Delete from copy_emp where department_id = v_deptno;
DBMS_OUTPUT.PUT_LINE(SQL%ROWCOUNT || nregistrri terse .);
End;

Structuri de control

Structura Condiional IF
IF condiie THEN
Instruciune;
[ELSIF condiie THEN
Instruciune;]
[ELSE
Instruciune;]
END IF;
Declare
V_varsta NUMBER:=13;
Begin
IF v_varsta < 18 THEN
DBMS_OUTPUT.PUT_LINE (Sunt copil);
ELSIF v_varsta < 40 THEN
DBMS_OUTPUT.PUT_LINE (Sunt nc tnr);
ELSE
DBMS_OUTPUT.PUT_LINE(Sunt mereu tnr!);
END IF;
End;

Laboratoare SGBD Informatic anul II Instructor Vrlan Simona-Elena


!ATENIE: atunci cnd avem NULL n condiia din IF se comporta ca i FALSE, deci se va trece direct pe ramura
urmtoare din IF. De exemplu: x :=5 i y:= NULL atunci IF x!=y va da NULL deoarece NULL este nedeterminat.
La fel pentru x:= NULL i y:=NULL d tot NULL i instruciunile nu se execut.
Structura CASE
Exista dou tipuri de structuri CASE: Case-ul obinuit i 2 tipuri de expresii CASE care sunt funcii ce
returneaz una din mai multe valori ntr-o variabil.
CASE
CASE [selector]
WHEN expresie1 THEN instruciuni;
WHEN expresie2 THEN instruciuni;
...
[ELSE instruciuni;]
END CASE;
Exemplu:
Declare
v_in NUMBER;
Begin
CASE v_in
WHEN 1 THEN
Select * from employees;
WHEN 2 THE
Select * from employees_copie;
ELSE
DBMS_OUTPUT.PUT_LINE(nu se selecteaz nimic);
END CASE;
End;

Expresie CASE tip1:


variabil := CASE selector
WHEN valoare1 THEN rezultat1
WHEN valoare2 THEN rezultat2
...
[ELSE rezultat n]
End;
Exemplu:
Declare
v_out VARCHAR2(15) := 50;
v_in NUMBER;
Begin
v_out := CASE v_in
WHEN 1 THEN mic
WHEN 50 THE mijlociu
ELSE alt valoare

Laboratoare SGBD Informatic anul II Instructor Vrlan Simona-Elena

End;

END;
DBMS_OUTPUT.PUT_LINE(v_out);

Expresie CASE de cutare tip2:


Case
WHEN condiie_de_cutare1 THEN rezultat1
WHEN condiie_de_cutare2 THEN rezultat2
...
[ELSE rezultat n]
End;
- nu are selector iar clauza WHEN conine o condiie de cutare care returneaz o valoare boolean i nu o
expresie care poate returna o valoare de orice tip
Exemplu:
Declare
v_out VARCHAR2(15) := 50;
v_in NUMBER;
Begin
v_out := CASE
-- nu mai avem selector
WHEN v_in = 1 THEN mic
WHEN v_in= 50 THE mijlociu
ELSE alt valoare
END;
DBMS_OUTPUT.PUT_LINE(v_out);
End;
Structurile REPETITIVE: FOR, WHILE, LOOP
LOOP structuta repetitiv de baz
LOOP
Instruciune1;
...
EXIT [WHEN condiie];
End LOOP;
Exemplu:
Declare
v_counter NUMBER(3):= 1;
Begin
LOOP
INSERT into salariat values (v_counter, Leonte,Bacau);
v_counter:= v_counter+1;
EXIT WHEN v_counter > 5;
End loop;
End;
Putem avea oricte clauze EXIT dorim. Este indicat folosirea lui WHEN pentru a nu avea o bucl infinit.
Bucla WHILE
WHILE condiie LOOP

/*dac condiia este adevrat se trece la execuia instruciunilor. Poate returna

Laboratoare SGBD Informatic anul II Instructor Vrlan Simona-Elena


Instruciuni;
...
End LOOP;

true, false i NULL caz n care nu se execut while */

Declare
v_counter NUMBER:=1;
Begin
While v_counter <= 3 LOOP
INSERT into salariat values (v_counter, Leonte,Bacau);
v_counter:=v_counter+1;
End LOOP;
End;
Bucla FOR
FOR contor IN [REVERSE]

/*contor nu se declar este declarat implicit i este incrementat automat.


Se folosete reverse pentru a decrementa contorul. */
Limita_minim . . limita_maxim LOOP -- limitele pot fi i expresii cu rezultat valoare numeric
Instruciuni;
...
End LOOP;
Begin

End;

FOR v_counter IN 1..3 LOOP


INSERT into salariat values (v_counter, Leonte,Bacau);
End LOOP;

! Structurile repetitive pot fi imbricate una n alta. Atunci structurile sunt etichetate <<etichet>> astfel nct
putem specifica explicit din care bucl se iese: End LOOP <<etichet>>.

Cursorul Explicit
Este folosit atunci cnd n urma interogrii rezult mai mult de o nregistrare.
Exemplu: se declar un cursor explicit pentru a obine numele i zile naionale pentru rile din Asia
Declare
CURSOR wf_holiday_cursor IS
Select country_name, national_holiday_date
From wf_countries where region_id IN (30, 34, 35);
v_country_name
wf_countries.country_name%TYPE;
v_holiday
wf_countries.nationa_holiday_date%TYPE;
Begin
OPEN wf_holiday_cursor;
--nti se deschide cursorul
LOOP
-- bucl pentru parcurgerea tuturor nrgistrrilor obinute
FETCH wf_holiday_cursor INTO v_country_name, v_holiday;
EXIT WHEN wf_holiday_cursor%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(v_country_name || || v_holiday);
End LOOP;
CLOSE wf_holiday_cursor;
--se nchide cursorul

Laboratoare SGBD Informatic anul II Instructor Vrlan Simona-Elena


End;
Paii pentru folosirea unui cursor:
1. declare: declare nume_cursor IS instruciune_select; (selectul nu va mai conine clauza INTO)
2. open: open nume_cursor; - cursorul este poziionat pe prima nregistrare
3. fetch parcurgerea fiecrei nregistrri: fetch nume_cursor INTO variabil1, variabil2, . . .
4. close: close nume_cursor;
Structura Record n cursor
Este folosit pentru a uura munca cnd vrem s selectm toate cmpurile dintr-un tabel.
Declare
CURSOR wf_holiday_cursor IS
Select *
From wf_countries where region_id IN (30, 34, 35);
v_holiday_record wf_holiday_cursor%ROWTYPE;
Begin
OPEN wf_holiday_cursor;
LOOP
FETCH wf_holiday_cursor INTO v_holiday_record;
EXIT WHEN wf_holiday_cursor%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(v_holiday_record .v_country_name );
End LOOP;
CLOSE wf_holiday_cursor;
End;
Alte atribute ale cursorului explicit sunt: %ISOPEN, %NOTFOUND, %FOUND, %ROWCOUNT
Cursor FOR LOOP
For nume_record IN nume_cursor LOOP -- nume_record este un cursor declarat implicit.
Instruciuni;
...
End LOOP;
Exemplu:
Declare
CURSOR wf_holiday_cursor IS
Select *
From wf_countries where region_id IN (30, 34, 35);
Begin
FOR v_holiday_record IN wf_cursor LOOP
-- v_holiday_record a fost implict declarat ca wf_holiday_cursor%ROWTYPE
EXIT WHEN wf_holiday_cursor%NOTFOUND; -- sau wf_holiday_cursor%ROWCOUNT>5
DBMS_OUTPUT.PUT_LINE(v_holiday_record .v_country_name );
End LOOP;
-- nu se folosete OPEN i CLOSE cursor
End;
!n loc s folosim cursor se mai poate face i aa:
FOR v_holiday_record IN (Select * from wf_countries where region_id IN (30, 34, 35); ) LOOP

Laboratoare SGBD Informatic anul II Instructor Vrlan Simona-Elena


Cursor cu parametri
CURSOR nume_cursor [(nume_parametru tip, . . .)] IS
Instructiune select; -- fr clauza INTO
Exemplu:
Declare
CURSOR wf_holiday_cursor(p_region NUMBER) IS
Select * from wf_countries where region_id =p_region ;
Begin
FOR v_holiday_record
IN
wf_cursor(30)
LOOP
EXIT WHEN wf_holiday_cursor%ROWCOUNT>5
DBMS_OUTPUT.PUT_LINE(v_holiday_record .v_country_name );
End LOOP;
End;
Cursor FOR UPDATE
CURSOR nume_cursor IS
Select . . .from . . .
FOR UPDATE [OF referin_coloan] [NOWAIT | WAIT n];
-referin_coloana este coloana ale crei rnduri le blocam
- dac rndurile au fost deja blocate nowait returneaz imediat eroare. Dac se omite nowait atunci serverul
Oracle va atepta pn cnd rndurile sunt disponibile
- wait n ateapt n secunde i returneaz eroare dac alt sesiune blocheaz rndurile
Cnd declarm un cursor FOR UPDATE fiecare rnd este blocat cnd deschidem cursorul. Acest lucru
previne modificarea cursorului de ctre ali utilizatori ct timp cursorul este deschis, dar nu previne citirea
rndurilor. Ne permite de asemenea s modificm noi cursorul prin clauza WHERE CURRENT OF pentru a ne
referi la cea mai recent FETCH nregistrare: UPDATE employees SET salary = . . . WHERE CURRENT OF
emp_cursor. Aceast clauz este folosit doar cu UPDATE i DELETE.
Declare
CURSOR wf_holiday_cursor IS
Select * from wf_countries where region_id= 30
FOR UPDATE of region_id NOWAIT;
Begin
FOR v_holiday_record
IN
wf_cursor
LOOP
UPDATE wf_countries
SET region_id=31
WHERE CURRENT OF wf_holiday_cursor;
End LOOP;
COMMIT;
End;
! De asemenea exist cursoare imbricate i se deschid pe rnd i se nchid n ordinea descresctoare
deschiderii lor.

Tratarea EXCEPIILOR
Exception handler este poriunea de program care definete aciunile ce au loc cnd o excepie apare
EXCEPTION

Laboratoare SGBD Informatic anul II Instructor Vrlan Simona-Elena


WHEN exception1 [OR exception2] THEN -- NO_DATA_FOUND OR TOO_MANY_ROWS
Instruciuni;
...
[WHEN OTHERS THEN
Instruciuni; . . .]
Cele de mai sus sunt excepii Oracle implicite. Exist i excepii non-predefinite. n acest sens orice
programator poate declara explicit un anumit timp de excepie pentru a prinde o eroare nedefinit. Pentru aceasta
trebuie:
1. declarate n DECLARE cu tipul EXCEPTION
2. asociem un numr de eroare standard Oracle ORA-n cu funcia PRAGMA EXCEPTION_INIT
3. tratarea erorii in seciunea EXCEPTION
Exemplu:
Declare
e_insert_except EXCEPTION;
(1)
PRAGMA EXCEPTION_INIT(e_insert_except, -01400);
(2)
Begin
Insert into departments (department_id, department_name) values (280, NULL);
EXCEPTION
WHEN e_insert_except
(3)
THEN DBMS_OUTPUT.PUT_LINE(insert failed);
End;
Putem lansa o eroare i n seciunea BEGIN astfel:
Begin
IF . . . THEN RAISE v_eroare;
EXCEPTION
WHEN v_eroare THEN . . .
End;

PROCEDURI
CREATE [OR REPLACE] PROCEDURE nume [parametri] IS | AS
[variabile, cursoare];
Begin
Instruciuni SQL i PL/SQL;
[Exception
WHEN exception_nume;]
End [nume];
Exemplu:
CREATE OR REPLACE PROCEDURE add_salariat IS
v_id salariat.salariat_id%TYPE:=20;
v_nume
salariat.salariat_nume%TYPE:=Mihaela;
Begin
INSERT INTO salariat values(v_id, v_nume);
DBMS_OUTPUT.PUT_LINE(SQL%ROWCOUNT ); --folosit pentru a testa dac insertul are loc
End;

Laboratoare SGBD Informatic anul II Instructor Vrlan Simona-Elena


Invocarea Procedurilor
! Nu se poate invoca o procedur n cadrul unei instruciuni SQL precum SELECT.
Begin
add_salariat;
End;
Crearea procedurilor cu PARAMETRI
CREATE OR REPLACE PROCEDURE add_salariat
(v_id IN salariat.salariat_id%TYPE, -- este numit parametru formal
v_nume IN salariat.salariat_nume%TYPE ) IS
Begin
INSERT INTO salariat values(v_id, v_nume);
DBMS_OUTPUT.PUT_LINE(SQL%ROWCOUNT );
End;
Begin
add_salariat(20, Mihaela); -- parametru actual
End;
Modul parametrilor este specificat n declararea parametrilor formali dup numele acestora i nainte de
tipul lor. Un IN parametru ofer valori pentru prelucrare(pot fi doar citii n cadrul procedurii, nu pot fi modificai),
un parametru OUT returneaz o valoare apelantului, iar un IN OUT parametru ofer o valoare de intrare care apoi
poate fi returnat ca valoare modificat.

FUNCII
CREATE [OR REPLACE] FUNCTION nume [parametri [mode] tip] RETURN tip IS | AS
[variabile];
Begin
Instruciuni SQL i PL/SQL;
RETURN expresie;
End [nume];
Apelul se face: variabil := nume_funcie(parametri); SAU nume_funcie(parametri);
! Pentru a terge o procedur sau o funcie stocat se folosete DROP PROCEDURE|FUNCTION nume;

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