Sunteți pe pagina 1din 224

Capitolul 1:Modelul relaional

Modelul relaional reprezint datele sub forma unor structuri bidimensionale, asemntoare
tabelelor. Apariia sa s-a datorat nevoii de a uura concepia, accesarea i procesarea datelor.
Modelele de date existente anterior (ierarhic i reea) erau extrem de complexe i necesitau personal
extrem de specializat pentru a concepe i a naviga n baza de date. De asemenea, datorit faptului c
performanele acestor tipuri de baze de date erau dependente de proiectarea i designul lor, pentru a
asigura o performan corespunztoare trebuia investit foarte mult efort n activitatea de proiectare.
Aceste motive fceau ca disponibilitatea de personal adecvat s fie foarte limitat. n plus, datorit
complexitii lor, sistemele care foloseau aceste modele erau foarte greu de instalat. n sfrit, dar
nu n ultimul rnd, modelele ierarhice i reea necesitau ca programatorul aplicaiei s cunoasc
implementarea fizic a bazei de date (legturile existente ntre nregistrri) i cunotine despre
limbajul de manipulare a datelor corespunztor.
Modelul relaional este o soluie pentru rezolvarea acestor probleme. Dei sistemul software necesar
unui model relaional este foarte complex, nvarea limbajului de definire a datelor i a celui de
manipulare a datelor necesit mult mai puin timp i efort dect cele corespunztoare modelelor
ierarhic i reea. De asemenea, proiectarea unui sistem care folosete modelul relaional este
flexibil, astfel nct modificrile sunt destul de uor de implementat, reducndu-se astfel efortul
corespunztor fazei de proiectare a bazei de date. n plus, simplitatea modelului relaional i a
limbajului sau de manipulare a datelor permite utilizatorilor s execute propriile lor manipulri.
Conceptele teoretice care formeaz baza modelului relaional au aprut la nceputul anilor 70, n
principal datorit lui Edgar F. Codd. Acest model difer de modelele precedente prin aceea c nu se
bazeaz pe dependenele de secven i cale. Modelele existente anterior permiteau accesul la date
prin ci specificate de o schem. Cum programele asociate depindeau de cile diferitelor nregistrri
din baza de date, dac, datorit unei schimbri de design, calea de acces pentru o nregistrare se
schimba, era necesar i modificarea programului de acces la datele respective, pentru a lua n
considerare aceast schimbare. Pe de alt parte, modelul relaional nu folosete cile de acces n
structura sa logic sau n limbajul sau de manipulare a datelor. De asemenea, n modelele ierarhic i
reea datele puteau fi accesate n mai mult de o secven, iar programele de aplicaie utilizau
secvena respectiv a datelor. Evident, dac secvena datelor era schimbat, programul trebuia
schimbat pentru a lua n considerare noua secven. Modelul relaional nu utilizeaz o anumit
secven n structura sa logic sau n limbajul su de manipulare. Aceast independen sporit a
datelor permite o tranziie mai uoar la noi relaii ntre date.
Modelul relaional nu este orientat spre sistemul de calcul, adic modelul nu include regulile,
structurile i operaiile referitoare la implementarea fizic a unui sistem de baze de date. De fapt,
unul dintre principalele obiective ale sistemului relaional este separarea clar ntre aspectele fizice
i cele logice ale unei baze de date. Spre deosebire de modelele menionate anterior, utilizatorul
poate obine date specifice din modelul relaional folosind un limbaj ne-procedural care i permite
s descrie datele cerute n loc de navigaia folosit.
n acelai timp, modelul relaional i operaiile folosite de ctre acesta au la baz o riguroas
fundamentare matematic; s-au creat algebra relaional i calculul relaional. Totui, pe lng
avantajele clare ale rigurozitii matematice, matematizarea excesiv a modelului i a limbajului de
manipulare creeaz o problem datorit faptului c n afara mediului academic doar un procent mic
de utilizatori au pregtirea necesar pentru a le nelege. Din fericire, folosirea modelului relaional
nu necesit neaprat nelegerea n profunzime a matematicii pe care este bazat. Operaiile de
manipulare a datelor pot fi privite ca o serie de operaii de proiecie, filtrare, reuniune, intersecie,
etc. asupra datelor din tabele.
12

Dei are la rndul lui imperfeciuni, modelul relaional a devenit n ultima vreme principalul model
de baze de date i a fost adoptat de majoritatea productorilor de software din acest domeniu.
Principalele sale avantaje sunt simplitatea, fundamentarea matematic riguroas i independena
datelor, adic separarea aspectelor logice ale acestora de cele fizice.
1.1. Concepte de baz ale modelului relaional
n general, definirea unui model de date presupune precizarea i identificarea urmtoarelor
elemente:
Structurile de date folosite
Operatorii care acioneaz asupra structurilor de date
Restriciile care trebuie impuse pentru meninerea corectitudinii datelor, numite i restricii de
integritate.
Aceast seciune prezint pe larg fiecare dintre aceste componente ale modelului relaional.
n modelul relaional datele sunt reprezentate ca structuri bidimensionale, numite relaii. O relaie
este alctuit dintr-un numr fix de elemente numite atribute, fiecare dintre acestea putnd lua
valori ntr-o mulime finit, numit domeniu. Numrul de atribute al unei relaii se numete aritatea
relaiei.
relaie (atribut_1, atribut_2, ..., atribut_n)
De exemplu datele despre angajaii unei firme se pot reprezenta ca o relaie de aritate 7, dup cum
urmeaz:
salariat (cod_salariat, nume, prenume, adresa, dat_natere, sex, cod_departament)
Elementele unei relaii se numesc tupluri sau nregistrri. De obicei relaiile sunt reprezentate sub
forma unor tabele, n care fiecare rnd reprezint un tuplu i fiecare coloan reprezint valorile
tuplurilor corespunztoare unui anumit atribut.
salariat
cod_
nume
salariat
S1
Ion
S2
Popescu
S3
Ionescu
S4
Costache

prenume

Adresa

dat_natere

sex

Cosmin
Vasile
Gina
Viorel

Str. Jiului Nr.3

01/01/1970
15/11/1956
28/02/1976
12/02/1975

M
M
F
M

Str. Valea Alb Nr.4


Str. Criana Nr. 11

cod_
departament
D1
D1
D2
D1

Relaiile ce constituie o baz de date trebuie s satisfac mai multe condiii, dup cum urmeaz:
1. Fiecare atribut trebuie s poarte un nume, care este unic n cadrul relaiei. Modelul relaional nu
permite ca dou atribute din cadrul aceleiai relaii s poarte acelai nume. Pe de alt parte, este
posibil ca dou atribute din dou relaii diferite s poarte acelai nume.
2. Fiecare atribut poate avea doar valori atomice, deci care nu se pot descompune din punct de
vedere logic. S presupunem, de exemplu, c un productor de automobile atribuie fiecrui
automobil fabricat un cod de identificare, care se obine prin concatenarea mai multor coduri,
reprezentnd marca automobilului, culoarea, fabrica unde este produs, seria i numrul de
fabricaie, etc. Atunci, definirea acestui cod de identificare ca atribut al unei relaii ar nclca
13

aceast regul, deoarece fiecare valoare a atributului s-ar putea descompune n mai multe valori
cu semnificaie logic.
3. Fiecare tuplu este unic. Nu sunt permise tupluri identice (duplicat). n plus, unicitatea unui tuplu
nu este limitat la datele existente: fiecare tuplu trebuie s fie unic tot timpul.
Aceasta nseamn c ntr-o relaie exist ntotdeauna unul sau mai multe atribute care asigur c
tuplul va rmne unic tot timpul. Un atribut sau set de atribute care identific n mod unic un tuplu
se numete cheie candidat sau mai simplu cheie. Pentru fiecare relaie se alege din mulimea
cheilor candidate o cheie care se numete cheie primar a relaiei. Eventualele alte chei candidate,
diferite de cheia primar, se numesc chei alternative. Cnd mai mult de un singur atribut este
necesar pentru a crea o cheie, se spune c avem o cheie compus. n cazul unei chei compuse,
atributele care fac parte din cheie sunt alese astfel nct nici unul s nu fie n plus, adic nici un
atribut nu poate fi ters din cheia candidat astfel nct partea din cheia candidat care rmne s
identifice nc n mod unic tuplurile; de aceea, se spune c o cheie trebuie sa fie minimal.
Uneori, n unele tupluri dintr-o relaie, un atribut poate fi necunoscut sau neaplicabil. Pentru a
reprezenta un astfel de atribut se folosete o valoare convenional, notat cu Null. Ca regul
general, nici unul dintre atributele care alctuiesc cheia primar nu poate avea valoarea Null pentru
nici unul din tuplurile relaiei.
Exemplu:
Pentru relaia salariat definit mai sus, o cheie candidat este cod_salariat. Dac se
presupune c nume, prenume i dat_natere identific n mod unic salariatul, atunci
combinaia acestor trei atribute este o alt cheie candidat, care, datorit faptului c este alctuit
din mai multe atribute, se numete i cheie compus. Dac cheia cod_salariat este aleas cheie
primar, atunci combinaia celor trei atribute (nume, prenume i dat_natere) devine cheie
alternativ.
n alegerea cheilor candidate s-a inut cont de principiul minimalitii n sensul c din cheia
compus nume, prenume i dat_natere nu poate fi ters nici un atribut i nici nu mai
trebuie adugat altul, aceste trei atribute identificnd n mod unic tuplurile. De exemplu, combinaia
(nume, prenume, dat_natere, cod_departament) nu este o cheie a relaiei salariat
pentru c i n absena atributului cod_departament, un salariat este identificat n mod unic de
primele trei atribute. Observm c tuplul identificat prin valoarea cheii primare egal cu S2 are
atributul adresa necunoscut, adic acesta are valoarea Null. Prin urmare, atributul adresa nu
poate fi cheie primar i nici nu poate intra n componena unei chei compuse care este i cheie
primar.
Se numete cheie strin un atribut sau o mulime de atribute ale unei relaii R1 care exist i ntr-o
alt relaie R2, nu neaprat distinct de R1, i care formeaz cheia primar a relaiei R2. n cazul
acesta, cheia strin din R1 se spune c face referin la cheia primar din R2. Valorile pe care le ia
cheia strin, dac nu sunt nule, trebuie s se gseasc printre valorile cheii primare la care face
referin.
Exemplu:
Dac mai definim o relaie de aritate 3, dup cum urmeaz:
departament (cod_departament, denumire, localitate)
cod_departament
D1

denumire
Analiz financiar

localitate
Bucureti
14

D2
D3
D4

Depozit
Contabilitate
Magazin

Piteti
Constana
Piteti

pentru evidena departamentelor din firm, atributul cod_departament din relaia salariat
devine cheie strin care face referin la cheia primar a relaiei departament. Valoarea cheii
strine cod_departament din relaia salariat trebuie ori s fie ori Null, ori s coincid cu o
valoare a cheii primare la care face referin. Prin urmare, dac atributul cod_departament din
relaia salariat ar fi avut pentru un anumit tuplu valoarea D5, valoare ce nu se regsete printre
valorile cheii primare cod_departament din relaia departament, atunci s-ar fi nclcat o
regul de integritate.
Exist posibilitatea ca o cheie strin s fac referin la cheia primar a propriei relaii. Pentru a
ilustra acest lucru, s adugm la relaia salariat un nou atribut cod_manager, reprezentnd
codul superiorului ierarhic al salariatului (facem presupunerea c un angajat poate avea cel mult un
superior ierarhic).
cod_
salariat
S1
S2
S3
S4

nume

prenume

.....

cod_manager

Ion
Popescu
Ionescu
Costache

Cosmin
Vasile
Gina
Viorel

.....
.....
.....
.....

S1
S1
S2

Deci salariatul cu codul S1 este superiorul ierarhic al salariailor cu codurile S2 i S3, salariatul cu
codul S2 este superiorul ierarhic al salariatului cu codul S4, iar S1 nu are un superior ierarhic.
4. Navigaia n cadrul modelului relaional se face prin intermediul valorii pe care o ia un atribut.
Aceasta nseamn c limbajul de interogare va prelua ca parametri de intrare doar numele unor
atribute i valorile posibile ale acestora, corespunztoare cerinei utilizatorului, i va returna
tuplurile care satisfac aceast cerin. Spre deosebire de alte modele, nu exist legturi ntre
tupluri i deci nu exist dependen de calea urmat.
5. Tuplurile pot fi prezentate utilizatorului n orice ordine. Deci acesta nu trebuie s fac nici o
presupunere n privina ordinii tuplurilor.
6. Atributele pot fi prezentate n orice ordine, deci utilizatorul nu trebuie s fac nici o presupunere
n privina ordinii acestora. Cu alte cuvinte, n modelul relaional nu exist dependen de
secven. De exemplu, dei relaiile
Salariat (cod_salariat, nume, prenume, adresa, dat_natere, sex, cod_departament)
i
Salariat (cod_salariat, nume, prenume, cod_departament, dat_natere, sex, adresa)
par diferite, ele sunt echivalente funcional pentru c au atribute identice, chiar dac sunt n alt
ordine.
7. Relaiile pot fi manipulate pentru a furniza utilizatorului diferite vederi asupra datelor, rezultatul
fiind noi relaii. Cu alte cuvinte, rezultatul manipulrii relaiilor sunt noi relaii. n plus, relaiile
produse ca rezultat al comenzilor limbajului de interogare a datelor satisfac toate regulile la care
sunt supuse relaiile iniiale.
15

1.2. Constrngeri de integritate


Pentru asigurarea integritii datelor, o baz de date trebuie s satisfac un numr de constrngeri,
numite constrngeri de integritate. Constrngerile de integritate ale modelului relaional se pot
mpri n dou clase: constrngeri structurale, care trebuie satisfcute de orice baz de date care
folosete modelul relaional i constrngeri de comportament, care sunt specifice fiecrei baze de
date particulare.
Constrngerile de integritate structurale exprim proprieti fundamentale, inerente modelului
relaional i sunt n general specificate la definirea bazei de date, ca parte a schemei bazei de date.
n modelul relaional exist dou tipuri de constrngeri structurale: de entitate i de referin. Ele au
fost menionate mai nainte, cnd am vorbit despre proprietile sistemului relaional, fr ns a le
meniona explicit numele.
1. Integritatea entitii: O cheie primar nu poate conine atribute ce pot avea valoarea Null. n plus,
prin nsi definiia unei chei primare, ea trebuie s fie unic i minimal.
2. Integritatea referirii: Valoarea unei chei strine trebuie ori s fie ori Null, ori s coincid cu o
valoare a cheii primare la care face referin.
Aceste dou tipuri de constrngeri pot fi impuse n Oracle prin simpla lor adugare la definiia
tabelelor respective, vezi seciunea 6.1.3.
Constrngerile de integritate de comportament sunt specifice unei anumite baze de date i in cont
de semnificaia valorilor atributelor din baza respectiv. De exemplu, constrngerile de domeniu
restricioneaz valorile unui atribut la o anumit mulime, iar constrngerile sintactice se pot referi
la tipul datelor, lungimea atributelor, etc. Constrngerile de comportament pot exprima legturi
ntre valorile unor atribute diferite, de exemplu valoarea unui atribut este dependent de valoarea
altui atribut sau set de atribute sau o expresie format din valorile mai multor atribute trebuie s se
ncadreze n anumite limite, etc.
Constrngerile de comportament pot fi impuse n Oracle fie prin adugarea lor la definiia tabelelor
(vezi seciunea 6.1.3), fie prin definirea unor secvene de program, numite declanatori (triggers)
care sunt ataate tabelelor i care intr n aciune la nclcarea acestor constrngeri, mpiedicnd
operaiile care ar duce la nclcarea integritii (vezi seciunea 9.16).
1.3. Operatorii sistemului relaional
n afara relaiilor i a proprietilor acestora, modelul relaional este definit i prin setul de operaii
care se pot efectua asupra acestor relaii. Exist dou moduri de descriere matematic a acestor
operatori, i anume algebra relaional i calculul relaional, vezi [3] [Basca97].
Algebra relaional, introdus de ctre Codd, este format dintr-o mulime de opt operatori, ce
acioneaz asupra relaiilor i genereaz tot o relaie. Operatorii algebrei relaionale sunt fie
operatorii tradiionali pe mulimi (UNION, INTERSECT, DIFFERENCE, PRODUCT), fie
operatori relaionali speciali (PROJECT, SELECT, JOIN, DIVISION). Cum ieirea generat de
fiecare dintre aceti operatori este tot o relaie, este posibil combinarea i compunerea lor. Cinci
dintre operatori (PROJECT, SELECT, DIFFERENCE, PRODUCT, UNION) sunt operatorii
primitivi ai limbajului, iar ceilali trei (JOIN, DIVISION, INTERSECT) sunt operatori derivai,
putnd fi definii n funcie de primii. Unii dintre operatori se aplic unei singure relaii (operatori
unari), iar alii opereaz asupra a dou relaii (operatori binari).
16

Calculul relaional reprezint o adaptare a calculului predicatelor la domeniul bazelor de date


relaionale. Ideea de baz este de a identifica o relaie cu un predicat. Pe baza unor predicate iniiale,
prin aplicarea unor operatori ai calculului cu predicate (conjuncia, disjuncia, negaia,
cuantificatorul existenial i cel universal) se pot defini noi predicate, adic noi relaii.
Algebra relaional i calculul relaional sunt echivalente unul cu cellalt, n sensul c orice relaie
care poate fi definit n algebra relaional poate fi definit i n calculul relaional i reciproc.
1.3.1 Algebra relaional i limbajul SQL
n prezent, limbajul dominant folosit pentru interogarea bazelor de date relaionale este SQL
(Structured Query Language), care este un limbaj bazat pe operaiile algebrei relaionale. Cu alte
cuvinte, orice operator al algebrei relaionale poate fi descris folosind comanda SELECT a
limbajului SQL cu diverse clauze. n ceea ce urmeaz vom defini operatorii algebrei relaionale i
vom exemplifica modul de implementare a acestor operatori n SQL. Pentru o explicaie a sintaxei
comenzii SELECT din limbajul SQL vezi seciunea 8.1.
Not: Comanda SELECT din limbajul SQL nu reprezint acelai lucru i nu trebuie confundat cu
operatorul SELECT din algebra relaional.
Operatorul PROJECT (proiecia)
Acesta este un operator unar care are ca parametri un atribut sau mai multe atribute ale unei relaii i
care elimin din relaie toate celelalte atribute, producnd o submulime pe vertical a acesteia.
Datorit faptului c suprimarea unor atribute poate avea ca efect apariia unor tupluri duplicate,
acestea vor fi eliminate din relaia rezultat deoarece, prin definiie, o relaie nu poate conine
tupluri cu valori identice. Notaiile folosite de obicei pentru acest operator sunt X(R) i
PROJECT(R, X) unde R reprezint relaia, iar X este atributul sau mulimea de atribute care
constituie parametrii proieciei.
Exemplu
R A
B
x1 y1
x1 y1
x1 y2
x2 y2

C
z1
z2
z2
z1

Proiecie

C
z1
z2
z2
z1

A
x1
x1
x1
x2

Eliminare duplicate

C,A(R) C
z1
z2
z1

n SQL, proiecia fr dubluri se obine folosind comanda SELECT cu specificaia DISTINCT:


SELECT DISTINCT C, A
FROM R;
n cazul folosirii comenzii SELECT fr clauza DISTINCT se va obine proiecia cu dubluri:
SELECT C, A
FROM R;
Operatorul SELECT (selecia)

17

A
x1
x1
x2

Acesta este un operator unar care este utilizat pentru extragerea tuturor tuplurilor dintr-o relaie care
satisfac o condiie specificat, producnd astfel o submulime pe orizontal a relaiei. Condiia
este o formul logic ce poate conine nume de atribute, constante, operatori logici (AND, NOT,
OR), operatori de comparaie (<, =, >, <=, >=, !=). Spre deosebire de alte limbaje de programare,
cum ar fi Pascal, limbajul SQL acord operatorilor de comparaie o prioritate mai mare dect
operatorilor logici, reducndu-se astfel numrul de paranteze necesare pentru expresii complexe.
Notaiile folosite de obicei pentru acest operator sunt C(R) sau SELECT(R, C), unde R reprezint
relaia, iar C este condiia care trebuie satisfcut de tuplurile selectate.
Exemplu
R A
B
x1 y1
x1 y1
x1 y2
x2 y2

C
z1
z2
z2
z1

A
x1
x1
x1

A=x1 OR B=y1(R)

B
y1
y1
y2

C
z1
z2
z2

n SQL, selecia se obine folosind comanda SELECT cu clauza WHERE:


SELECT *
FROM R
WHERE A = x1 OR B = y1;
Combinarea seleciei cu proiecia fr dubluri se face n modul urmtor:
SELECT DISTINCT C, A
FROM R
WHERE A = x1 OR B = y1;
R A
x1
x1
x1
x2

B
y1
y1
y2
y2

C
z1
z2
z2
z1

selecie

A
x1
x1
x1

B
y1
y1
y2

C
z1
z2
z2

proiecie cu
eliminarea duplicatelor

C
z1
z2

A
x1
x1

C
z1
z2
z2

A
x1
x1
x1

Combinarea seleciei cu proiecia cu dubluri se face n modul urmtor:


SELECT C, A
FROM R
WHERE A = x1 OR B = y1;
R A
x1
x1
x1
x2

B
y1
y1
y2
y2

C
z1
z2
z2
z1

selecie

A
x1
x1
x1

B
y1
y1
y2

C
z1
z2
z2

PRODUCT (produsul cartezian)


18

proiecie fr
eliminarea duplicatelor

Acesta este un operator binar. Produsul cartezian a dou relaii R i S este mulimea tuturor
tuplurilor care se obin prin concatenarea unui tuplu din R cu un tuplu din S. Prin urmare, dac
aritatea relaiei R este m, iar aritatea relaiei S este n, atunci produsul cartezian dintre R i S va avea
aritatea m + n. Notaiile folosite de obicei pentru acest operator sunt R S, PRODUCT(R, S),
TIMES(R, S).
Exemplu
R A
B
x1 y1
x2 y1
x3 y2

C
z1
z2
z1

S D
z1
z2

E
u1
u2

RS

A
x1
x1
x2
x2
x3
x3

B
y1
y1
y1
y1
y2
y2

C
z1
z1
z2
z2
z1
z1

D
z1
z2
z1
z2
z1
z2

E
u1
u2
u1
u2
u1
u2

Produsul cartezian poate fi exprimat n SQL printr-o comand SELECT pe mai multe tabele fr
clauza WHERE:
SELECT *
FROM R, S;
Compatibilitate la reuniune
Dou relaii R i S se numesc compatibile la reuniune dac ele conin acelai numr de atribute (au
aceeai aritate) i atributele cu acelai numr de ordine din fiecare relaie au acelai domeniu din
care pot lua valori. Operatorii UNION, INTERSECT, DIFFERENCE, prezentai n continuare, sunt
operatori binari ce nu pot fi aplicai dect asupra relaiilor compatibile la reuniune.
UNION (reuniunea)
Reuniunea a dou relaii R i S este mulimea tuplurilor aparinnd fie lui R, fie lui S. Reuniunea
celor dou mulimi va cuprinde fiecare tuplu o singur dat, chiar dac el face parte din amndou
mulimile. Reuniunea se poate aplica doar relaiilor compatibile la reuniune. Notaiile folosite de
obicei pentru acest operator sunt R S sau UNION(R, S). Reuniunea este o operaie binar
comutativ, adic R S = S R.
Exemplu
R A
B
x1 y1
x2 y1
x3 y1

S C
x1
x1

D
y1
y2

RS

A
x1
x2
x3
x1

B
y1
y1
y1
y2

n SQL reuniunea se poate exprima folosind operatorul UNION:


SELECT A, B
FROM R
UNION
SELECT C, D
FROM S;
19

DIFFERENCE (diferena)
Diferena a dou relaii R i S este mulimea tuplurilor care aparin lui R, dar nu aparin lui S.
Diferena este o operaie binar ne-comutativ, adic R S S R, care se poate aplica doar
relaiilor compatibile la reuniune. Notaiile folosite de obicei pentru acest operator sunt R - S,
DIFFERENCE(R, S), MINUS(R, S).
Exemplu
R A
B
x1 y1
x2 y1
x3 y1

S C
x1
x1

D
y1
y2

RS

A
x2
x3

B
y1
y1

n SQL diferena se poate exprima folosind operatorul MINUS:


SELECT A, B
FROM R
MINUS
SELECT C, D
FROM S;
n plus, diferena poate fi simulat i prin operatorul NOT EXISTS. De exemplu, comanda SQL de
mai sus este echivalent cu urmtoarea:
SELECT A, B
FROM R
WHERE NOT EXISTS
(SELECT *
FROM S
WHERE R.A = S.C AND R.B = S.D);
Not: Pentru simplitate, n comanda SQL de mai sus am presupus c nici un atribut din relaiile R
sau S nu poate avea valoarea Null. Dac, de exemplu, atributul A din relaia S i atributul C din
relaia S pot avea valoarea Null, atunci expresia R.A = S.C trebuie nlocuit cu R.A = S.C OR (R.A
IS NULL AND S.C IS NULL). Acest lucru se datoreaz faptului c n SQL, expresia NULL =
NULL are valoarea False.
INTERSECT (intersecia)
Intersecia a dou relaii R i S este mulimea tuplurilor care aparin att lui R ct i lui S. Intersecia
este o operaie binar comutativ care se poate aplica doar relaiilor compatibile la reuniune.
Notaiile folosite de obicei pentru acest operator sunt R S, INTERSECT(R, S), AND(R, S).
Intersecia este un operator derivat, putnd fi exprimat cu ajutorul reuniunii i diferenei: R S = R
(R S) sau R S = S (S R)
Exemplu
R A
B
x1 y1
x2 y1
x3 y1

S C
x1
x1

D
y1
y2

RS

A
x1

20

B
y1

n SQL diferena se poate exprima folosind operatorul INTERSECT:


SELECT A, B
FROM R
INTERSECT
SELECT C, D
FROM S;
n plus, intersecia poate fi simulat i prin operatorul EXISTS. De exemplu, comanda SQL de mai
sus este echivalent cu urmtoarea:
SELECT A, B
FROM R
WHERE EXISTS
(SELECT *
FROM S
WHERE R.A = S.C AND R.B = S.D);
n cazul cnd operatorii UNION, DIFFERENCE sau INTERSECT se aplic unor relaii care sunt
obinute prin selecie din aceeai relaie, atunci acetia pot fi simulai prin aplicarea operatorilor
logici corespunztori (OR, AND NOT, AND) asupra condiiilor de selecie. De exemplu,
urmtoarele comenzi sunt echivalente:
SELECT A, B
FROM R
WHERE A = x1
MINUS
SELECT A, B
FROM R
WHERE B = y1;
SELECT A, B
FROM R
WHERE A = x1 AND NOT B = y1;
DIVISION (diviziunea)
Diviziunea este o operaie binar care se aplic asupra a dou relaii R i S, astfel nct mulimea
atributelor lui R include mulimea atributelor lui S. Dac R este o relaie cu aritatea m, iar S o relaie
cu aritatea n, unde m > n, atunci diviziunea lui R la S este mulimea tuplurilor de dimensiune m n
la care, adugnd orice tuplu din S, se obine un tuplu din R. Notaiile utilizate cel mai frecvent sunt
R S, DIVISION(R, S), DIVIDE(R, S).
Exemplu
R A
B
x1 y1
x1 y2
x1 y1
x2 y1
x2 y2

C
z1
z1
z2
z2
z2

S C
z1
z2

RS

A
x1

B
y1

21

Diviziunea este o operaie derivat care se exprim cu ajutorul diferenei, produsului cartezian i
proieciei: R S = R1 R2, unde R1 = X(R), R2 = X((R1 S) R), iar X este mulimea
atributelor lui R care nu exist n S. Pentru exemplul de mai sus:
R1

A
x1
x1
x2
x2

B
y1
y2
y1
y2

R1 S A
x1
x1
x2
x2
x1
x1
x2
x2

R2

A
x2
x2
x1

B
y1
y2
y2

R1 R2

A
x1

B
y1
y2
y1
y2
y1
y2
y1
y2

C
z1
z1
z1
z1
z2
z2
z2
z2

(R1 S) - R

A
x2
x2
x1

B
y1
y2
y2

C
z1
z1
z2

B
y1

Operatorul DIVISION este legat de cuantificatorul universal () care nu exist n SQL, dar care
poate fi simulat cu ajutorul cuantificatorului existenial (), care exist n SQL, utiliznd relaia: x
P(x) NOT x NOT P(x). Pentru a ilustra exprimarea operatorul DIVISION n cele dou moduri
(folosind cuantificatorul universal i cuantificatorul existenial), s considerm relaiile
student_curs i curs_fundamental de mai jos:
curs_student
cod_student Curs
S1
matematica
S1
Fizica
S1
Mecanica
S2
matematica
S2
informatica
S3
Fizica
S4
matematica
S4
Fizica

curs_fundamental
curs
matematica
fizica

curs_student curs_fundamental
curs
S1
S4
Atunci relaia curs_student curs_fundamental poate fi definit prin urmtoarea
ntrebare: care sunt studenii care urmeaz toate cursurile fundamentale? Alternativ, aceast relaie
poate fi definit prin ntrebarea: care sunt studenii pentru care nu exist curs fundamental care s
nu fie urmat de ctre acetia? Utiliznd a doua formulare, rezult c operatorul DIVISION poate fi
simulat n SQL prin doi operatori NOT EXISTS:
SELECT DISTINCT cod_student
FROM curs_student cs1
22

WHERE NOT EXISTS


(SELECT *
FROM curs_fundamental cf
WHERE NOT EXISTS
(SELECT *
FROM curs_student cs2
WHERE cf.curs = cs2.curs
AND cs1.cod_student = cs2.cod_student));
JOIN (compunerea, jonciunea)
Operatorul de compunere permite regsirea informaiei din mai multe relaii corelate. Compunerea
este o operaie binar care are ca rezultat o nou relaie n care fiecare tuplu este o combinaie a
unui tuplu din prima relaie cu un tuplu din a doua relaie.
Operatorul JOIN este un operator derivat, putnd fi simulat printr-o combinaie de produs cartezian,
selecie i proiecie. n general, se construiete un produs cartezian, se elimin tupluri prin selecie i
se elimin atribute prin proiecie. Dup modalitile n care se face selecia i proiecia, se disting
mai multe tipuri de compunere: THETA-JOIN, NATURAL-JOIN, SEMI-JOIN, OUTER-JOIN.
Fiecare dintre acestea vor fi prezentate n continuare.
THETA-JOIN
Operatorul THETA-JOIN combin perechile de tupluri din dou relaii, cu condiia ca ntre valorile
atributelor specificate s existe o anumit legtur, adic s satisfac o anumit condiie specificat
explicit n cadrul operaiei. n cadrul condiiei operatorului THETA-JOIN se poate folosi orice
operator de comparaie (>, >=, <, <=, <>, =). n cazul n care este folosit operatorul de comparaie
=, tipul de compunere se numete EQUI-JOIN. Operatorul THETA-JOIN se reprezint de obicei cu
ajutorul simbolului
sub care se scrie condiia, R
S sau prin JOIN(R, S, condiie).
condiie

Exemplu
R A
B

S D

x1
x1
x2

y1
y1
y2

1
1
3

2
4
4

z1
z2
z2

C<D

x1
x2
x3

y1
y2
y3

1
3
5

2
4

z1
z2

Urmtorul exemplu ilustreaz realizarea operatorului THETA-JOIN n SQL:


SELECT *
FROM R, S
WHERE R.C < S.D;
NATURAL-JOIN (Compunerea natural)
Compunerea natural este o operaie binar comutativ care combin tupluri din dou relaii, R i S,
cu condiia ca atributele comune s aib valori identice. n cazul compunerii naturale atributele
specificate trebuie s aib acelai nume. Practic diferena dintre NATURAL-JOIN i EQUI-JOIN
const n faptul c n primul caz numele atributelor sunt identice iar n cel de al doilea caz acestea
sunt diferite. De obicei, compunerea natural se noteaz prin R
S sau JOIN(R, S).

23

Pentru dou relaii R i S, compunerea natural pe un set de atribute comune X const n efectuarea
succesiv a urmtoarelor operaii:
1. Se calculeaz produsul cartezian R S.
2. Se selecteaz din R S acele tupluri obinute pentru care valorile atributelor X din tuplul R sunt
identice cu valorile atributelor X din tuplul S.
3. Deoarece n relaia astfel obinut atributele X apar de dou ori (o dat provenind din R i o dat
din S), se elimin una dintre apariiile acestor atribute.
Exemplu
nr_lucrtor
1
2
3
4
5

lucrtor
cod_secie
S1
S1
S2
S1
S1

nr_atelier
1
2
1
2
1

lucrtor
atelier
nr_lucrtor cod_secie nr_atelier
1
S1
1
2
S1
2
3
S2
1
4
S1
2
5
S1
1

atelier
cod_secie nr_atelier
S1
1
S1
2
S2
1
S2
2

denumire
Proiectare
Informatica
Mecanica
Electrotehnica

denumire
Proiectare
Informatica
Mecanica
Informatica
Proiectare

n exemplul de mai sus, {cod_secie, nr_atelier} este cheie primar n tabelul atelier i
cheie strin n tabelul lucrtor.
Urmtorul exemplu ilustreaz realizarea compunerii naturale n SQL:
SELECT lucrtor.nr_lucrtor, lucrtor.cod_secie, lucrtor.nr_atelier, atelier.denumire
FROM lucrtor, atelier
WHERE lucrtor.cod_secie = atelier.cod_secie
AND lucrtor.nr_atelier = atelier.nr_atelier;
SEMI-JOIN (semi-compunerea)
Operaia de semi-compunere aplicat asupra a dou relaii R i S genereaz o relaie care conine
toate tuplurile din R corelate cu oricare din tuplurile din S. Operaia nu este comutativ i se noteaz
de obicei prin SEMI-JOIN(R, S).
Exemplu
R A
B
x1 y1
x2 y1
x3 y2
x4 y2

C
z1
z1
z1
z2

S B
y1
y2
y2

C
z1
z2
z2

D
u1
u2
u3

SEMIJOIN(R, S)

Urmtorul exemplu ilustreaz realizarea compunerii naturale n SQL:


SELECT DISTINCT R.A, R.B, R.C
24

A
x1
x2
x4

B
y1
y1
y2

C
z1
z1
z2

FROM R, S
WHERE R.B = S.B
AND R.C = S.C
OUTER-JOIN (compunere extern)
Operaia de compunere extern este o extindere a compunerii naturale. n cazul aplicrii
operatorului NATURAL-JOIN se pot pierde tupluri atunci cnd exist un tuplu ntr-una din relaii
care nu este corelat cu nici un tuplu din cealalt relaie. Operatorul OUTER-JOIN elimin acest
inconvenient. Practic, la aplicarea operatorului OUTER-JOIN, se realizeaz compunerea natural a
celor dou relaii, la care se adaug tuplurile din S care nu sunt coninute n compunere, completate
cu valori Null pentru atributele rmase din R. Operatorul se noteaz cu OUTERJOIN(R, S). Exist
i alte variante ale acestui operator, de exemplu o alt variant adaug la tuplurile obinute din
compunerea natural a lui R i S att tuplurile din R care nu sunt coninute n compunere ct i
tuplurile din S care nu sunt coninute n compunere, completnd restul cu Null. n mod evident,
aceast variant a operatorului se poate obine cu uurin din varianta prezentat de noi. Operatorul
OUTER-JOIN, n varianta prezentat de noi, este ne-comutativ.
Exemplu:
student
nr_stud
1
2
3
4
5

nume
Popescu
Ionescu
Ionescu
Costache
Matache

Prenume

cod_facult

Ion
Vasile
Viorel
Ion
Mihai

F1
F1
F2
F2
F1

facultate
cod_facul nume_facult
t
F1
Matematica
F2
Fizica
F3
Informatica
F4
Mecanica

OUTERJOIN (student, facultate)


nr_stud
nume
Prenume cod_facult
1
Popescu Ion
F1
2
Ionescu
Vasile
F1
3
Ionescu
Viorel
F2
4
Costache Ion
F2
5
Matache Mihai
F1
Null
Null
Null
F3
Null
Null
Null
F4

nume_facult
Matematica
Matematica
Fizica
Fizica
Matematica
Informatica
Mecanica

localitate
Bucureti
Bucureti
Piteti
Ploieti

localitate
Bucureti
Bucureti
Bucureti
Bucureti
Bucureti
Ploieti
Ploieti

n versiunea SQL folosit de Oracle, operatorul OUTER JOIN este specificat prin sufixul (+)
adugat la cmpul dup care se face compunerea, corespunztor tuplului ale crui atribute pot fi
completate cu Null:
SELECT student.nume_stud, student.nume, student.prenume,
facultate.cod_facult, facultate.nume_facult, facultate.localitate
FROM student, facultate
WHERE student.cod_facult (+) = facultate.cod_facult;

1.4 Tabele, rnduri, coloane

25

Modelul relaional este bazat pe matematica relaional i acest lucru se reflect n terminologia pe
care am prezentat-o pn acum. Pe de alt parte, folosirea acestui model n economie, unde
conceptele matematice sunt foarte puin sau deloc utilizate i nelese, a necesitat o nou
terminologie. Aa c, odat cu preluarea modelului relaional de ctre economie are loc o
transformare a terminologiei relaionale ntr-una care poate fi uor neleas de cei fr o pregtire
special n domeniu. Pentru cei care nu sunt experi n procesarea datelor, relaiile devin tabele,
tuplurile devin rnduri i atributele devin coloane. Acesta este i terminologia pe care o vom folosi
n continuare n aceast carte.
1.5. Sisteme de Gestiune a Bazelor de Date Relaionale (SGBDR).
n principiu, un sistem de gestiune a bazelor de date relaionale (SGBDR) este un SGBD care
utilizeaz drept concepie de organizare a datelor modelul relaional. n mod evident ns, aceast
definiie este mult prea general pentru a putea fi folosit n practic, deoarece modul de
implementare a modelului relaional difer de la un productor la altul. n 1985, Codd a publicat un
set de 13 reguli n raport cu care un SGBD poate fi apreciat ca relaional. Trebuie remarcat c nici
un SGBD comercializat n prezent nu satisface n totalitate regulile lui Codd, dar aceasta nu
mpiedic etichetarea acestora drept relaionale. Cu alte cuvinte, regulile lui Codd nu trebuie
folosite pentru a aprecia dac un sistem este sau nu relaional, ci msura n care acesta este
relaional, adic numrul regulilor lui Codd respectate de ctre acesta.
1.5.1. Regulile lui Codd
Regula 1. Regula reprezentrii logice a datelor:
ntr-o baz de date relaional, toate datele sunt reprezentate la nivel logic ntr-un singur mod, i
anume sub form de valori atomice n tabele.
Deci toate datele trebuie memorate sub form de tabele, iar valoarea corespunztoare interseciei
dintre un rnd i o coloan trebuie s fie atomic, adic s nu mai poat fi descompus din punct de
vedere logic. Aa cum am discutat mai nainte, un exemplu de nclcare a acestei reguli este
stocarea ca o singur coloan a unui cod al automobilului, obinut prin concatenarea mai multor
coduri, reprezentnd marca automobilului, culoarea, fabrica unde este produs, seria i numrul de
fabricaie, etc. Uneori aceast regul este nclcat n practic, dar acest lucru este de cele mai multe
ori semnul unui design de calitate slab, crend probleme de integritate a bazei de date.
Aceast regul este cea mai important dintre cele definite de Codd, iar un SGBD care nu respect
aceast regul nu poate fi n nici un caz considerat relaional.
Regula 2. Regula accesului la date:
Toate datele individuale din tabele trebuie s fie accesibile prin furnizarea numelui tabelului,
numelui coloanei i valorii cheii primare.
Conform modelului relaional, ntr-un tabel nu pot exista rnduri identice, iar fiecare rnd poate fi
identificat prin valoarea cheii primare. n consecin, orice dat individual poate fi identificat
folosind numele tabelului, al coloanei i valoarea cheii primare. Oracle nu respect aceast regul
deoarece permite existena a mai multe rnduri identice n acelai tabel. Totui, acest lucru poate fi
evitat, de exemplu prin definirea unei chei primare, care elimin implicit i posibilitatea existenei
rndurilor identice. Pe de alt parte, aceast regul este nclcat n Oracle i de existena
identificatorului de rnd, ROWID, care poate fi folosit pentru accesarea rndului respectiv.
Regula 3. Regula reprezentrii valorilor necunoscute:
26

Un sistem relaional trebuie s permit declararea i manipularea sistematic a valorilor Null, cu


semnificaia unor valori necunoscute sau inaplicabile.
Aceast regul, implic, de exemplu, c un SGBDR trebuie s fac diferena ntre valoarea
numeric 0 i Null sau ntre irul de caractere spaiu i valoarea Null. Valoarea Null trebuie s
reprezinte absena informaiei respective i are un rol important n implementarea restriciilor de
integritate structural (integritatea entitii i integritatea referirii). Oracle respect aceast regul,
limbajul SQL permind declararea i manipularea valorilor Null.
Regula 4. Regula dicionarului de date:
Descrierea bazei de date (dicionarul de date) trebuie s fie reprezentat la nivel logic tot sub
form de tabele, astfel nct asupra acesteia s se poat aplica aceleai operaii ca i asupra
datelor propriu-zise.
Cu alte cuvinte, dicionarul de date trebuie s fie organizat la nivel logic i accesat la fel ca orice
tabel din baza de date. Aceast regul este respectat de ctre Oracle, dicionarul de date constnd
din tabele i tabele virtuale (vederi) care pot fi interogate la fel ca oricare alte tabele sau vederi,
folosind comanda SELECT.
Regula 5. Regula limbajului de acces:
ntr-un sistem relaional trebuie s existe cel puin un limbaj de accesare a datelor, care s asigure
urmtoarele operaii: definirea tabelelor de baz i a tabelelor virtuale (vederilor), manipularea i
interogarea datelor (att interactiv ct i prin program), definirea restriciilor de integritate,
autorizarea accesului la date, delimitarea tranzaciilor.
Limbajul SQL folosit de ctre Oracle permite definirea tabelelor (comenzile CREATE TABLE,
ALTER TABLE, DROP TABLE), a vederilor (comenzile CREATE VIEW, ALTER VIEW, DROP
VIEW), manipularea (comenzile INSERT, UPDATE, DELETE) i interogarea acestora (comanda
SELECT), definirea restriciilor de integritate (clauza CONSTRAINT folosit la definirea
tabelelor), autorizarea accesului la date (printr-un set de privilegii de sistem i la nivel de obiect),
delimitarea tranzaciilor (operaiile COMMIT i ROLLBACK).
Regula 6. Regula de actualizare a tabelelor virtuale (vederilor).
Un SGBD trebuie s poat determina dac o vedere poate s fie actualizat sau nu.
Un tabel virtual (vedere) este un tabel logic, n sensul c el organizeaz datele sub forma unor
rnduri i coloane, ca orice alt tabel, dar n schimb el nu stocheaz datele, fiind construit pe baza
unor interogri asupra unuia sau mai multor tabele de baz. De exemplu s considerm tabelul :
salariu(cod_salariat, salariu_brut, zile_totale, zile_lucrate).
Pe baza acestui tabel se poate defini vederea
salariu_r(cod_salariat, salariu_brut, salariu_realizat)
unde salariu_realizat este definit ca
salariu_realizat = salariu_brut*zile_totale/zile_lucrate.
S presupunem acum c se dorete actualizarea coloanei salariu_brut din vedere. Acest lucru este
posibil, datorit faptului c actualizarea se propag napoi la coloana din tabelul de baz,
producndu-se i actualizarea acesteia. Pe de alt parte, nu este posibil actualizarea coloanei
27

salariu_realizat, datorit faptului c schimbarea valorii acesteia s-ar putea produce datorit
schimbrii valorilor mai multor coloane (salariu_brut, zile_totale sau zile_lucrate), SGBD-ul
netiind care din aceste coloane trebuie actualizat n tabelul de baz. Oracle respect aceast
regul, existnd un set de reguli care determin dac o coloan a unei vederi poate sau nu s fie
actualizat.
Regula 7. Regula manipulrii datelor:
Un sistem relaional trebuie s ofere posibilitatea procesrii tabelelor (de baz sau virtuale) nu
numai n operaiile de interogare a datelor ct i n cele de inserare, actualizare i tergere.
Aceasta nseamn c operaiile de manipulare a datelor (inserare, actualizare i tergere) trebuie s
se poat efectua asupra oricrei mulimi de rnduri dintr-un tabel, pornind de la ntregul tabel i
terminnd cu un singur rnd sau cu nici unul. Deci, un SGBD relaional nu oblig utilizatorul s
caute ntr-un tabel rnd cu rnd pentru a regsi, modifica sau terge informaia dorit, deoarece
operaiile prin care se manipuleaz coninutul bazei de date lucreaz la nivel de mulime de rnduri.
Limbajul SQL asigur aceast facilitate prin instruciunile: INSERT cu subinterogare, UPDATE i
DELETE (vezi seciunile 8.2, 8.3 i 8.4).
Regula 8. Regula independenei fizice a datelor:
Programele de aplicaie nu trebuie s depind de modul de stocare i accesare fizic a datelor.
Deci un SGBD relaional trebuie s separe complet aspectele de ordin fizic ale datelor (modul de
stocare i modul de acces la date) de cele de ordin logic. Cu alte cuvinte, programele de aplicaie nu
trebuie s depind de stocarea fizic a datelor. De exemplu, dac un fiier care conine un tabel de
date este mutat pe o alt unitate de disc sau i este schimbat numele, aceasta nu trebuie s aib vreun
efect asupra aplicaiilor care folosesc acel tabel, utilizatorilor fiindu-le transparent aceast
schimbare. n mare, Oracle respect aceast regul, dei stocarea fizic a datelor trebuie luat n
consideraie la proiectarea bazei de date.
Regula 9. Regula independenei logice a datelor:
Programele de aplicaie nu trebuie s fie afectate de nici o restructurare logic a tabelelor bazei de
date care conserv datele.
Deci orice modificare efectuat asupra unui tabel care conserv datele din acesta (de exemplu, dac
un tabel trebuie divizat n dou, din raiuni de cretere a performanelor) nu trebuie s afecteze
funcionarea programelor de aplicaie. Aceast regul este respectat de ctre Oracle prin
posibilitatea definirii vederilor: dac un tabel este divizat n dou, atunci se poate crea o vedere care
altur cele dou tabele, astfel nct aceast mprire nu va avea nici un efect asupra aplicaiei.
Regula 10. Regula independenei datelor din punctul de vedere al integritii:
Regulile de integritate a bazei de date trebuie s fie definite n limbajul utilizat de sistem pentru
definirea datelor i nu n cadrul aplicaiilor individuale; n plus, aceste reguli de integritate trebuie
stocate n dicionarul de date.
Cu alte cuvinte, restriciile de integritate trebuie impuse la definirea tabelelor bazei de date i nu n
cadrul aplicaiilor care folosesc aceste tabele. n general, Oracle respect aceast regul, la definirea
tabelelor (n cadrul comenzii CREATE TABLE) putndu-se defini att restriciile de integritate
structural (NOT NULL, UNIQUE, PRIMARY KEY, FOREIGN KEY) ct i unele restricii de
comportament (CHECK). Informaii despre aceste restricii sunt stocate n dicionarul bazei de date.
Regula 11. Regula independenei datelor din punctul de vedere al distribuirii:
28

Programele de aplicaie nu trebuie s fie afectate de distribuirea pe mai multe calculatoare a bazei
de date.
Cu alte cuvinte, baza de date trebuie s mearg corect indiferent dac se gsete pe un singur
calculator sau este distribuit n mai multe noduri ale unei reele. Aceast regul este o extensie a
regulii 8, privind independena programelor de aplicaie fa de modul de stocare fizic a datelor.
Aceast regul este n general respectat de Oracle, existnd totui restricii privind accesarea unor
obiecte aflate n alt nod al reelei. n plus, n Oracle exist posibilitatea replicrii locale a tabelelor
aflate n alte noduri ale reelei, evitndu-se astfel transmiterea n mod repetat a informaiilor prin
reea.
Regula 12. Regula privind prelucrarea datelor de ctre un limbaj de nivel inferior.
Orice limbaj nerelaional folosit pentru accesarea datelor trebuie s respecte aceleai condiii de
integritate ca i limbajul relaional de acces.
De exemplu, dac sistemul posed un limbaj de nivel inferior, prin care se acceseaz datele la nivel
de rnd i nu, potrivit sistemului relaional, la nivelul mulimilor de rnduri, acest limbaj nu poate fi
folosit pentru evitarea restriciilor de integritate (integritatea entitii, integritatea referenial,
restricii de comportament) pe care trebuie s le respecte limbajul procedural de acces la date.
Aceast regul este respectat de ctre Oracle prin faptul c singurul limbaj de accesare a datelor
este SQL, care este un limbaj relaional.
Dac un SGBD ndeplinete principiile sistemului relaional (folosete ca structuri de date tabele
conforme cu modelul relaional, suport cele dou reguli de integritate structural i operaiile
relaionale) i respect aceste 12 reguli, atunci el poate fi numit relaional. Codd rezum aceste
lucruri prin regula zero:
Regula 0. Regula de baz:
Un SGBD Relaional trebuie s fie capabil s gestioneze baza de date exclusiv pe baza
caracteristicilor sale relaionale.
Aceasta nseamn c sistemul trebuie s-i ndeplineasc toate funciile prin manipulri n care
unitatea de procesare s fie tabelul (mulimea de rnduri), asupra cruia s se efectueze operaiile
specifice modelului relaional. Trebuie spus c regula 0 nu este respectat n totalitate de nici un
SGBD existent pe pia, inclusiv Oracle, implementarea acestora folosind att caracteristici
relaionale ct i nerelaionale.
Se obinuiete ca, n conformitate cu tipul de cerine pe care le exprim, regulile s fie grupate n
cinci categorii, i anume:
1.
2.
3.
4.
5.

reguli de baz: Regula 0 i Regula 12;


reguli structurale: Regula 1 i Regula 6;
reguli privind integritatea datelor: Regula 3 i Regula 10;
reguli privind manipularea datelor: Regula 2, Regula 4, Regula 5 i Regula 7;
reguli privind independena datelor: Regula 8, Regula 9 i Regula 11.

Trebuie spus c nici unul dintre SGBD-urile existente n prezent nu satisface n totalitate toate cele
13 reguli ale lui Codd. De aceea, n practic nu sunt utilizate regulile lui Codd, fiind formulate n
schimb un set de cerine minimale pe care trebuie s le satisfac un sistem SGBD pentru a putea fi
considerat relaional.
Un SGBD este denumit minimal relaional, dac satisface urmtoarele condiii:
29

1. Toate datele din cadrul bazei de date sunt reprezentate prin valori n tabele.
2. Nu exist pointeri ntre tabele observabili de ctre utilizator.
3. Sistemul suport operatorii relaionali de proiecie, selecie i compunere natural, fr limitri
impuse de considerente interne.
Un SGBD este denumit complet relaional dac este minimal relaional i satisface n plus
urmtoarele condiii:
4. Sistemul suport toate operaiile de baz ale algebrei relaionale, fr limitri impuse de
considerente interne.
5. Sistemul suport restriciile de integritate de baz ale modelului relaional (integritatea entitii
i integritatea referenial)
SGDB-ul Oracle este complet relaional i chiar se apropie destul de mult de un SGBD relaional
ideal, definit prin regulile lui Codd.

30

Capitolul 2: Proiectarea bazelor de date relaionale


Dup mai bine de dou decenii de folosire a modelului relaional, proiectarea (designul) bazelor de
date rmne nc mai degrab art dect tiin. Au fost sugerate un numr de metode, dar pn n
prezent nici una nu este dominant. Pe de alt parte proiectarea bazelor de date trebuie s fie bazat
pe consideraii practice care stau la baza oricrei activiti de procesare a datelor. Pentru a crea un
design adecvat este necesar o cunoatere aprofundat a funcionrii antreprizei, a modului n care
aceasta folosete datele i a sistemului de management al bazelor de date folosit.
Metodele curente de proiectare a bazelor de date sunt n general divizate n trei etape separate:
crearea schemei conceptuale, crearea design-ului logic al bazei de date i crearea design-ului fizic al
bazei de date.
1. Crearea schemei conceptuale. Aceasta este un design de nivel nalt (incluznd relaiile dintre
datele ntregului sistem), care descrie datele i relaiile necesare pentru execuia operaiilor
necesare, fiind independent de orice model de baze de date. Designul de la acest nivel este foarte
general, se realizeaz ntr-o perioad scurt de timp i prezint modul n care gruprile de date
sunt integrate n sistemul de ansamblu.
2. Crearea design-ului logic al bazei de date. n aceast faz schema conceptual este
transformat n structuri specifice unui anumit sistem de management al bazei de date. La acest
nivel designul este rafinat, sunt definite elemente de date specifice i sunt grupate n nregistrri.
n cazul modelului relaional, la sfritul acestei etape vom avea un numr de tabele care vor
permite stocarea i manipularea corect a tuturor datelor necesare sistemului.
3. Crearea design-ului fizic al bazei de date. n aceast etap designul logic este transformat ntro structur fizic eficient .
Primele dou etape vor fi prezentate pe larg n acest capitol. Cel de-al treilea va fi abordat n
capitolul 6, cnd va fi prezentat organizarea logic a bazei de date Oracle.
2.1. Crearea schemei conceptuale.
Procesul de design al schemei conceptuale ncepe prin determinarea datelor necesare activitilor
din antrepriz. Este creat o echip de design a schemei conceptuale care se ocup cu determinarea
datelor necesare, eventual prin folosirea de interviuri cu managerii antreprizei. Dup ce echipa
proiecteaz datele, ea le revizuiete i le organizeaz.
2.1.1. Modelul entitate-legtur (entitate-relaie)
Una dintre tehnicile folosite pentru organizarea rezultatelor din etapa de colectare a datelor este
modelul entitate-legtur, care mparte elementele unui sistem real n dou categorii i anume
entiti i legturi (relaii) ntre aceste entiti. Principalele concepte folosite n acest model sunt
cele de entitate, relaie (legtur) i atribut.
Nota: Nu trebuie confundat conceptul de relaie n sensul de legtur sau asociere, care intervine n
modelul entitate-legtur cu cel definit n capitolul 1.
Entitate
31

O entitate este un obiect de interes i pentru care trebuie s existe date nregistrate. O entitate poate
fi att un obiect tangibil precum persoane, locuri sau lucruri - ct i abstracte precum comenzi,
conturi bancare, etc. De exemplu, s considerm o universitate format din mai multe faculti; n
fiecare facultate studiaz mai muli studeni i predau mai muli profesori. Fiecare student urmeaz
mai multe cursuri, dup cum un profesor poate preda unul sau mai multe cursuri. Elementele
semnificative ale acestui sistem sunt: facultate, student, profesor i curs; acestea sunt entitile
sistemului. Ele sunt reprezentate n figura 2.1 mpreun cu relaiile dintre ele. Remarcai c
entitile se reprezint prin dreptunghiuri, iar relaiile dintre ele prin arce neorientate.

FACULTATE

lucreaz _n

studiaz _la
STUDENT

PROFESOR

pred
urmeaz

CURS

Figura 2.1
Ideile de baz pentru identificarea i reprezentarea entitilor sunt urmtoarele:
Fiecare entitate este denumit n mod unic; nu pot exista dou entiti cu acelai nume sau o
entitate cu dou nume diferite.
Entitile sunt reprezentate ntotdeauna prin substantive, dar nu orice substantiv folosit n
descrierea sistemului este o entitate a acestuia. Entitile sistemului sunt doar acele substantive
care au o semnificaie deosebit n descrierea sistemului. De exemplu, chiar dac suntem
interesai de numrul de ore de predare efectuate de un profesor pe sptmn, aceasta nu
nseamn c vom crea o entitate pentru aceasta. De fapt, vom vedea n continuare c numrul de
ore predate va fi un atribut al entitii PROFESOR.
De asemenea, pentru fiecare entitate trebuie s se dea o descriere detaliat, de exemplu, putem
spune c un PROFESOR este un cadru didactic angajat al universitii pe o perioad
nedeterminat, din aceast categorie fcnd parte att profesorii permaneni ct i cei asociai,
dar fiind exclui cei care predau la universitate numai o perioad limitat.
Relaie (legtur)
Entitile pot forma relaii ntre ele. O relaie este o asociere nedirecionat ntre dou entiti. Ea
exprim un raport care exist ntre entitile respective. De exemplu, lucreaz_n este o relaie
ntre entitile PROFESOR i FACULTATE, iar pred este o relaie ntre entitile PROFESOR i
CURS.
Principalele idei pentru identificarea i reprezentarea relaiilor sunt urmtoarele:
Relaiile sunt reprezentate prin verbe, dar nu orice verb este o relaie.
ntre dou entiti poate exista mai mult dect o singur relaie. De exemplu, dac lum n vedere
c fiecare facultate este condus de un decan i c acesta este ales din rndurile profesorilor,
atunci ntre entitile PROFESOR i FACULTATE va mai exista o relaie numit conduce.
Pot exista relaii cu acelai nume, dar relaiile care asociaz aceleai entiti trebuie s poarte
nume diferite.

32

Cardinalitatea unei relaii indic numrul maxim de instane din fiecare entitate care poate participa
la relaie. Cu alte cuvinte, cardinalitatea unei relaii reprezint rspunsul la ntrebri de genul: Ci
studeni pot studia la o facultate? Muli. Dar la cte faculti poate studia un student? La cel mult
una. Deci cardinalitatea relaiei studiaz_la este de muli-la-unu. Cardinalitatea unei relaii poate
fi de trei feluri: muli-la-unu, unu-la-unu sau muli-la-muli.
muli-la-unu (many-to-one, N:1): Relaia dintre entitile A i B este de tipul muli-la-unu dac
fiecrei instane din A i poate fi asociat cel mult o singur instan din B i fiecrei instane din
B i pot fi asociate mai multe instane din A. De exemplu, relaiile lucreaz_n dintre
PROFESOR i FACULTATE i studiaz_la dintre STUDENT i FACULTATE sunt de tipul
N:1. O relaie muli-la-unu se reprezint n modul urmtor:

STUDENT

studiaz _la

FACULTATE

Figura 2.2
unu-la-unu (one-to-one, 1:1): Relaia dintre entitile A i B este de tipul unu-la-unu dac fiecrei
instane din A i poate fi asociat cel mult o singur instan din B i fiecrei instane din B i
poate fi asociat cel mult o singur instan din A. De exemplu, relaia conduce dintre
PROFESOR i FACULTATE este o relaie 1:1.

PROFESOR

conduce

FACULTATE

Figura 2.3
muli-la-muli (many-to-many, N:M): Relaia dintre entitile A i B este de tipul muli-la-muli
dac fiecrei instane din A i pot fi asociate mai multe instane din B i fiecrei instane din B i
pot fi asociate mai multe instane din A. De exemplu, relaiile pred dintre PROFESOR i
CURS i urmeaz dintre STUDENT i CURS sunt de tipul N:M. O relaie N:M se reprezint
n modul urmtor:

PROFESOR

pred

CURS

Figura 2.4
Valorile discutate pn acum (N:1, 1:1, N:M) reprezint cardinalitatea maxim a unei relaii. Pe de
alt parte, o relaie este caracterizat i de o cardinalitate minim, care indic obligativitatea
participrii entitilor la relaie. Cu alte cuvinte, aceasta furnizeaz rspunsul la ntrebri de genul:
Ci studeni trebuie s studieze la o facultate? Zero. Dar la cte faculti trebuie s studieze un
student? Cel puin una. Deci cardinalitatea minim a relaiei studiaz_la dintre STUDENT i
FACULTATE este de 0:1. n mod similar, relaia pred dintre PROFESOR i CURS are
cardinalitatea minim 0:0 (un profesor trebuie s predea zero cursuri i un curs trebuie s fie predat
de zero profesori de exemplu dac cursul este nou i nu s-a stabilit nc titularul de curs). Deci
cardinalitatea minim a unei relaii poate avea valorile 0:0, 0:1 i 1:1. Dac participarea unei entiti
33

la o relaie este obligatorie (cardinalitatea minim respectiv este 1) se mai spune i c participarea
acesteia la relaie este total. n caz contrar (cardinalitatea minim respectiv este 0), participarea
entitii la relaie se numete parial. De exemplu participarea entitii STUDENT la relaia
studiaz_la este parial, pe cnd participarea entitii FACULTATE la aceeai relaie este total.
n cadrul reprezentrii grafice, cardinalitatea maxim a unei relaii se va indica fr paranteze, n
timp ce cardinalitatea minim, dac este diferit de cea maxim, se va scrie n paranteze, vezi
figurile 2.5, 2.6 i 2.7. De multe ori, cardinalitatea minim nu este indicat n diagrama entitatelegtur, pe cnd cardinalitatea maxim trebuie indicat ntotdeauna, ea fiind esenial.

STUDENT

M
M(0)

studiaz _la 1

FACULTATE

Figura 2.5
PROFESOR

1(0)

1(0) FACULTATE

conduce

Figura 2.6

PROFESOR

M
M(0)

pred

M(0)

CURS

Figura 2.7

Un alt mod de a reprezenta relaiile, indicnd doar cardinalitatea lor maxim este urmtorul:

relaii muli-la-unu

STUDENT

studiaz _la

FACULTATE

Figura 2.8

relaii unu-la-unu

PROFESOR

conduce

Figura 2.9

relaii muli-la-muli

34

FACULTATE

PROFESOR

pred

CURS

Figura 2.10

Atribut
Un atribut este o caracteristic a unei entiti sau a unei relaii. Fiecare entitate are un anumit numr
de atribute despre care sunt nregistrate date. De exemplu, numele, prenumele, vrsta i numrul de
ore predate sunt atribute ale entitii PROFESOR. Fiecare atribut poate lua o valoare care
furnizeaz informaii despre entitatea respectiv. Exemple de valori de atribute sunt Ionescu
pentru nume, Mihai pentru prenume etc. Pe de alt parte i relaiile pot avea atribute. De exemplu,
relaia urmeaz dintre STUDENT i CURS poate avea ca atribute nota obinut la examen i nota
obinut la restan - pentru cei care nu au promovat examenul - iar relaia lucreaz_n dintre
PROFESOR i FACULTATE poate avea ca atribut data angajrii.
Principalele idei pentru identificarea i reprezentarea atributelor sunt urmtoarele:
Numele unui atribut este unic n cadrul unei entiti sau al unei relaii.
Atributele sunt ntotdeauna substantive, dar nu orice substantiv este un atribut.
Pentru fiecare atribut, trebuie furnizat o descriere, mpreun cu domeniul de valori (ntreg, ir
de caractere, dat, etc.).
Alegerea atributelor trebuie fcut n aa fel nct s se evite aa-numitele atribute indirecte. Un
atribut indirect al unei entiti sau relaii este un atribut care nu aparine n mod real acelei
entiti sau relaii, fiind o caracteristic a unui alt obiect al sistemului. De exemplu, numele
facultii este un atribut indirect al entitii STUDENT, el descriind de fapt o proprietate a
entitii FACULTATE. De aceea, el va trebui redistribuit acestei entiti.
Modelul entitate-legtur i modelul relaional.
Modelul entitate-legtur poate fi transformat n mod natural ntr-o baz de date relaionale. Fr a
intra deocamdat n amnuntele acestei transformri, enunm n continuare principalele idei ale
acestei transformri:
O entitate devine un tabel.
Un atribut al unei entiti devine o coloan a tabelului respectiv.
O relaie va fi reprezentat fie printr-un tabel special, fie printr-o cheie strin ntr-unul dintre
cele dou tabele entitate, care face referire la cheia primar a celuilalt tabel entitate.
Chei primare. Chei naturale i chei artificiale.
n concordan cu terminologia folosit n capitolul 1, o cheie a unei entiti va fi un atribut sau un
set de atribute care identific n mod unic o instan a acelei entiti. Cu alte cuvinte, o cheie face
distincie ntre oricare dou rnduri diferite ale tabelului provenit din entitatea respectiv. De
exemplu, putem presupune c fiecare student va fi identificat n cadrul universitii printr-un cod
unic; atunci codul studentului este o cheie a entitii STUDENT. Pe de alt parte, numele
studentului nu poate fi cheie a acestei entiti deoarece pot exista mai muli studeni cu acelai
nume. Dac ns presupunem c nu pot exista studeni cu acelai nume, prenume i dat de natere
atunci combinaia acestor atribute este la rndul ei cheie a entitii STUDENT.
35

Exist dou tipuri de chei: naturale i artificiale. O cheie natural este constituit dintr-un atribut
sau o combinaie de atribute cu semnificaie real pentru entitatea n cauz. De exemplu, combinaia
nume, prenume, dat de natere este o cheie natural a entitii STUDENT. O cheie artificial este
un atribut al unei entiti care nu are semnificaie real pentru entitatea n cauz, fiind folosit doar
pentru a face distincie ntre instanele entitii. De exemplu, codul studentului este o cheie
artificial a entitii STUDENT.
Una dintre cheile entitii va fi declarat cheie primar. Deci, n principiu, oricare dintre cele dou
chei ale entitii STUDENT poate fi declarat cheie primar. Pe de alt parte ns, este preferat
folosirea cheilor primare artificiale, excepie fcnd cazul cnd cheia primar respectiv nu va fi
stocat n alte tabele ca i cheie strin. Principalele avantaje ale cheilor primare artificiale fa de
cele naturale sunt urmtoarele:
Stabilitatea. Valoarea unei chei artificiale rmne aceeai pe parcursul funcionrii sistemului, n
timp ce valoarea unei chei naturale poate fi n general modificat, aceast modificare atrgnd, la
rndul ei, schimbarea cheilor strine care fac referire la ea. De exemplu, numele unei studente se
poate schimba prin cstorie; dac se consider combinaia nume, prenume i data naterii ca
fiind cheia primar a entitii STUDENT, atunci orice schimbare a numelui va impune
modificarea valorilor cheilor strine corespunztoare. Ca o regul general, valoarea cheii
primare a unui tabel nu trebuie s poat fi modificat, aceasta crend probleme privind pstrarea
integritii datelor - cu alte cuvinte schimbarea cheii primare a unui tabel va trebui nsoit de
schimbarea cheilor strine care fac referire la aceasta.
Simplitatea. n general, o cheie artificial este mai simpl dect una natural. Cheile naturale
sunt mai complexe, att din punct de vedere fizic (numrul de octei) ct i al numrului de
coloane. De exemplu, este mult mai comod stocarea codului studentului ca i cheie strin,
dect a combinaiei dintre numele, prenumele i data naterii.
Nu prezint ambiguiti. O cheie primar trebuie s nu prezinte ambiguiti, astfel nct s poat
fi folosit cu uurin de ctre dezvoltator sau utilizator n filtrrile efectuate pe tabele. i n
aceast privin, o cheie natural creeaz probleme. De exemplu, numele i prenumele unui
student pot fi formate dintr-unul sau mai multe cuvinte care pot fi desprite de un spaiu sau de
o linie, etc.
Elimin valorile Null. n cazul cheilor primare naturale, valorile Null reprezint o problem. De
exemplu, aceasta nseamn c un student nu poate fi nregistrat dac nu i se tie data de natere.
n concluzie, o cheie primar trebuie s fie unic, diferit de Null, scurt, simpl, fr ambiguiti,
s nu conin informaii descriptive, s fie uor de manipulat, s fie stabil i familiar utilizatorului.
Cheile artificiale ndeplinesc toate aceste condiii n afar de ultima, fiind preferate aproape
ntotdeauna celor naturale.
Diagrama entitate-legtur
Entitile sistemului, mpreun cu relaiile dintre ele se reprezint prin aa numita diagram entitatelegtur, n care entitile sunt reprezentate prin dreptunghiuri, iar relaiile dintre acestea prin arce
neorientate, specificndu-se i cardinalitatea acestora. Pentru fiecare entitate se specific cheile
primare i eventual atributele mai semnificative, atributele care reprezint chei primare trebuind s
36

fie subliniate. Diagrama entitate-legtur a sistemului descris la nceputul acestui capitol este
reprezentat n figura 2.11.

FACULTATE
1
cod_facultate
nume_facultate
adresa

lucreaz _n
conduce

1(0)

PROFESOR
M(0)
1(0)

M(0)

studiaz _la

pred
M(0)

M(0)
STUDENT
cod_student
nume
prenume
data_naterii

cod_profesor
nume
prenume
data_naterii
grad_didactic

CURS
M(0)

urmeaz

M(0)

cod_curs
nume_curs
descriere

Figura 2.11

Cazuri speciale de entiti, relaii i atribute


n continuare vom considera cteva cazuri speciale de entiti, relaii i atribute, ncercnd n acelai
timp o clasificare a acestora.
Subentitate/Superentitate.
O subentitate este o submulime a unei alte entiti, numit superentitate. De exemplu, s
presupunem c n sistemul prezentat mai sus nu vom reine date numai despre profesorii,
universitii, ci i despre tot personalul din universitate. Atunci vom crea o superentitate
PERSONAL, pentru care PROFESOR este o subentitate. O alt subentitate a acestei superentiti
va fi PERSONAL_ADMINISTRATIV. O subentitate se reprezint printr-un dreptunghi inclus n
dreptunghiul care reprezint superentitatea corespunztoare, vezi figura 2.12. Cheia primar,
atributele i relaiile unei superentiti sunt valabile pentru orice subentitate, reciproca fiind
evident fals. De exemplu, cheia primar a entitii PROFESOR va fi acum cod_personal, care
este cheia primar a entitii PERSONAL, n timp ce unele dintre atributele subentitii
PROFESOR (de exemplu nume, prenume, data_nasterii) se regsesc printre atributele
entitii PERSONAL. Pe de alt parte ns, subentitatea PROFESOR poate avea i alte atribute
dect cele specifice superentitii PERSONAL, de exemplu gradul didactic. Cu alte cuvinte,
37

atributele comune vor fi repartizate superentitii, n timp ce atributele specifice vor fi repartizate
subetitilor.
ntre o subentitate i superentitatea corespunztoare exist ntotdeauna o relaie 1:1, avnd
cardinalitatea minim 1:0.
Uneori este convenabil s se creeze superentiti din entiti cu mai multe atribute comune. De
exemplu, din entitile PROFESOR i PERSONAL_ADMINISTRATIV s-a creat entitatea
PERSOANA. Superentitatea astfel creat va conine atributele comune, iar atributele specifice
vor fi repartizate subentitilor componente. n plus, se va crea o nou cheie artificial pentru
superentitatea nou format. De exemplu, pentru PERSOANA s-a creat un cod personal, care a
devenit cheie primar a acestei entiti.

PERSONAL
cod_personal
nume
prenume
data_naterii
PROFESOR
grad_didactic
PERSONAL_ADMINISTRATIV

Figura 2.12

Entitate dependent (detaliu)/entitate master.


O entitate dependent (detaliu) este o entitate care nu poate exista de sine stttoare, ci numai
ataat unei alte entiti, aceasta din urm fiind numit entitatea master a acestei legturi. De
exemplu, dac presupunem c fiecare curs poate fi constituit dintr-unul sau mai multe module,
atunci entitatea MODUL va fi o entitate dependent de CURS, vezi figura 2.13. ntre entitile
master i detaliu va exista ntotdeauna o relaie 1:N, avnd cardinalitatea minim 1:0. Cheia
primar a unei entiti detaliu va fi format din cheia primar a entitii master plus una sau mai
multe atribute ale entitii detaliu. De exemplu, cheia entitii MODUL poate fi aleas ca fiind
combinaia dintre cod_curs i nr_modul, acesta din urm specificnd numrul de ordine al unui
modul n cadrul unui curs.

38

MODUL
cod_curs
nr_modul
decriere

CURS
M(0)

face_parte_din

cod_curs
nume_curs
descriere

Figura 2.13
Relaii recursive.
Pot exista relaii nu numai ntre dou entiti diferite, ci i ntre o entitate i ea nsi; acestea se
numesc relaii recursive. De exemplu, dac presupunem c activitatea de cercetare n universitate
este organizat pe o structur ierarhic, adic un profesor poate avea un ef i poate fi la rndul
lui eful mai multor profesori, atunci entitatea profesor admite o relaie recursiv de tipul N:1,
vezi figura 2.14.

este_ef
M(0)
PROFESOR
1(0)
Figura 2.14
Relaii binare (de tip 2)/ relaii ntre mai mult de dou entiti (de tip 3).
Pn acum am discutat doar despre relaiile dintre dou entiti, numite relaii binare sau de tip 2.
Pot ns exista i relaii ntre mai mult de dou entiti, pe care le vom numi relaii de tip 3. De
exemplu, s presupunem c fiecare student trebuie s efectueze mai multe proiecte, iar pentru
fiecare proiect el poate s-i aleag unul sau mai multi profesori coordonatori. Deci relaia
efectueaz_coordoneaz este o relaie de tip 3 ntre entitile STUDENT, PROIECT i
PROFESOR, vezi figura 2.15. O relaie de tip 3 nu poate fi spart n relaii binare ntre entitile
componente, un exemplu este oferit n figura 2.16, unde prin spargerea relaiei
efectueaz_coordoneaz n trei relaii binare prin proiecie se obin informaii eronate, relaia
iniial nemaiputnd fi reconstituit din relaiile componente.

39

STUDENT
M(0)
coordoneaz M(0)

PROFESOR

efectueaz
M(0)
PROIECT
Figura 2.15

STUDENT
s1
s1
s2

PROIECT
p1
p2
p1

PROFESOR
x2
x1
x1

a) Relaia de tip 3 iniial


STUDENT
s1
s1
s2

PROIECT
p1
p2
p1

STUDENT
s1
s1
s2

PROFESOR
x2
x1
x1

PROIECT
p1
p2
p1

PROFESOR
x2
x1
x1

b) Descompunerea relaiei de tip 3 n 3 relaii binare prin proiecie


STUDENT
s1
s1
s1
s2

PROIECT
p1
p1
p2
p1

PROFESOR
x1
x2
x1
x1

c) Reconstituirea eronat a relaiei iniiale


Figura 2.16.
Atribute simple/ compuse/ repetitive (multivaloare)/ calculate (deduse)
Atributele pot fi de patru feluri: simple, compuse, repetitive (multivaloare) i calculate (deduse).
Unui atribut simplu i corespunde o singur valoare, atomic. De exemplu, numele i prenumele
unui student sunt atribute simple. Un atribut compus este format din mai multe atribute simple,
numite componentele sale. Valoarea unui atribut compus este reprezentat de valorile atributelor
componente. Dac presupunem, de exemplu, c o adres se poate descompune n componentele
ar, ora, strad, numr i cod, atunci adresa este un atribut compus din 5 componente. Un
atribut repetitiv (multivaloare) este un atribut care poate avea mai multe valori, numrul acestora
variind de la o instan la alta. De exemplu, un student poate avea mai multe numere de telefon,
deci acesta este un atribut repetitiv. Un atribut calculat reprezint un atribut a crui valoare nu
40

este cunoscut direct, ci calculat pe baza valorilor altor atribute. De exemplu atributul valoare
este calculat ca produs ntre atributele cantitate i pre. Atributele calculate se folosesc foarte rar
deoarece ele reprezint de fapt o redundan a datelor.
Probleme n identificarea entitilor, relaiilor i atributelor
Relaie sau entitate?.
Uneori este greu de identificat dac o component a sistemului este relaie sau entitate. Dac o
entitate are o cheie provenit din combinaia cheilor primare a dou sau mai multe entiti, atunci
trebuie definit o relaie. Deci entitatea PRED din figura 2.17 a) va avea semnificaia unei
relaii ntre entitile PROFESOR i CURS, reprezentat n figura 2.17 b).

a)

PROFESOR

PRED

CURS

cod_profesor

cod_profesor
cod_curs

cod_curs

PROFESOR
b)

CURS
M

pred

cod_profesor

M
cod_curs

Figura 2.17

Relaie sau atribut?


Dup cum am vzut pn acum, o relaie poate fi reprezentat ca un atribut al unei entiti, dup
cum atributele unei entiti pot fi nlocuite cu relaii. Deci, care este diferena ntre o relaie i un
atribut? Atunci cnd un atribut al unei entiti reprezint cheia primar a altei entiti, el face
referin la o relaie. Deci figura 2.18 a) va reprezenta o relaie ntre entitile STUDENT i
FACULTATE, vezi figura 2.18 b).

41

STUDENT
a)

STUDENT
b)

cod_student
cod_facultate

M studiaz _la

FACULTATE
cod_facultate

cod_student

Figura 2.18

Etapele obinerii modelului entitate-legtur.


Pentru realizarea modelului entitate-legtur a sistemului analizat sunt parcurse urmtoarele etape:

Identificarea entitilor sistemului.,


Identificarea relaiilor sistemului i stabilirea cardinalitii acestora.
Identificarea atributelor entitilor i relaiilor sistemului.
Stabilirea cheilor primare ale entitilor.
Trasarea diagramei entitate-legtur.

Diagrama entitate-legtur a sistemului prezentat ca exemplu n aceast seciune, incluznd


entitile i relaiile menionate mai sus, este prezentat n figura 2.19.
Trebuie remarcat c aceeai realitate poate fi perceput diferit de ctre analiti diferii, aa c este
posibil obinerea de modele diferite pentru acelai sistem, dup cum i un sistem poate s se
modifice n timp, ceea ce va atrage la rndul su modificarea modelului asociat. n sfrit, exist i
alte moduri grafice de prezentare a diagramei entitate-legtur, vezi de exemplu [15] [Popescu96],
n acest capitol prezentndu-se doar una dintre notaiile existente.

42

PERSONAL
cod_personal
nume, prenume, data_naterii
PERSONAL_ADMINISTRATIV
FACULTATE
cod_facultate
nume_facultate
adresa
1
studiaz _l
a

M(0)

lucreaz _n M(0)

este_ef

PROFESOR
1(0)

conduce 1(0)

grad_didactic

M(0)

1(0)

M(0)

coordoneaz

M(0)
STUDENT
cod_student
nume
prenume
data_naterii

M(0)

M(0)

efectueaz

PROIECT

pred

cod_proiect
nume_proiect

M(0)

M(0)
CURS
M(0)

urmeaz

cod_curs
nume_curs
descriere
1
face_parte_din
M(0)
MODUL
cod_curs
nr_modul
descriere

Figura 2.19

2.2. Crearea design-ului logic al bazei de date.


Pentru realizarea design-ului logic al bazei de date, schema conceptual este transformat ntr-un
design al bazei de date care va funciona ntr-un sistem de gestiune al bazelor de date specific.
Designul logic al bazei de date este o rafinare a modelului iniial furnizat de schema conceptual.
Aceasta nu nseamn c modelul conceptual nu este corect, dar trebuie stabilite detalii suplimentare
necesare dezvoltrii proiectului.
43

2.2.1. Transformarea modelului entitate legtur n modelul relaional


Deci pentru obinerea design-ului logic al unei baze de date relaionale se pornete de la schema
conceptual, mai precis de la modelul entitate-legtur, i se ncearc reprezentarea entitilor i a
legturilor sub form de tabele relaionale. Regulile de conversie ale entitilor, legturilor i
atributelor sunt urmtoarele:
Transformarea entitilor:
Regula general este c entitile devin tabele, distingndu-se urmtoarele subcazuri:
Entitile independente devin tabele independente, adic tabele a cror cheie primar nu conine
chei strine. De exemplu, entitatea STUDENT va deveni un tabel a crui cheie primar este
cod_student.
Entitile dependente devin tabele dependente (tabele detaliu) adic tabele a cror cheie primar
conine cheia strin ce face referin la cheia primar a entitii de care depinde entitatea n
cauz. De exemplu, cheia primar a entitii MODUL va fi format din cod_curs, care
reprezint o cheie strin pentru entitatea CURS, plus nr_modul.
Subentitile devin subtabele adic tabele a cror cheie primar este cheia strin pentru tabelul
superentitate. De exemplu, cheia primar a tabelului PROFESOR este cod_personal, care este
o cheie strin ce face referin la cheia primar cod_personal din tabelul PERSONAL.
Uneori, se prefer construirea unor supertabele, formate att din atributele superentitii - cele
comune tuturor subentitilor - ct i din atributele specifice fiecrei subentiti. Avantajul unor
astfel de supertabele este simplificarea programelor de manipulare a datelor. Pe de alt parte
ns, ele creeaz probleme suplimentare privind integritatea datelor, de exemplu dac vom avea
un singur tabel pentru tot personalul din facultate, atunci cnd se insereaz n tabel un rnd
corespunztor unui profesor numai atributele specifice pot avea valori diferite de Null. n plus,
subtabelele obinute din descompunerea unui astfel de supertabel sunt mai stabile, mai flexibile,
ocup spaiu fizic mai mic i conin mai puine valori Null.
Transformarea relaiilor:
Relaiile 1:1 devin chei strine, cheia strin fiind plasat n tabelul cu mai puine linii. De
exemplu, relaia conduce dintre PROFESOR i FACULTATE se realizeaz prin inserarea unei
chei strine n tabelul FACULTATE care face referin la cheia primar a tabelului PROFESOR,
vezi figura 2.20.
Not: Plasamentul cheii strine va fi indicat printr-o sgeat (
), iar cnd cheia strin va fi
coninut n cheia primar, atunci vrful sgeii va fi umplut (
).
Deci ntr-o relaie 1:1 poziia cheii strine depinde de cardinalitatea minim a relaiei. Dac
aceasta este tot 1:1, atunci cheia strin poate fi plasat n oricare din cele dou tabele. Dac ns
aceast cardinalitate minim este 1:0, atunci cheia strin este plasat n tabelul a crui
cardinalitate minim n relaie este 0.
Relaiile N:1 devin chei strine plasate n tabelul care se afl de partea muli a relaiei. De
exemplu relaia lucreaz_n va fi realizat prin inserarea unei chei strine n tabelul
PROFESOR care va face referin la cheia primar a tabelului FACULTATE, vezi figura 2.21.
i n cazul relaiilor N:1 se disting dou cazuri n funcie de cardinalitatea minim a relaiei.
Dac aceasta este 0:1, atunci cheia strin respectiv nu poate avea valoarea Null, iar n cazul
entitilor dependente ea va face chiar parte din cheia primar a tabelului. Dac ns
44

cardinalitatea minim a relaiei este 0:0 atunci cheia strin poate avea valoarea Null i nu poate
face parte din cheia primar.
O relaie muli-la-muli se transform ntr-un tabel special, numit tabel asociativ, care are dou
chei strine pentru cele dou tabele asociate; cheia primar a tabelului asociativ este compus din
aceste dou chei strine plus eventual alte coloane adiionale. n acest caz se spune c o relaie
muli-la-muli se sparge n dou relaii muli-la-unu, tabelul asociativ fiind n relaie de muli-launu cu fiecare dintre cele dou tabele entitate. De exemplu, relaia pred dintre PROFESOR i
CURS se realizeaz printr-un tabel a crui cheie primar este combinaia cheilor strine ale
acestor dou entiti, vezi figura 2.22.
O relaie de tip 3 (relaie ntre mai mult de dou entiti) devine un tabel asociativ care are cte o
cheie strin pentru fiecare dintre tabelele asociate; cheia primar este compus din aceste chei
strine plus eventual alte coloane adiionale. De exemplu, tabelul reprezentat n figura 2.23
exprim relaia efectueaz_coordoneaz dintre STUDENT, PROIECT i PROFESOR. n acest
caz, cheia primar este combinaia cheilor strine corespunztoare celor trei entiti.
Transformarea atributelor:
Atributele simple ale unei entiti devin coloane n tabelul provenit din entitatea corespunztoare.
De asemenea, fiecare component a unui atribut compus devine o coloan n tabel. De exemplu,
pentru atributul compus adres, format din ar, ora, strad, numr i cod, vom avea cinci
coloane, cte una pentru fiecare component a sa.
Atributele repetitive (multivaloare) ale unei entiti devin tabele dependente ce conin o cheie
strin (care face referin la cheia primar a entitii) i atributul multivaloare; cheia primar a
acestui nou tabel este format din cheia strin plus una sau mai multe coloane adiionale. De
exemplu, dac presupunem c un student poate avea mai multe numere de telefon, atunci
nr_telefon este un atribut multivaloare al entitii STUDENT, care va da natere unui tabel
TELEFON, a crui cheie primar va fi combinaia dintre cod_student i nr_telefon, vezi
figura 2.24.
Atributele simple ale unei relaii 1:1 sau 1:N vor deveni coloane ale tabelului care conine cheia
strin. De exemplu, data angajrii, care este un atribut al relaiei lucreaz_n dintre
PROFESOR i FACULTATE, va fi reprezentat ca o coloan n tabelul PROFESOR.
De asemenea, fiecare atribut compus al unei relaii 1:1 sau 1:N va deveni o coloan n tabelul
care conine cheia strin.
Atributele simple ale unei relaii N:M vor deveni coloane ale tabelului asociativ. De exemplu,
nota obinut la examen, care este un atribut al relaiei urmeaz dintre STUDENT i CURS va
fi reprezentat ca o coloan n tabelul asociativ corespunztor acestei relaii.
De asemenea, fiecare component a unui atribut compus al unei relaii N:M va deveni o coloan
n tabelul asociativ.
Atributele repetitive (multivaloare) ale unei relaii 1:1 sau 1:N vor deveni tabele dependente de
tabelul care conine cheia strin, iar atributele repetitive ale unei relaii N:M vor deveni tabele
dependente de tabelul asociativ corespunztor relaiei. Evident, cheia primar a acestor tabele
dependente va fi o combinaie format din cheia strin respectiv i una sau mai multe coloane
adiionale. De exemplu, dac presupunem n cadrul anumitor cursuri studenii trebuie s dea un
numr de teste, atunci test va fi un atribut multivaloare al relaiei urmeaz dintre STUDENT
45

i CURS i care va da natere unui tabel dependent de tabelul asociativ al acestei relaii, vezi
figura 2.25.

PROFESOR

1(0)

conduce

1(0)

FACULTATE
cod_facultate

cod_personal

Figura 2.20
PROFESOR

M(0)

lucreaz _n

FACULTATE
cod_facultate

cod_personal

Figura 2.21
PROFESOR

CURS

PRED
1

M(0)

cod_personal

M(0)

1
cod_curs

cod_personal
cod_curs

Figura 2.22
PROFESOR
cod_personal
1
M(0)
EFECTUEAZ_
COORDONEAZ

STUDENT
1
cod_student

M(0)

PROIECT
M(0)

cod_student
cod_proiect
cod_personal

Figura 2.23

46

1
cod_proiect

STUDENT

M(0)

TELEFON
cod_student
nr_telefon

cod_student

Figura 2.24
TEST
cod_student
cod_curs
nr_test
M(0)
1
STUDENT
1
cod_student

CURS

URMEAZ
M(0)

M(0)
cod_student
cod_curs

1
cod_curs

Figura 2.25
n figura 2.26 este prezentat diagrama logic a bazei de date pentru sistemul descris ca exemplu.
Aceasta a rezultat din diagrama entitate-legtur, n urma transformrilor prezentate mai sus.

47

PERSONAL
cod_personal
nume, prenume, data_naterii
PERSONAL_ADMINISTRATIV
FACULTATE
cod_facultate
nume_facultate

1
1(0)

M(0)

lucreaz _
n
conduce

1(0)
1

M(0)
PROFESOR
grad_didactic

studiaz _la
M(0)

STUDENT
1

cod_student
nume
prenume
data_naterii

M(0)

EFECTUAZA
COORDONEAZA
M(0)

M(0)
cod_student
cod_proiect
cod_personal

PROIECT

PREDA

cod_proiect
nume_proiect

cod_personal
cod_curs
M(0)

1
URMEAZA
M(0)

M(0)

cod_student
cod_curs

CURS
M(0)

TELEFON
cod_student
nr_telefon

1(0)
1

M(0)

este_ef

cod_curs
nume_curs
descriere
1
face_parte_din

M(0)

M(0)

TEST

MODUL

cod_student
cod_curs
nr_test

cod_curs
nr_modul
descriere

Figura 2.26
Tabelele asociate acestei diagrame sunt urmtoarele:
PERSONAL (cod_personal, nume, prenume, data_nastere, sex, stare_civila)
PERSONAL_ADMINISTRATIV (cod_personal, profesie, funcie)
PROFESOR (cod_personal, grad_didactic, titlu, sef, ore_predate, data_angajrii, cod_facultate)
CURS (cod_curs, nume_curs, descriere, nr_ore)
PREDA (cod_personal, cod_curs)
MODUL (cod_curs, nr_modul, descriere)
48

FACULTATE (cod_facultate, nume_facultate, localitate, strada, nr, cod_postal cod_decan)


STUDENT (cod_student, nume, prenume, data_nasterii, tara, localitate, strada, nr, cod_postal,
studii_anterioare)
TELEFON (cod_student, nr_telefon, tip_telefon)
PROIECT (cod_proiect, nume_proiect, domeniu)
EFECTUEAZA_COORDONEAZA (cod_student, cod_proiect, cod_personal)
URMEAZA (cod_student, cod_curs, nota_examen, nota_restant, observatii)
TEST (cod_student, cod_curs, nr_test, nota_test, observatii)
Not: Atributele subliniate constituie cheia primar a tabelului iar cele italice constituie chei
strine.
Exemplu
Pentru urmtorul scenariu s se realizeze diagrama logic a bazei de date i s se defineasc tabelele
corespunztoare evideniindu-se cheile primare i cheile strine.
Un spital este organizat n saloane, fiecare avnd mai muli pacieni. Fiecare doctor din spital
aparine unei anumite secii condus de un ef de secie care este tot doctor. Fiecare doctor este
responsabil de mai muli pacieni, un pacient putnd fi tratat de unul sau mai muli doctori.

SALON

con ine

M(0)

PACIENT
cod_pacient

nr_salon
1
are
M(0)
ASISTENTA

1
M(0)
TRATAMENT
cod_pacient
cod_doctor

cod_asistenta

M(0)
1
DOCTOR
cod_doctor
1(0)
M(0)
conduce lucreaza n
1(0)
1
SECTIE
Figura 2.27

cod_sectie

Diagrama logic a bazei de date pentru acest sistem este reprezentat n figura 2.27. Tabelele
asociate acestei diagrame sunt urmtoarele:
SALON (nr_salon, capacitate, etaj)
ASISTENTA (cod_asistenta, nume, prenume, nr_salon)
PACIENT (cod_pacient, nume, prenume, data_natere, sex, nr_salon)
49

DOCTOR (cod_doctor, nume, prenume, grad, statut, cod_sectie)


TRATAMENT (cod_pacient, cod_doctor, descriere)
SECTIE (cod_sectie, denumire, camera_garda, sef)

50

2.3. Normalizarea bazei de date.


n general, pentru proiectarea unei baze de date relaionale se creeaz mai nti schema conceptual
a acesteia (folosind de obicei modelul entitate-legtur), care este transformat apoi ntr-un design
logic, folosind metodologia descris n seciunile precedente. n trecut ns, n locul acestei tehnici
de modelare conceptual, proiectarea unei baze de date relaionale se fcea folosindu-se o tehnic
numit normalizare, ce const din descompunerea unui tabel relaional n mai multe tabele care
satisfac anumite reguli i care stocheaz aceleai date ca i cel iniial. n prezent, normalizarea se
folosete pentru a rafina designul logic al bazei de date rezultat n urma transformrii schemei
conceptuale, eliminnd unele probleme care pot apare n urma procesului de proiectare iniial.
Evident, dac schema conceptual este corect i dac transformarea acesteia n tabele relaionale
este corect, procesul de normalizare nu mai este necesar. Totui, cunoaterea acestei tehnici este
necesar deoarece ea stabilete criteriile pe care trebuie s le ndeplineasc un design corect al unei
baze de date relaionale.
Dup transformarea modelului entitate-legtur n tabele relaionale, n baza de date rezultat poate
exista redundan n date ct i anomalii de actualizare, adic anumite rezultate nedorite n timpul
ncrcrii, exploatrii i ntreinerii bazei de date.
n continuare vom ilustra cu ajutorul unui exemplu, aceste posibile deficiene ale bazei de date,
precum i modul n care tehnica normalizrii nltur aceste rezultate nedorite. nainte ns, dm
urmtoarea definiie:
Fie R un tabel relaional i fie X i Y dou submulimi de coloane ale lui R. Vom spune c X
determin funcional pe Y sau Y depinde funcional de X dac nu exist dou rnduri n tabelul R
care s aib aceleai valori pentru coloanele din X i s aib valori diferite pentru cel puin o
coloan din Y. Cu alte cuvinte, o valoare a lui X determin n mod unic o valoare a lui Y, adic
oricare dou rnduri din R care au aceeai valoare pentru X trebuie s ia aceeai valoare pentru Y.
Notaia utilizat pentru descrierea dependenei funcionale este X Y. X se va numi determinant,
iar Y determinat. Spunem c dependena X Y este trivial dac toate elementele lui Y sunt i
elemente ale lui X, Y X.
S considerm acum tabelul relaional:
VNZRI (cod_client, nume_client, nr_telefon, cod_comand, data,
cod_articol, nume_articol, cost_articol, cantitate)
Tabelul de mai sus se folosete pentru nregistrarea tranzaciilor unui magazin ce vinde articole la
comand, vezi figura 2.28. Coloanele subliniate constituie cheia primar a tabelului.
VNZRI
cod_
nume_
client
client
A1
Popescu
A1
Popescu
A2
Ionescu
A2
Ionescu
A2
Ionescu
A1
Popescu
A3
Georgescu

nr_
telefon
3215576
3215576
2325587
2325587
2325587
3215576
4555895

cod_
comand
C1
C1
C2
C2
C2
C3
C4

data
12.05.99
12.05.99
13.05.99
13.05.99
13.05.99
14.05.99
14.05.99
51

cod_
articol
P1
P3
P1
P3
P2
P3
P1

nume_
articol
cma
tricou
cma
tricou
pantaloni
tricou
cma

cost_
articol
100.000
50.000
100.000
50.000
200.000
50.000
100.000

cantitate
2
1
3
2
1
3
1

Figura 2.28: tabelul VNZRI


n mod evident, numele clientului i numrul su de telefon vor fi dependente de codul clientului,
data la care a fost efectuat comanda va depinde de codul acesteia, iar numele i costul articolului
vor fi dependente de codul acestuia. n plus, vom presupune, aa cum este i normal, c o comand
poate fi fcut de un singur client, cu alte cuvinte codul clientului, i implicit i numele i numrul
de telefon al acestuia, vor depinde de codul comenzii. Cu alte cuvinte, n tabelul de mai sus am
identificat urmtoarele dependene funcionale pentru care determinantul nu este cheie a tabelului:
{cod_articol} {nume_articol, cost_articol}
{cod_comand} {data, cod_client, nume_client, nr_telefon}
{cod_client} {nume_client, nr_telefon}
Not: dependena {cod_comand} {nume_client, nr_telefon} poate fi dedus din dependenele
{cod_comand} {cod_client} si {cod_client} {nume_client, nr_telefon}. Astfel de
dependene se numesc dependene tranzitive i vor fi definite mai riguros n seciunea 2.3.3.
Datorit acestor dependene, n tabelul prezentat mai sus pot s apar urmtoarele deficiene:
Poate exista redundan n date, adic unele informaii apar de mai multe ori. De exemplu,
numele i costul articolului cu codul P1 (P1, cma, 100.000) sunt specificate de 3 ori i tot de 3
ori sunt specificate numele i numrul de telefon ale clientului cu codul A1 (A1, Popescu,
3215576).
Pot apare anomalii la actualizare:
Anomalie la inserie. S presupunem c magazinul a achiziionat un nou articol pe care
urmeaz s-l vnd, de exemplu un articol codul P4, numele pantofi i costul 250.000.
Totui, tuplul (P4, pantofi, 250.000) nu poate fi inserat n tabelul VNZRI dect dac
exist o comand pentru acest articol - aceasta datorit faptului c trebuie s dm o
valoare diferit de Null coloanei cod_comanda, care face parte din cheia primar. La
fel se ntmpl i dac vrem s inserm datele (numele i numrul de telefon) unui nou
client.
Anomalie la tergere. S presupunem c n cadrul comenzii cu codul C2 este anulat
articolului P2 (pantaloni). tergnd rndul corespunztor - cel pentru care valoarea cheii
primare este (C2, P2) - se pierde i informaia referitoare la numele i costul articolului
respectiv. La fel, dac se terge rndul pentru care valoarea cheii primare este (C4, P1),
se pierde informaia referitoare la clientul cu codul A3.
Anomalie la modificare. S presupunem c s-a schimbat numele articolului P1 de la
cma la bluz. Dac modificarea respectiv se face doar pentru un rnd al
tabelului, atunci n tabel vor apare date incorecte - celelalte dou rnduri vor conine
numele vechi al articolului. Deci aceast modificare trebuie fcut n toate rndurile
pentru care valoarea coloanei cod_articol este P1, costul modificrii fiind n acest caz
semnificativ. La fel se ntmpl i n cazul n care se modific numrul de telefon sau
numele unui client.
Redundana i anomaliile care apar n lucrul cu baza de date sunt datorate dependenelor care exist
n cadrul tabelelor bazei de date, mai precis acele dependene pentru care determinantul nu este
cheie a tabelului. Normalizarea este procesul reversibil de descompunere a unui tabel relaional n
tabele cu o structur mai simpl, proces care are ca scop tocmai evitarea redundanei datelor i
evitarea anomaliilor de actualizare.
Spunem c procesul este reversibil n sensul c descompunerea se face fr pierdere de informaie,
adic tabelul iniial poate fi reconstruit prin compunerea natural pe atribute comune a tabelelor
rezultate. Pentru un tabel R care se descompune prin proiecie n tabelele R1, R2, ..., Rn, condiia de
descompunere fr pierdere de informaie presupune ca R s fie obinut prin compunerea natural a
52

tabelelor R1, R2, , Rn (adic coloanele din R s fie reuniunea coloanelor din R1, R2, ..., Rn i
fiecare rnd din R s fie obinut prin compunerea rndurilor din cele n tabele pentru care valoarea
atributelor comune este identic).
Un caz particular al acestei descompuneri, cel mai des utilizat n construcia formelor normale, este
regula Casey-Delobel: fie un tabel R(X, Y, Z) care se descompune prin proiecie n tabelele R1(X,
Y) i R2(X, Z) - unde prin X am notat coloanele comune ale tabelelor R1 i R2, iar prin Y i Z
coloanele specifice lui R1 i respectiv R2; n acest caz, condiia de descompunere fr pierdere de
informaie presupune ca tabelul R s fie obinut prin compunerea natural a tabelelor R1 si R2
(adic prin compunerea rndurilor celor dou tabele pentru care valorile coloanelor X sunt identice).
ntr-un limbaj pseudo-SQL, compunerea natural a celor dou tabele se scrie n modul urmtor:
SELECT R1.X, R1.Y, R2.Z
FROM R1, R2
WHERE R1.X = R2.X
De exemplu, aplicnd succesiv regula Casey-Delobel, tabelul VNZRI se poate descompune fr
pierdere de informaii n tabelele
VNZRI_1 (cod_client, nume_client, nr_telefon, cod_comand, data, cod_articol, cantitate)
i
ARTICOL (cod_articol, nume_articol, cost_articol), vezi figura 2.29,
iar tabelul VNZRI_1 poate fi descompus n
VNZRI_2 (cod_comand, cod_articol, cantitate), vezi figura 2.30
i
COMANDA_2 (cod_comand, data, cod_client, nume_client, nr_telefon).
La rndul lui, tabelul COMANDA_2 poate fi descompus n tabelele
COMANDA_3 (cod_comand, data, cod_client)
i
CLIENT (cod_client, nume_client, nr_telefon), vezi figura 2.31.
n consecin, tabelul VNZRI poate fi descompus fr pierdere de informaii n tabelele
VNZRI_2, ARTICOL, COMANDA_3 i CLIENT.
VNZRI_1
cod_
nume_
client
client
A1
Popescu
A1
Popescu
A2
Ionescu
A2
Ionescu
A2
Ionescu
A1
Popescu
A3
Georgescu
ARTICOL
cod_
nume_
articol
articol
P1
cma

nr_
telefon
3215576
3215576
2325587
2325587
2325587
3215576
4555895

cod_
comand
C1
C1
C2
C2
C2
C3
C4

cost_
articol
100.000
53

data
12.05.99
12.05.99
13.05.99
13.05.99
13.05.99
14.05.99
14.05.99

cod_
articol
P1
P3
P1
P3
P2
P3
P1

cantitate
2
1
3
2
1
3
1

P2
P3

pantaloni
tricou

200.000
50.000

Figura 2.29
VNZRI_2
cod_
cod_
comand articol
C1
P1
C1
P3
C2
P1
C2
P3
C2
P2
C3
P3
C4
P1
COMANDA_2
cod_
cod_
comand client
C1
A1
C2
A2
C3
A1
C4
A3

cantitate
2
1
3
2
1
3
1
nume_
client
Popescu
Ionescu
Popescu
Georgescu

nr_
telefon
3215576
2325587
3215576
4555895

data
12.05.99
13.05.99
14.05.99
14.05.99

Figura 2.30
COMANDA_3
cod_
cod_
comand
client
C1
A1
C2
A2
C3
A1
C4
A3
CLIENT
cod_
nume_
client
client
A1
Popescu
A2
Ionescu
A3
Georgescu

data
12.05.99
13.05.99
14.05.99
14.05.99
nr_
telefon
3215576
2325587
4555895

Figura 3.31
n plus, procesul de normalizare trebuie s realizeze o descompunere minimal a tabelului iniial,
deci nici o coloan din tabelele rezultate nu poate fi eliminat fr a duce la pierderea de informaii
i implicit la pierderea caracterului ireversibil al transformrii. Ca o consecin, nici unul dintre
tabelele rezultate nu trebuie s fie coninut ntr-altul.
n sfrit, este de dorit ca procesul de normalizare s conserve dependenele dintre date. Aceasta
nseamn c pentru fiecare dependen netranzitiv trebuie ca att determinantul ct i determinatul
s existe ntr-unul din tabelele rezultate prin descompunere. Se poate vedea c aceast cerina este
ndeplinit de descompunerea tabelului VNZRI, fiecare dintre dependenele netranzitive
54

existente n tabel, {cod_articol} {nume_articol, cost_articol}, {cod_comand} {data,


cod_client} i {cod_client} {nume_client, nr_telefon}, regsindu-se ntr-unul dintre tabelele
ARTICOL, COMANDA_3 i CLIENT. Dependenele tranzitive nu trebuie conservate deoarece pot
fi deduse din celelalte. Totui, aa cum vom vedea n continuare, nu ntreg procesul de normalizare
conserv dependenele, aceast cerin putnd fi nclcat n procesul de transformare n formele
normale superioare (BCNF).
Exist o teorie matematic a normalizrii ai cror autori sunt Codd i Fagin. Un tabel este ntr-o
anumit form normal dac satisface un anumit set de constrngeri. Exist ase forme normale:
prima form normal, a doua form normal, a treia form normal, forma normal Boyce-Codd, a
patra form normal i a cincea form normal. Constrngerile pentru o form normal sunt
ntotdeauna mai puternice dect cele pentru formele normale inferioare, de aceea tabelele aflate n a
doua form normal constituie un subset al tabelelor aflate n prima form normal .a.m.d.
2.3.1. Prima form normal (1NF First Normal Form)
Definiie 1NF
Un tabel relaional este n prima form normal (1NF) dac fiecrei coloane i corespunde o valoare
indivizibil (atomic), deci orice valoare nu poate s fie o mulime sau un tuplu de valori. n plus,
nu pot s apar grupuri de atribute repetitive.
Tabelul VNZRI (figura 2.28) se afl n prima form normal.
De exemplu, pentru o coloan care conine date calendaristice, sub forma zz-ll-aa (doi digii pentru
zi, doi pentru lun i doi pentru an), se consider c valoarea respectiv nu se poate descompune n
ziua, luna i anul corespunztoare acestei valori. Pe de alt parte ns, dac vom considera c adresa
este un atribut compus format din componentele ar, ora, strad, numr i cod, fiecare avnd
semnificaie proprie i putnd fi folosite independent la interogarea bazei de date, atunci adresa va fi
reprezentat n tabel prin 5 coloane n loc de una. De asemenea, un tabel aflat n 1NF nu poate
conine atribute sau grupuri de atribute repetitive. De exemplu, n tabelul de mai jos, dac un
student poate avea mai multe numere de telefon, atunci coloanele telefon1, telefon2, telefon3
constituie un grup de atribute repetitive. Deci tabelul STUDENT de mai jos nu este n prima form
normal, el coninnd att un atribut compus (adresa) ct i un grup de atribute repetitive.
cod_
student
101

nume

prenume

Ionescu

Vasile

101

Ionescu

Vasile

102

Pop

Costic

STUDENT
adresa
telefon1
Romania, 6245981
Bucureti,
Str. Polizu
5, 7355
Romania, 6245981
Bucureti,
Str. Polizu
5, 7355
Romania, 3215469
Cluj,
Str. Unirii
7, 3551

Figura 2.32

55

telefon2

telefon3

materia

nota

3215678

092659019

Drept

10

3215678

092659019

Engleza 8

Fizic

Algoritmul 1NFA permite aducerea unei relaii n 1NF prin eliminarea atributelor compuse i a
celor repetitive.
Algoritmul 1NFA
1. Se nlocuiesc n tabel coloanele corespunztoare atributelor compuse cu coloane ce conin
componentele elementare ale acestora.
2. Se plaseaz grupurile de atribute repetitive, fiecare n cte un nou tabel.
3. Se introduce n fiecare tabel nou creat la pasul 2 cheia primar a tabelului din care a fost extras
atributul respectiv. Prin urmare, n tabelul nou creat atributele introduse vor fi chei strine ce fac
referin la tabelul din care au fost extrase.
4. Se stabilete cheia primar a fiecrui nou tabel creat la pasul 2. Aceasta va fi creat din cheia
strin introdus la pasul 3 plus una sau mai multe coloane adiionale.
Prin aplicarea algoritmului de mai sus, tabelul STUDENT se descompune n tabelele STUDENT_1
i TELEFON, aflate amndou n 1NF.
nume

prenume

STUDENT_1
ora
strad

cod_
student
101

ar

Ionescu

Vasile

Romania

Bucuret
i

101

Ionescu

Vasile

Romania

102

Pop

Costic

Romania

Bucuret
i
Cluj

nr Cod_potal

materia

not
a
10

Polizu

7355

Drept

Polizu

7355

Engleza 8

Unirii

3551

Fizic

TELEFON
cod_
telefon
student
101
6245981
101
3215678
101 092659019
102
3215469
Figura 2.33
Prima form normal este o cerin minimal a tuturor sistemelor relaionale. Sistemele de baze de
date care nu respect nici mcar aceast form nu pot fi numite relaionale. Tabelele aflate n prima
form normal permit o referire simpl a datelor prin indicarea numelui tabelului, a coloanei i a
cheii rndului din care face parte informaia respectiv. Operatorii pentru aceste tabele sunt mai
simpli i permit definirea unor tehnici de proiectare i utilizare a bazelor de date.
2.3.2. A doua form normal (2NF Second Normal Form)
S vedem acum modul n care procesul de normalizare nltur redundana logic i anomaliile de
actualizare semnalate la nceputul acestei seciuni. Pentru acest lucru dm nti urmtoarea definiie.
Fie R un tabel relaional i fie X i Y dou submulimi de coloane ale lui R. O dependen
funcional X Y se numete total dac pentru orice subset de coloane Z al lui X, Z X, dac Z
Y atunci Z = X. Cu alte cuvinte, nu exist nici un subset Z al lui X, Z X, pentru care Z Y. O
relaie funcional care nu este total se numete parial.

56

Se observ c n tabelul VNZRI (figura 2.28) exist redundan n date - de exemplu (P1,
cma, 100.000) - datorat faptului c atributele nume_articol i cost_articol nu depind de
cod_comand, care este o component a cheii primare a tabelului. Cu alte cuvinte, n tabelul
VNZRI exist o dependen parial de cheia primar. Acest tip de dependene vor fi nlturate
n a doua form normal.
Definiie 2NF
Un tabel relaional R este n a doua form normal (2NF) dac i numai dac:
R este n 1NF
Orice coloan care depinde parial de o cheie a lui R este inclus n acea cheie.
Cu alte cuvinte, a doua form normal nu permite dependene funcionale pariale fa de cheile
tabelului, cu excepia dependenelor triviale, de incluziune. Deci tabelul VNZRI nu este n 2NF,
coloanele nume_articol i cost_articol depinznd parial de cheia primar a tabelului.
Pentru a obine tabele relaionale n 2NF, tabelul iniial se descompune fr pierdere de informaie
dup urmtoarea regul: Fie R(K1, K2, X, Y) un tabel relaional unde K1, K2, X i Y sunt
submulimi de coloane ale lui R astfel nct K1 K2 este o cheie a lui R, iar K1 X este o
dependen funcional total. Dac X K1 atunci tabelul este deja n 2NF, altfel tabelul R poate fi
descompus prin proiecie n R1(K1, K2, Y) - avnd cheia K1 K2 - i R2(K1, X) - avnd cheia
K1. Remarcai c aceast descompunere conserv nu numai datele, ci i dependenele funcionale,
att determinantul ct i determinatul dependenei eliminate regsindu-se n tabelul nou creat.
Folosind aceast regul, algoritmul 2NFA permite aducerea n 2NF a unui tabel relaional aflat n
1NF prin eliminarea dependenelor funcionale pariale.
Algoritm 2NFA
1. Pentru fiecare coloan X care depinde funcional parial de o cheie K, K X, i care nu este
inclus n K, se determin K1 K un subset al lui K, astfel nct dependena K1 X este
total i se creeaz un nou tabel R1(K1, X), adic un tabel format din determinantul (K1) i
determinatul (X) acestei relaii.
2. Dac n tabelul R exist mai multe dependene totale ca mai sus cu acelai determinant, atunci
pentru acestea se creeaz un singur tabel format din determinant - luat o singur dat - i din
determinaii dependenelor considerate
3. Se elimin din tabelul iniial R toate coloanele, X, care formeaz determinatul dependenei
considerate.
4. Se determin cheia primar a fiecrui tabel nou creat, R1. Acesta va fi K1, determinantul
dependenei considerate.
5. Dac noile tabele create conin alte dependene pariale, atunci se merge la pasul 1, altfel
algoritmul se termin.
Pentru tabelul VNZRI cheia primar este {cod_comand, cod_articol}. Atributul
nume_articol i cost_articol depind funcional parial de aceast cheie primar i depind
funcional total de atributul cod_articol coninut n cheia primar. Acelai lucru se ntmpl i cu
atributele data, cod_client, nume_client i nr_telefon care depind funcional total numai de
atributul cod_comand coninut n cheia primar. Prin urmare vom avea urmtoarele dependene
totale:
{cod_comand} {data, cod_client, nume_client, nr_telefon}
{cod_articol} {nume_articol, cost_articol}
n consecin, tabelul VNZRI va fi descompus n tabelele VNZRI_2, COMANDA_2 i
ARTICOL, care sunt toate n 2NF, vezi figura 2.34.
57

COMANDA_2
VNZRI_1

M
VNZRI

M
VNZRI_2

1
ARTICOL

M
1
ARTICOL

Figura 2.34
Se observ c un tabel care are cheia primar format dintr-un singur atribut este automat n 2NF.
Prin urmare, algoritmul 2NFA nu se poate aplica dect n cazul n care cheia primar a unui tabel
este o cheie compus.
2.3.3. A treia form normal (3NF Third Normal Form)
Dei tabelul COMANDA_2 este n 2NF, se observ c nc mai exist redundan n date - tuplul
(A1, Popescu, 3215576) apare de dou ori. Intuitiv, aceasta se explic prin faptul c atributele
nume_client i nr_telefon depind indirect de cheia primar a tabelului, dependena fcndu-se
prin intermediul atributului cod_client. Aceste dependene indirecte vor fi ndeprtate n 3NF.
Definiie 3NF
Un tabel relaional R este n a treia form normal (3NF) dac i numai dac:
R este n 2NF
Pentru orice coloan A neconinut n nici o cheie a lui R, dac exist un set de coloane X astfel
nct X A, atunci fie X conine o cheie a lui R, fie A este inclus n X.
A doua condiie din definiie interzice dependenele funcionale totale fa de alte coloane n afara
celor care constituie chei ale tabelului. Prin urmare, un tabel este n 3NF dac orice coloan care nu
este coninut ntr-o cheie depinde de cheie, de ntreaga cheie i numai de cheie. n mod evident
tabelul COMANDA_2 nu este n 3NF existnd dependenele {cod_client} {nume_client} i
{cod_client} {nr_telefon}. Pe de alt parte, tabelele VNZRI_2 i ARTICOL sunt n 3NF.
Adesea, cea de-a doua condiie din definiia de mai sus se formuleaz folosind noiunea de
dependen tranzitiv. Fie R un tabel relaional, X o submulime de coloane a lui R i A o coloan a
lui R. Spunem c A este dependent tranzitiv de X dac exist o submulime de coloane Y care nu
include A i nu determin funcional pe X astfel nct X Y i Y A. Dac n aceast definiie se
dorete s se evidenieze i Y atunci se spune c A depinde funcional de X prin intermediul lui Y i
se scrie X Y A. De exemplu, n tabelul COMANDA_2 coloanele nume_client i
nr_telefon depind tranzitiv de cheia primar cod_comand prin intermediul coloanei
cod_client. Folosind aceast definiie, condiia ca un tabel s fie n 3NF se poate reformula astfel:
Definiie 3NF
Un tabel relaional R este n a treia form normal (3NF) dac i numai dac:
R este n 2NF
Orice coloan neconinut n nici o cheie a lui R nu este dependent tranzitiv de nici o cheie a lui
R.

58

Pentru a obine tabele relaionale n 3NF, tabelul iniial se descompune fr pierdere de informaie
dup urmtoarele reguli. Fie R(K, X, Y, Z) un tabel relaional unde K este o cheie a lui R, iar X, Y
i Z sunt submulimi de coloane ale lui R.
a. Dac exist dependena tranzitiv K X Y, atunci R se poate descompune n R1(K, X, Z) avnd cheia K - i R2(X, Y) - avnd cheia X.
b. Dependena tranzitiv poate fi mai complex. Fie K1 K o parte a cheii K astfel nct exist
dependena tranzitiv K X1 Y, unde X1 = K1 X. n acest caz, R poate fi descompus n
R1(K, X, Z) - avnd cheia K - i R2(K1, X, Y) - avnd cheia K1 X
Remarcai c descompunerile corespunztoare regulilor de mai sus conserv nu numai datele, ci i
dependenele funcionale, determinantul i determinatul dependenelor eliminate regsindu-se n
tabelele nou create.
Un exemplu de aplicare a primei reguli este descompunerea tabelului COMANDA_2 n
COMANDA_3 i CLIENT, amndou fiind n 3NF.
COMANDA_3
M
COMANDA_2

1
CLIENT

Figura 2.35
Pentru a exemplifica cea de-a doua regul, s lum tabelul PROIECTE (cod_angajat, cod_proiect,
rol_n_proiect, suma_obinut), vezi figura 2.36, care stocheaz date privind repartizarea pe
proiecte a angajailor unei firme. S presupunem c suma obinut de un angajat depinde de
proiectul respectiv i de rolul angajatului n acel proiect, deci avem dependena {cod_proiect,
rol_n_proiect} {suma_obinut}. Aplicnd regula a doua de mai sus, tabelul PROIECTE se
descompune n tabelele PROIECTE_3 (cod_angajat, cod_proiect, rol_n_proiect) i SUMA
(cod_proiect, rol_n_proiect, suma_obinut), vezi figurile 2.37 i 2.38.
PROIECTE
cod_
cod_
angajat proiect
A1
P1
A2
P1
A3
P1
A4
P1
A1
P2
A4
P2
Figura 2.36
PROIECTE_3
cod_
cod_
angajat proiect
A1
P1
A2
P1
A3
P1

rol_n_proiect
Programator
Coordonator
Programator
Programator
Programator
Analist

Suma_
Obinut
100.000
150.000
100.000
100.000
90.000
140.000

rol_n_proiect
Programator
Coordonator
Programator
59

A4
A1
A4

P1
P2
P2

Programator
Programator
Analist

SUMA
cod_
rol_n_proiect
proiect
P1
programator
P1
coordonator
P2
programator
P2
analist
Figura 2.37

suma_
obinut
100.000
150.000
90.000
140.000
PROIECTE_3
M
PROIECTE

1
SUMA

Figura 2.38
Folosind aceast regul, algoritmul 3NFA permite aducerea n 3NF a unui tabel relaional aflat n
2NF prin eliminarea dependenelor funcionale tranzitive.
Algoritmul 3NFA
1. Pentru fiecare dependen funcional tranzitiv K X Y se transfer coloanele din X i Y
ntr-o nou relaie.
2. Se determin cheia primar a fiecrei noi relaii create la pasul 1, aceasta fiind format din
coloanele din X.
3. Se elimin din relaia principal coloanele din Y.
4. Dac tabelele rezultate conin alte dependene tranzitive, atunci se merge la pasul 1, altfel
algoritmul se termin.
Aplicnd algoritmii 2NFA i 3NFA, tabelul VNZRI a fost descompus n tabelele VNZRI_2,
ARTICOL, COMANDA_3 i CLIENT, care sunt toate n 3NF. Se poate constata cu uurin c n
aceste tabele nu mai exist nici redundan n date i nici anomalii de actualizare.
COMANDA_3
1

VNZRI

M
VNZRI_2
M
1
ARTICOL

Figura 2.39

60

CLIENT

2.3.4. Forma normal Boyce-Codd (BCNF Boyce-Codd Normal Form)


Totui, nu toate tabelele aflate n a treia form normal sunt lipsite de redundan n date i anomalii
de actualizare. Pentru a ilustra aceast situaie s considerm urmtorul exemplu. O companie de
transporturi efectueaz curse, n care poate folosi unul sau mai muli oferi - de exemplu prima
jumtate a cursei conduce un ofer, cea de-a doua alt ofer - i mai multe dintre autobuzele aflate n
dotare, cu condiia ca ntr-o curs un ofer s conduc un singur autobuz. Pe de alt parte ns, un
autobuz este repartizat unui ofer i deci nu poate fi condus dect de acesta. Aceast situaie poate fi
modelat printr-un tabel TRANSPORTURI (cod_curs, cod_ofer, cod_autobuz, loc_plecare,
loc_sosire), unde ultimele dou coloane indic locul de plecare i locul de pornire a oferului n
curs, vezi figura 2.40. n acest tabel avem dependenele:
{cod_curs, cod_ofer} {cod_autobuz, loc_plecare, loc_sosire}
{cod_autobuz} {cod_ofer}
iar cheile tabelului sunt {cod_curs, cod_ofer} i {cod_curs, cod_autobuz}. Se poate vedea cu
uurin c tabelul TRANSPORTURI este n 3NF i totui n acest tabel exist redundan n date,
tuplurile (S1, A1) i (S2, A2) aprnd de 2 ori, datorit dependenei {cod_autobuz} {cod_ofer}.
TRANSPORTURI
cod_curs
C1
C1
C2
C2
C3

cod_ofer
S1
S2
S2
S1
S1

cod_autobuz
A1
A2
A2
A3
A1

loc_plecare
Constana
Bucureti
Cluj
Sibiu
Bucureti

loc_sosire
Bucureti
Braov
Sibiu
Bucureti
Constana

Figura 2.40
Forma Boyce-Codd elimin acest tip de redundane. Intuitiv, un tabel R este n BCNF dac fiecare
determinant al unei dependene funcionale este cheie candidat a lui R. Tabelul TRANSPORTURI
de mai sus nu este n BCNF, cod_autobuz nefiind o cheie a lui R. O definiie mai riguroas pentru
BCNF este prezentat n continuare.
Definiie BCNF
Un tabel relaional este n forma normal Boyce-Codd (BCNF) dac i numai dac pentru orice
dependen funcional total X A, unde X este un subset de coloane iar A o coloan neconinut
n X, X este o cheie a lui R.
Orice tabel n BCNF este i n 3NF, reciproca fiind fals, dup cum demonstreaz contraexemplul
de mai sus. n plus, orice tabel care are cel mult dou coloane este n BCNF. Orice tabel relaional
se poate descompune fr pierdere de informaie n tabele aflate n BCNF, dar nu acelai lucru se
poate spune despre descompunerea cu pstrarea dependenelor funcionale, dup cum vom vedea n
continuare.
Un algoritm care permite aducerea n BCNF a unui tabel relaional aflat n 3NF prin eliminarea
dependenelor non-cheie este prezentat n continuare.
Algoritmul BCNFA
1. Pentru fiecare dependen non-cheie X Y, unde X i Y sunt subseturi de coloane ale lui R, se
creeaz dou tabele. Una dintre ele va fi format din coloanele {X, Y}, iar cealalt va fi format
din toate coloanele iniiale, mai puin coloanele Y.

61

2. Dac tabelele rezultate conin alte dependene non-cheie, atunci se merge la pasul 1, altfel
algoritmul se termin.
Aplicnd acest algoritm, tabelul TRANSPORTURI de mai sus se va descompune n tabelele
TRANSPORTURI_BC (cod_curs, cod_autobuz, loc_plecare, loc_sosire) i AUTOBUZ
(cod_autobuz, cod_ofer), vezi figura 2.41. Se observ c descompunerea s-a fcut fr pierdere de
informaie, dar a fost pierdut dependena funcional {cod_curs, cod_ofer} {cod_autobuz}.
TRANSPORTURI_BC
cod_curs cod_autobuz
C1
A1
C1
A2
C2
A2
C2
A3
C3
A1
AUTOBUZ
cod_autobuz
A1
A2
A3

loc_plecare
Constana
Bucureti
Cluj
Sibiu
Bucureti

loc_sosire
Bucureti
Braov
Sibiu
Bucureti
Constana

cod_ofer
S1
S2
S1

Figura 2.41
2.3.5. A patra form normal (4NF Fourth Normal Form)
Dac BCNF elimin redundanele datorate dependenelor funcionale, 4NF determin redundanele
datorate dependenelor multivaloare. Pentru a ilustra acest tip de redundane, s considerm tabelul
ANGAJAI (cod_angajat, limba_strin, maina) aflat n BCNF, vezi figura 2.42. Un angajat poate
cunoate mai multe limbi strine i poate avea mai multe maini, dar nu exist nici o legtur ntre
limba strin i main. Cu alte cuvinte, redundana datelor din tabelul ANGAJAI este cauzat de
existena a dou relaii N:M independente, vezi figura 2.43. A patra form normal va nltura
aceste relaii N:M independente.
ANGAJAI
cod_angajat
A1
A1
A1
A1
A1
A1
A2
A2

limba_strin
Englez
Francez
Italian
Englez
Francez
Italian
Englez
Francez

Maina
Ford Mondeo
Ford Mondeo
Ford Mondeo
Skoda Octavia
Skoda Octavia
Skoda Octavia
Ford Mondeo
Ford Mondeo

Figura 2.42.

62

limba_str in M

cod_angajat M

maina

Figura 2.43
Pentru a defini mai riguros constrngerile impuse de 4NF dm nti urmtoarea definiie. Fie R un
tabel relaional, X i Y dou submulimi de coloane ale lui R i Z = R - X - Y mulimea coloanelor
din R care nu sunt nici n X nici n Y. Spunem c exist o dependen multivaloare Y de X sau c X
determin multivaloare pe Y, i notm X Y, dac, pentru orice valoare a coloanelor lui X, sunt
asociate valori pentru coloanele din Y care nu sunt corelate n nici un fel cu valorile coloanelor lui
Z. Cu alte cuvinte X Y dac i numai dac oricare ar fi u i v dou rnduri ale lui R cu u(X) =
v(X), exist s i t dou rnduri ale lui R astfel nct s(X) = u(X), s(Y) = u(Y), s(Z) = v(Z) i astfel
nct t(X) = u(X), t(Y) = v(Y), t(Z) = u(Z) (vezi figura 2.44) unde prin u(X) am notat valoarea
coloanelor X corespunztoare rndului u, etc. n mod evident, dac X Y atunci i X Z.
Dependena multivaloare se mai numete i multidependen.

u
v
s
t

X
x
x
x
x

Y
y1
y2
y1
y2

Z
z1
z2
z2
z1

Figura 2.44.
De exemplu, n tabelul ANGAJAI avem dependenele multivaloare cod_angajat
limba_strin i cod_angajat maina. Pe de alt parte ns, nici limba_strin i nici
maina nu depinde funcional de cod_angajat.
Orice dependen funcional este i o dependen multivaloare, dar afirmaia reciproc nu este n
general adevrat, dup cum demonstreaz contraexemplul de mai sus. Un tabel care se afl n
BNCF i pentru care aceast afirmaie reciproc este adevrat se afl n 4NF.
Definiie 4NF
Un tabel relaional R este n a patra form normal (4NF) dac i numai dac:
R este n BCNF
Orice dependen multivaloare X Y este de fapt o dependen funcional X Y.
Condiia a doua arat c dac exist o dependen multivaloare X Y, atunci orice coloan, A, a
lui R va depinde funcional de coloanele din X, X A - aceasta deoarece existena unei
dependene multivaloare X Y implic i existena unei dependene multivaloare X (R - X
- Y). innd cont de faptul c R este n BCNF, nseamn c exist o cheie candidat a lui R inclus
n X. Deci definiia de mai sus se poate reformula astfel:
Definiie 4NF
Un tabel relaional R este n a patra form normal (4NF) dac i numai dac pentru orice
dependen multivaloare X Y exist o cheie a lui R inclus n X.
Un tabel poate fi adus n 4NF prin descompunere fr pierdere de informaie dup urmtoarea
regul. Fie R(X, Y, Z) un tabel relaional n care exist o dependen multivaloare X Y astfel

63

nct X nu conine nici o cheie a lui R. Atunci tabelul R poate fi descompus prin proiecie n dou
tabele R1(X, Y) i R2(X, Z).
Aplicnd aceast regul tabelul ANGAJAI se descompune n tabelele ANGAJAI_4A
(cod_angajat, limba_strin), ANGAJAI_4B (cod_angajat, maina), vezi figura 2.45, aflate
amndou n 4NF.
ANGAJAI_4A
cod_angajat limba_strin
A1
Englez
A1
Francez
A1
Italian
A2
Englez
A2
Francez
ANGAJAI_4B
cod_angajat maina
A1
Ford Mondeo
A1
Skoda Octavia
A2
Ford Mondeo
Figura 2.45
Aplicnd recursiv aceast regul, algoritmul 4NFA permite aducerea unui tabel relaional din
BNCF n 4NF prin eliminarea dependenelor multivaloare.
Algoritmul 4NFA
1. Se identific dependenele multivaloare X Y pentru care X i Y nu conin toate coloanele
lui R i X nu conin nici o cheie a lui R. Se poate presupune c X i Y sunt disjuncte datorit
faptului c din X Y rezult X (Y - X).
2. Se nlocuiete tabelul iniial R cu dou tabele, primul format din coloanele {X, Y}, iar cellalt
din toate coloanele iniiale, mai puin coloanele Y.
3. Dac tabelele rezultate conin alte dependene multivaloare, atunci se face transfer la pasul 1,
altfel algoritmul se termin.
2.3.6. A cincea form normal (5NF Fifth Normal Form)
A cincea form se ntlnete destul de rar n practic, ea avnd mai mult valoare teoretic. Dac n a
patra form normal sunt eliminate relaiile N:M independente, a cincea form normal are ca scop
eliminarea relaiilor N:M dependente. Redundanele datorate unor astfel de relaii pot fi nlturate
prin descompunerea tabelului n 3 sau mai multe tabele. Pentru a ilustra acest tip de redundane, s
considerm tabelul LUCRTOR_ATELIER_PRODUS (cod_lucrtor, cod_atelier, cod_produs),
aflat n 4NF. Aparent acest tabel este ilustrarea unei relaii de tip 3 care exist ntre lucrtor, atelier
i produs. Dac ns presupunem c ntre lucrtor i atelier, lucrtor i produs, atelier i produs
exist relaii N:M, vezi figura 2.47, atunci n tabel pot exista redundane n date - tuplurile (L2, A1),
(L2, P1) i (A1, P1) apar de 2 ori, vezi figura 2.46, care pot fi nlturate prin descompunerea
tabelului LUCRTORI n 3 tabele, LUCRTOR_ATELIER (cod_lucrtor, cod_atelier),
LUCRTOR_PRODUS (cod_lucrtor, cod_produs) i ATELIER_PRODUS (cod_atelier,
cod_produs), vezi figura 2.48. Se observ c tabelul LUCRTOR_ATELIER elimin redundana
(L2, A1), tabelul LUCRTOR_PRODUS elimin redundana (L2, P1), n timp ce tabelul
ATELIER_PRODUS elimin redundana (A1, P1). De asemenea, se poate vedea c tabelul iniial
LUCRTOR_ATELIER_PRODUS nu poate fi reconstituit din compunerea a doar dou din
64

tabelele componente, vezi figura 2.49, unde tabelul R_12 rezult din compunerea tabelelor
LUCRTOR_ATELIER i LUCRTOR_PRODUS, R_13 rezult din compunerea tabelelor
LUCRTOR_ATELIER i ATELIER_PRODUS, iar R_23 rezult din compunerea tabelelor
LUCRTOR_PRODUS
i
ATELIER_PRODUS.
Pe
alt
parte,
tabelul
iniial
LUCRTOR_ATELIER_PRODUS poate fi obinut prin compunerea tuturor celor trei tabele
componente, de exemplu el rezult prin compunerea lui R_12 cu ATELIER_PRODUS.
LUCRTOR_ATELIER_PRODUS
Cod_lucrtor
cod_atelier cod_produs
L1
A1
P1
L2
A1
P2
L2
A1
P1
L2
A2
P1
Figura 2.46

cod_atelier
M

M
cod_lucr tor M

M
cod_produs

Figura 2.47
LUCRTOR_ATELIER
Cod_lucrtor cod_atelier
L1
A1
L2
A1
L2
A2
LUCRTOR_PRODUS
Cod_lucrtor cod_produs
L1
P1
L2
P2
L2
P1
ATELIER_PRODUS
Cod_atelier cod_atelier
A1
P1
A1
P2
A2
P1
Figura 2.48
R_12
Cod_lucrtor
L1

cod_atelier
A1

cod_produs
P1
65

L2
L2
L2
L2

A1
A1
A2
A2

P2
P1
P2
P1

R_13
Cod_lucrtor
L1
L1
L2
L2
L2

cod_atelier
A1
A1
A1
A1
A2

cod_produs
P1
P2
P2
P1
P1

R_23
Cod_lucrtor
L1
L1
L2
L2
L2

cod_atelier
A1
A2
A1
A1
A2

cod_produs
P1
P1
P2
P1
P1

Figura 2.49
Dependena funcional i dependena multivaloare, i implicit regulile de descompunere pentru
formele normale 1NF-4NF, permit descompunerea prin proiecie a unui tabel relaional n dou
tabele relaionale. Totui, regulile de descompunere asociate acestor forme normale nu dau toate
descompunerile posibile prin proiecie a unui tabel relaional. Exist tabele care nu pot fi
descompuse n dou tabele, dar pot fi descompuse n trei sau mai multe tabele fr pierdere de
informaie. Astfel de descompuneri, n trei sau mai multe tabele, sunt tratate de 5NF. Pentru a arta
c un tabel se poate descompune fr pierderi de informaie a fost introdus conceptul de joindependen sau dependen la compunere, definit n cele ce urmeaz.
Fie R un tabel relaional i R1, R2, ..., Rn o mulime de tabele relaionale care nu sunt disjuncte - au
coloane comune - astfel nct reuniunea coloanelor din R1, R2, ..., Rn este mulimea coloanelor din
R. Se spune c R satisface join-dependena *{R1, R2, ..., Rn} dac R se descompune prin proiecie
pe R1, R2, ..., Rn fr pierdere de informaie, adic tabelul iniial poate fi reconstruit prin
compunerea natural pe atribute comune ale tabelelor rezultate. n exemplul de mai sus, tabelul
LUCRTOR_ATELIER_PRODUS satisface dependena de uniune *{LUCRTOR_ATELIER,
LUCRTOR_PRODUS, ATELIER_PRODUS}.
Join-dependena este o generalizare a dependenei multivaloare. Mai precis, dependena multivaloare corespunde join-dependenei cu dou elemente. ntr-adevr, dac n relaia R(X, Y, Z) avem
multidependen X Y, atunci avem i join-dependen *{(X Y), (X Z)}. Invers, dac
avem join-dependen *{R1, R2}, atunci avem i dependen multivaloare (R1 R2) (R1 - (R1
R2)).
Definiie.
Un tabel relaional R este n a cincea form normal (5NF) dac i numai dac orice joindependen *{R1, R2, ..., Rn} este consecina cheilor candidate ale lui R, adic fiecare dintre R1,
R2, ..., Rn include o cheie candidat a lui R.

66

Orice tabel relaional care este n 5NF este n 4NF deoarece, aa cum am artat mai sus, orice
dependen multivaloare poate fi privit ca un caz particular de dependen la uniune. Trecerea de la
4NF la 5NF const n identificarea join-dependenelor cu mai mult de trei elemente i
descompunerea tabelului iniial prin proiecie pe aceste componente. Dup cum am mai spus, 5NF
are o importan practic redus, cazurile cnd apare n practic fiind extrem de rare.
Orice tabel relaional poate fi descompus fr pierderi de informaie ntr-o mulime de tabele
relaionale care sunt n 5NF. Se garanteaz faptul c un tabel n 5NF nu conine anomalii ce pot fi
eliminate lund proieciile pe diferite submulimi de coloane ale acestuia.
Concluzii
Normalizarea este procesul de transformare a structurilor de date i are ca scop eliminarea
redundanelor i promovarea integritii datelor. Normalizarea este un pilon de baz al bazelor de
date relaionale. n general, un set de structuri de date nu sunt considerate relaionale dect dac
sunt complet normalizate.
Normalizarea datelor este mprit n ase etape, numite forme normale. Fiecare form normal are
asociat att un criteriu ct i un proces. Criteriul unei anumite forme normale este mai restrictiv
dect al formei normale inferioare, astfel nct orice tabel relaional care este ntr-o anumit form
normal este i n form normal inferioar. Procesul asociat unei forme normale se refer la
trecerea unor structuri de date din forma normal inferioar n forma normal curent. Etapele
normalizrii sunt rezumate pe scurt n continuare.

1NF 2NF elimin dependenele funcionale pariale fa de chei.


2NF 3NF elimin dependenele funcionale tranzitive fa de chei.
3NF BCNF elimin dependenele funcionale pentru care determinantul nu este cheie.
BCNF 4NF elimin toate dependenele multivaloare care nu sunt i dependene funcionale.
4NF 5NF elimin toate join-dependenele care nu sunt implicate de o cheie.

n practic, cel mai adesea apar primele forme normale (1NF - 3NF), astfel nct un tabel relaional
aflat n 3NF este de obicei complet normalizat. n special 5NF apare extrem de rar, avnd valoare
practic foarte sczut.
2.3.7. Denormalizare
n principiu, denormalizarea este exact procesul invers normalizrii. Denormalizarea este procesul
de cretere a redundanei datelor, care are ca scop creterea performanei sau simplificarea
programelor de manipulare a datelor. Totui, trebuie reinut c o denormalizare corect nu nseamn
nicidecum a nu normaliza structurile de date iniiale. Din contr, denormalizarea are loc dup ce
structurile bazei de date au fost complet normalizate, i se face prin selectarea strategic a acelor
structuri unde denormalizarea aduce avantaje semnificative. Pe de alt parte, orice denormalizare
trebuie nsoit de introducerea de msuri suplimentare, care s asigure integritatea datelor chiar i
n cazul unei baze de date care nu este complet nenormalizat.
Creterea performanei
Principalul obiectiv al denormalizrii este creterea performanei programelor de manipulare a
datelor. Una dintre cele mai ntlnite situaii de acest gen este denormalizarea folosit pentru
operaii sau calcule efectuate frecvent. Ilustrm aceast situaie cu exemplul urmtor. S
presupunem c pentru nregistrarea tranzaciilor unui magazin care vinde articole la comand se
folosesc tabelele
67

VNZRI_2 (cod_comand, cod_articol, cantitate),


ARTICOL (cod_articol, nume_articol, cost_articol),
COMANDA_3 (cod_comand, data, cod_client),
CLIENT (cod_client, nume_client, nr_telefon)
descrise mai sus, vezi figurile 2.29, 2.30 i 2.31. Aceste tabele sunt n 5NF i conin toate datele
necesare pentru obinerea oricrui raport privind vnzrile din magazin - de exemplu, n funcie de
articol, dat, cantitate, client, etc.. Totui, s presupunem c majoritatea rapoartelor cerute de
conducerea magazinului utilizeaz cantitatea total vndut ntr-o lun pentru fiecare articol.
Tabelele de mai sus conin toate datele necesare pentru obinerea acestei informaii, de exemplu ea
se poate obine printr-o simpl interogare SQL. Pe de alt parte ns, aceasta ar nsemna ca totalul
pentru fiecare articol s fie recalculat de fiecare dat cnd este cerut. Deoarece este puin probabil
ca acest total s se schimbe dup ncheierea lunii respective, repetarea acestora ar putea fi nlocuit
cu un tabel suplimentar
ARTICOL_LUNA (cod_articol, luna, cantitate_total)
Datele coninute n acest nou tabel sunt redundante, ele putnd fi obinute n orice moment din
datele coninute n tabelele VNZRI_2 i COMANDA_3, dar prezint avantajul c folosirea lor
este mai facil i mai rapid dect repetarea calculelor. Pe de alt parte ns, folosirea acestui tabel
suplimentar are i dezavantaje, putnd duce la pierderea integritii datelor. Modificarea datelor din
tabelele VNZRI_2 i COMANDA_3 nu se reflect automat n datele din noul tabel. De
exemplu, dac dup efectuarea calculelor i inserarea totalului n noul tabel se efectueaz o vnzare
suplimentar, aceast vnzare nu este reflectat n datele din noul tabel. De aceea, n situaiile n
care baza de date nu este total normalizat, trebuie luate msuri suplimentare pentru pstrarea
integritii datelor. De exemplu, pentru ca orice modificare a tabelelor iniiale s fie reflectat
automat n noul tabel, n Oracle se pot crea aa numitele triggere (declanatoare) ale bazei de date
bazate pe tabelele VNZRI_2 i COMANDA_3 care se declaneaz dup fiecare actualizare
(INSERT, UPDATE, DELETE) a acestor tabele i care actualizeaz datele din tabelul
ARTICOL_LUNA. Aceste triggere pe baz, la rndul lor, vor ncetini operaiile de actualizare din
tabelele pe care sunt bazate.
Datorit problemelor legate de redundan i integritate, orice denormalizare trebuie s fie gndit
cu atenie pentru a fi siguri c avantajele acesteia n privina performanelor i a simplitii
programelor depesc efortul necesar pentru impunerea integritii. n exemplul de mai sus, se pot
crea tabele suplimentare pentru totaluri pe lun sau pe zi. Dac aceste totaluri sunt utilizate rar, este
mai convenabil ca ele s fie calculate direct din tabele normalizate, fr a mai introduce alte date
redundante. n concluzie, fiecare caz trebuie studiat cu atenie pentru a vedea dac problemele
inerente asociate denormalizrii (redundana, meninerea integritii) sunt compensate de creterea
n performan pentru anumite situaii.
Simplificarea codului
Un alt motiv invocat pentru folosirea denormalizrii este acela al simplificrii codului pentru
manipularea datelor. Cu alte cuvinte, pentru un dezvoltator, un singur tabel poate prea uneori mai
uor de utilizat dect dou sau mai multe. De exemplu, s considerm tabelul
STOCURI(cod_depozit, cod_material, nume_material, cantitate)
utilizat de o firm pentru a nregistra cantitile de materiale existente n fiecare din depozitele sale.
Evident, acest tabel nu este n 2NF i poate fi normalizat prin descompunerea n dou tabele:
STOCURI_2(cod_depozit, cod_material, cantitate)
MATERIAL(cod_material, nume_material)
Totui, dac se dorete aflarea tuturor depozitelor n care exist ciment, de exemplu, pentru
dezvoltator este mai convenabil s foloseasc varianta nenormalizat, n acest caz interogarea SQL
corespunztoare fiind
68

SELECT cod_depozit, cantitate


FROM stocuri
WHERE nume_material = CIMENT
Evident, interogarea de mai sus este mai simpl dect varianta n care se folosesc cele dou tabele
normalizate
SELECT cod_depozit, cantitate
FROM stocuri_2, material
WHERE stocuri_2.cod_material = material.cod_material
AND nume_material = CIMENT
Pe de alt parte ns, diferena de performan (timp de execuie) dintre cele dou variante de
interogri este neglijabil, de multe ori chiar interogarea pe structuri normalizate va fi mai rapid
dect cealalt, astfel nct singurul avantaj al folosirii structurii nenormalizate este simplitatea.
Dac pentru un dezvoltator simplificarea invocat mai sus este nesemnificativ - orice dezvoltator
trebuie s fie capabil s scrie o interogare pe mai multe tabele de tipul celei de mai sus - problema
se pune cu mai mare stringen n cazul n care utilizatorii pot s-i scrie propriile interogri ale
bazei de date. n acest caz, pentru a pstra att avantajele normalizrii i pentru a permite n acelai
timp simplificarea interogrilor, se poate crea o vedere bazat pe cele dou tabele normalizate
CREATE VIEW stocuri AS
SELECT cod_depozit, stocuri_2.cod_material, nume_material, cantitate
FROM stocuri_2, material
WHERE stocuri_2. cod_material = material.cod_material
O astfel de vedere ascunde tabelele normalizate i permite utilizatorilor scrierea unor interogri
mai simple. Pe de alt parte ns, performana programelor poate scdea mult n cazul vederilor
complexe, n acest caz fiind uneori de preferat a se utiliza tabelele de baz pentru creterea
performanei.
Concluzii
Designul logic al bazei de date are un impact profund asupra performanelor i structurii sistemului.
Dei este posibil a compensa un design prost prin scrierea unui volum mare de cod, acest lucru nu
este n nici un caz de dorit, mai ales c n majoritatea cazurilor el va duce inevitabil la scderea
performanelor sistemului. n mod ideal, dezvoltarea oricrei aplicaii trebuie s nceap de la o
structur complet normalizat, care s constituie o temelie solid a acesteia. Denormalizarea, dac
ea este necesar, trebuie fcut numai dup ce se obine o structur complet normalizat. Ca regul
general, denormalizarea este folosit rar i numai dup o analiz atent.

69

Capitolul 5 : Securitatea bazei de date.


Baza de date Oracle conine propriul ei sistem de securitate care previne accesul neautorizat la baza
de date. Sistemul de securitate al bazei de date Oracle este realizat prin intermediul utilizatorilor
bazei de date. Serverul bazei de date solicit numele utilizatorului i parola pentru fiecare accesare
la baza de date; indiferent de utilitarul folosit pentru interfa, serverul bazei de date nu permite
accesul la baza de date dac nu este utilizat un nume i o parol corect.
Not: Aa cum am mai menionat, n contextul bazei de date Oracle, un utilizator nseamn de fapt
un cont de utilizator i nu o persoan care acceseaz baza de date. Evident, o persoan poate accesa
baza de date folosind unul sau mai muli utilizatori Oracle, iar mai multe persoane pot accesa baza
de date folosind acelai utilizator Oracle (acesta este cazul de obicei n practic)
O schem este o colecie de obiecte disponibile unui utilizator. Obiectele schemei sunt structuri
logice ce se refer efectiv la datele unei baze de date precum tabele, vederi, secvene, indeci,
sinonime, etc.
Fiecrui utilizator al bazei de date i sunt acordate anumite drepturi, cunoscute sub numele de
privilegii. Un privilegiu este permisiunea de a executa o aciune sau de a accesa un obiect
aparinnd unui alt utilizator. n Oracle, un utilizator nu poate executa nici un fel de aciune fr a
avea privilegiul s o fac. n acest sens unui utilizator i pot fi acordate sau revocate privilegii.
Accesul unui utilizator la baza de date este administrat printr-un numr de drepturi numite privilegii
de sistem, sau privilegii la nivelul bazei de date, care permit utilizatorului s efectueze operaii
precum conectarea la baza de date i crearea de obiecte. Odat ce utilizatorul a creat obiecte ale
bazei de date, el este apoi responsabil de a acorda drepturi altor utilizatori pentru obiectele care sunt
proprietatea lui. Aceste drepturi sunt numite privilegii la nivel de obiect.
Rolurile sunt utilizate pentru a simplifica administrarea privilegiilor. Astfel, n loc de a acorda un
anumit privilegiu direct unui utilizator, privilegiile sunt acordate unui rol, iar un rol este acordat la
rndul lui unui utilizator. Cu alte cuvinte, rolurile reprezint un grup de privilegii.
Acest capitol prezint modul n care se realizeaz securitatea unei baze de date Oracle, referindu-se
la fiecare dintre conceptele menionate mai sus.
5.1 Privilegii de sistem
Aciunile pe care un utilizator le poate efectua asupra bazei de date sunt administrate prin
privilegiile de sistem acordate acestuia. n Oracle exist peste 80 de privilegii de sistem, denumirea
lor fiind inspirat de aciunile pe care le permit. Ele variaz de la permisiunea de a se conecta la o
baza de date (CREATE SESSION) la dreptul de a crea un tabel (CREATE ANY TABLE) sau index
(CREATE ANY INDEX) sau de a distruge un tabel (DROP ANY TABLE) sau index (DROP ANY
INDEX) din schema oricrui utilizator. O list a tuturor privilegiilor de sistem este prezentat n
Anexa 4A.
5.2 Privilegii la nivel de obiect
Securitatea obiectelor unei baze de date este administrat ca un numr de privilegii la nivel de
obiect, care determin ce acces au utilizatorii la obiectele bazei de date. Privilegiile la nivel de
obiect existente n Oracle sunt rezumate n tabelul din figura 5.1. Tabelul din figura 5.2 indic
obiectele asupra crora poate fi acordat fiecare privilegiu n parte.

94

Fiecare privilegiu la nivel de obiect este permis independent de celelalte, adic un privilegiu de
obiect este acordat numai pentru un obiect.
Privilegiul de
obiect
SELECT
INSERT
UPDATE
DELETE
ALTER
REFERENCES
EXECUTE

INDEX
READ

Descrierea permisiunii
Selectarea rndurilor dintr-un tabel, vedere sau instantaneu i
extragerea numerelor dintr-un generator de secvene
Inserarea nregistrrilor ntr-un tabel sau vedere
Actualizarea nregistrrilor dintr-un tabel sau vedere
tergerea nregistrrilor dintr-un tabel sau vedere
Modificarea structurii i parametrilor unui tabel sau a unei secvene
Referirea unui tabel utiliznd chei strine
Executarea unei proceduri funcii, pachet sau proceduri externe i
accesarea obiectelor declarate n specificaia pachetului: n plus,
pentru opiunea obiect din Oracle8 (vezi capitolul 10), acest
privilegiu se poate acorda i asupra unui tip de date creat de
utilizator, n acest caz acest tip de date putnd fi folosit la crearea
unor tabele, la definirea unor coloane din tabele i la declararea
unor variabile sau parametrii
Crearea indecilor tabelului
Citirea unui BFILE din directorul specificat (vezi Anexa 3)
Figura 5.1.

Privilegiul de Tabel
obiect
SELECT
INSERT
UPDATE
DELETE
ALTER
REFERENCES
EXECUTE
INDEX
READ

X
X
X
X
X
X

Vedere
X
X
X
X

Secven

Procedur
funcie
pachet

Instantaneu

Director

Bibliotec

X
X

X
X
Figura 5.2.

Fiecare obiect al bazei de date este proprietatea unui utilizator al bazei de date - se spune c obiectul
face parte din schema respectivului utilizator. Proprietarul unui obiect are control deplin asupra
acestuia. El poate efectua orice aciune asupra unui obiect deinut fr s aib privilegii la nivel de
obiect deoarece aceste privilegii sunt implicite. n plus, proprietarul unui obiect poate acorda
privilegii asupra obiectului respectiv i altor utilizatori.
Prin urmare, pentru a efectua o aciune asupra unui obiect (interogare, actualizare, distrugere, etc.),
un utilizator trebuie s se gseasc n unul din urmtoarele cazuri:
- s fie proprietarul acelui obiect;
- s aib acordat privilegiul la nivelul obiectului respectiv de efectua acea aciune ;
- s aib acordat privilegiul de sistem care s i permit acest lucru.

95

De exemplu, pentru a putea interoga (SELECT) un tabel, un utilizator trebuie s fie proprietarul
acelui tabel, s posede privilegiul SELECT pe acel tabel sau s posede privilegiul de sistem
SELECT ANY TABLE. Privilegiile necesare pentru efectuarea diverselor aciuni asupra obiectelor
bazei de date sunt sintetizate pe categorii de obiecte n Anexa 4B.
5.3 Roluri
Pentru a simplifica modul de administrare, privilegiile pot fi grupate n roluri (roles). Un grup de
privilegii pot fi acordate unui rol, iar un rol poate fi acordat la rndul lui unui utilizator, acordnduse astfel utilizatorului n mod implicit privilegiile asociate cu acel rol. De asemenea, este posibil
acordarea unui rol altui rol, putndu-se crea astfel ierarhii de roluri. n plus, unui rol i poate fi
revocat un privilegiu dup cum i unui utilizator i poate fi revocat un rol. n general, rolurile se
folosesc atunci cnd exist utilizatori care au nevoie de acelai seturi de privilegii.
Rolurile permit simplificarea gestionarii privilegiilor: n loc de a acorda mai multe privilegii unui
utilizator, acestuia i poate fi acordat rolul care conine aceste privilegii. Pe lng simplificarea
modului de administrare a privilegiilor, rolurile au avantajul de a putea fi administrate dinamic:
atunci cnd privilegiile unui rol se modific, aceste modificri se reflect automat n privilegiile
acordate utilizatorilor care dein rolul respectiv. n plus, un rol poate fi activat sau dezactivat n
cadrul aceleiai sesiuni, aceasta avnd ca efect acordarea sau retragerea privilegiilor respective
utilizatorului. De asemenea un rol poate fi protejat cu o parol care va trebui introdus n momentul
n care se dorete activarea acestuia.
Oracle ofer un set de roluri predefinite cu privilegii incluse care sunt create odat cu baza de date
(vezi Anexa 4C). Acestea sunt urmtoarele:
CONNECT ofer privilegiile de baz pentru utilizatorul unei aplicaii.
RESOURCE ofer privilegiile de baz pentru programatorul unei aplicaii.
DBA ofer toate privilegiile de sistem cu posibilitatea de a acorda aceste privilegii altor utilizatori
sau roluri (cu alte cuvinte are opiunea WITH ADMIN OPTION, vezi seciunea 5.8).
EXP_FULL_DATABASE i IMP_FULL_DATABASE sunt pentru utilizatorii utilitarelor Export
i Import (vezi Anexa 1), adic ofer privilegiile necesare operaiilor de export i respectiv
import ale bazei de date.
DELETE_CATALOG_ROLE, EXECUTE_CATALOG_ROLE i SELECT_CATALOG_ROLE
ofer privilegiile de accesare a vederilor dicionarului de date i a pachetelor.
Alte
roluri:
AQ_ADMINISTRATION_ROLE,
AQ_USER_ROLE,
RECOVERY_CATALOG_OWNER i SNMPAGENT.
5.4 Utilizatorii bazei de date
Odat cu crearea unei baze de date sunt creai i doi utilizatori ai bazei de date: SYS i SYSTEM.
Utilizatorul SYS este proprietarul tuturor tabelelor interne ale bazei de date, pachetelor i
procedurilor predefinite etc. El este de asemeni proprietarul vederilor i tabelelor dicionarului de
date i are atribuite toate rolurile predefinite - printre care i cel de DBA. SYS constituie temelia
bazei de date Oracle. Din acest motiv, trebuie evitat pe ct posibil folosirea acestui utilizator; o
simpl comand greit fcut de cineva conectat la baza de date ca SYS poate avea efect
devastator.

96

Utilizatorul SYS este singurul care poate avea acces la anumite tabele ale dicionarului de date.
Datorit faptului c acesta este proprietarul tuturor structurilor dicionarului de date, pentru a acorda
privilegii asupra obiectelor dicionarului de date este necesar conectarea ca SYS. Parola iniial
pentru utilizatorul SYS este CHANGE_ON_INSTALL, dar, datorit importanei acestui utilizator,
este recomandat schimbarea acesteia imediat dup instalare.
Utilizatorul SYSTEM este de asemenea creat odat cu crearea bazei de date i, n mod normal, este
utilizat iniial pentru crearea altor utilizatori i pentru administrarea bazei de date. Ca i SYS, i
SYSTEM are drepturi depline asupra tuturor obiectelor bazei de date, avnd acordat rolul de DBA i,
de aceea, de multe ori contul SYSTEM se utilizeaz pentru a administra baza de date. Totui, este
preferabil ca pentru administrarea bazei de date s se creeze un utilizator separat cu privilegiile de
DBA. Parola iniial pentru utilizatorul SYSTEM este MANAGER i se recomand schimbarea ei
imediat dup crearea bazei de date.
Utilizatorii SYS i SYSTEM nu trebuie n nici un caz folosii pentru a crea sau interoga obiecte
specifice aplicaiilor sau pentru a interaciona direct cu aplicaiile.
Pentru baza de date exemplu, se creeaz automat mai muli utilizatori prezentai n tabelul de mai
jos:
Nume cont
Parola
utilizator
INTERNAL ORACLE (dac baza de date a
fost instalat folosind opiunea
Custom, parola se specific n
timpul instalrii)
SYS

CHANGE_ON_INSTALL

SYSTEM

MANAGER

SCOTT

TIGER

DEMO

DEMO

Descriere
Numele administratorului bazei de date cu care se
realizeaz anumite operaii precum pornirea i oprirea
bazei de date. INTERNAL nu este cu adevrat un
utilizator, el este de fapt un alias al utilizatorului SYS
cu privilegiul suplimentar SYSDBA.
Numele administratorului bazei de date ce are
urmtoarele roluri:
CONNECT
RESOURCE
DBA
EXP_FULL_DATABASE
IMP_FULL_DATABASE
DELETE_CATALOG_ROLE
EXECUTE_CATALOG_ROLE
SELECT_CATALOG_ROLE
AQ_ADMINISTRATION_ROLE
AQ_USER_ROLE
RECOVERY_CATALOG_OWNER
SNMPAGENT
Numele utilizatorului bazei de date ce deine numai
rolul DBA.
Numele utilizatorului bazei de date ce deine rolurile
CONNECT i RESOURCE.
Numele utilizatorului bazei de date ce deine rolurile
CONNECT i RESOURCE. Este recomandat
tergerea acestui cont n cazul n care nu este folosit.

97

DBSNMP

DBSNMP

Numele utilizatorului bazei de date ce deine rolurile


CONNECT, RESOURCE i SNMPAGENT.
Figura 5.3

5.5 Schema
Schema reprezint o colecie de obiecte care sunt proprietatea unui utilizator. Un utilizator poate
avea o singur schem, care va avea acelai nume cu acesta. O schem este creat pentru a
administra o aplicaie, avnd drepturi depline asupra tuturor obiectelor aplicaiei. Acest lucru are
anumite avantaje dintr-o serie de motive: separ n general administrarea obiectelor bazei de date de
administrarea obiectelor aplicaiei i permite ca toate datele aplicaiei s poat fi exportate sau
mutate de ctre proprietarul acestora.
ntre spaiile tabel i schema unei baze de date nu exist nici o legtur; obiectele unei scheme se
pot gsi n spaii tabel diferite, dup cum i ntr-un spaiu tabel se pot gsi obiecte din mai multe
scheme.
Pentru a accesa un obiect din propria schema, un utilizator poate folosi doar numele acestuia. Pentru
a accesa un obiect din schema altui utilizator, trebuie specificat att numele obiectului ct i schema
din care face parte, folosind sintaxa:
schema.obiect
De exemplu, un utilizator, s-l numim costel, va putea crea n schema proprie un tabel numit
persoana, folosind comanda:
CREATE TABLE persoana...;
Dac ns un alt utilizator dorete crearea tabelului persoana n schema utilizatorului costel,
va trebui s foloseasc comanda:
CREATE TABLE costel.persoana ...;
Pentru interogarea tabelului, utilizatorul costel va folosi comanda:
SELECT * FROM persoana;
n schimb, pentru a interoga tabelul, orice alt utilizator va folosi comanda:
SELECT * FROM costel.persoana;
n plus, pentru a accesa un obiect din schema altui utilizator, un utilizator va trebui s posede
privilegiile necesare respectivului tip de acces. De exemplu, pentru interogarea tabelului
persoana, orice alt utilizator va trebui s posede privilegiul SELECT pe tabelul persoana sau
privilegiul de sistem SELECT ANY TABLE.
n general, trebuie s existe mcar trei tipuri de acces la o aplicaie: administratorul bazei de date,
dezvoltatorul i utilizatorul:
Administratorul bazei de date va trebui s administreze structurile i obiectele bazei de date
(cum ar fi fiierele, spaiile tabel i tabelele). Administratorul bazei de date este de fapt
proprietarul aplicaiei i al bazei de date. El trebuie s dein o varietate de privilegii de sistem.

98

Dezvoltatorul va trebui s poat efectua att operaii de interogare, ct i de manipulare (DML)


i definire (DDL) a datelor. Pentru aplicaiile de dimensiuni reduse, proprietarul aplicaiei este de
obicei utilizat i pentru dezvoltare. n general ns, pentru dezvoltare se folosete o alt schem
dect cea care deine obiectele aplicaiei, deci un dezvoltator trebuie s dein n principal
privilegii la nivel de obiect.
Utilizatorul, pe de alt parte, va putea efectua doar operaii de interogare i manipulare a datelor,
fr a avea ns permisiunea de a efectua operaii de definire a datelor.
Schema care deine obiectele aplicaiei va acorda privilegiile necesare fiecrui tip de acces la
aplicaie.
5.6 Crearea, modificarea i distrugerea utilizatorilor
Utilizatorii bazei de date pot fi creai folosind comanda SQL CREATE USER, avnd sintaxa
urmtoare:
CREATE USER nume_utilizator
IDENTIFIED {BY parola | EXTERNALLY}
[DEFAULT TABLESPACE nume_spaiu_tabel]
[TEMPORARY TABLESPACE nume_spaiu_tabel]
[QUOTA {ntreg [K|M]|UNLIMITED} nume_spaiu_tabel ]...
[PROFILE nume_profil ]
[PASSWORD EXPIRE]
[ACCOUNT {LOCK|UNLOCK}]
unde

IDENTIFIED indic modul n care Oracle permite accesul utilizatorului: prin parol, cnd
Oracle menine n mod intern o parol pentru utilizator, pe care acesta o va utiliza pentru
accesarea bazei de date; EXTERNALLY, cnd verificarea accesului utilizatorului este fcut de
ctre sistemul de operare - n acest caz utilizatorul trebuie s fie identic cu cel definit n sistemul
de operare.
DEFAULT TABLESPACE indic spaiul tabel folosit n mod implicit de obiectele create de
ctre utilizator. Dac aceast clauz este omis, spaiul tabel implicit este SYSTEM.
TEMPORARY TABLESPACE indic spaiul tabel pentru segmentele temporare ale
utilizatorului. Dac aceast clauz este omis, spaiul tabel implicit pentru segmentele
temporare este SYSTEM.
QUOTA permite utilizatorului s aloce spaiu pe un spaiu tabel; la folosirea acestei clauze poate
fi specificat spaiul maxim alocat (n bytes, Kbytes (K) sau Mbytes (M)) sau poate fi folosit
opiunea UNLIMITED pentru a permite utilizatorului s aloce orict de mult spaiu pe spaiul
tabel.
PROFILE atribuie utilizatorului un profil. Un profil este un set de limitri pentru resursele bazei
de date (de exemplu, numrul maxim de sesiuni concurente, timpul maxim al unei sesiuni, etc.).
Dac profilul este atribuit unui utilizator, atunci utilizatorul nu poate depi limitele specificate
de profil. Un profil poate fi creat folosind comanda SQL CREATE PROFILE. Dac aceast
clauz este omis, Oracle atribuie n mod implicit utilizatorului profilul DEFAULT.
PASSWORD EXPIRE foreaz ca parola iniial s fie schimbat de ctre utilizator n
momentul n care acesta se va conecta pentru prima dat la baza de date.

99

ACCOUNT LOCK|UNLOCK blocheaz sau deblocheaz contul permind sau nu accesul


utilizatorului la baza de date. Dac se folosete opiunea de blocare (LOCK), contul utilizatorului
este creat ns utilizatorul nu se va putea conecta pn cnd nu se deblocheaz n mod explicit
contul. Aceast opiune se folosete, de exemplu, n cazul n care se prefer crearea unui cont
pentru un angajat nou dar nu i se permite accesul pn cnd nu este pregtit s-l foloseasc.
Opiunea implicit este UNLOCK.

Pentru a putea crea un alt utilizator, trebuie ca utilizatorul ce realizeaz acest lucru s dein
privilegiul de sistem CREATE USER.
Exemplul urmtor creeaz utilizatorul costel cu parola costica, avnd ca spaiu tabel implicit
ts_alfa, spaiu tabel temporar ts_temp i cot de spaiu nelimitat pe spatiile tabel ts_alfa,
ts_beta i ts_temp.
CREATE USER costel
IDENTIFIED BY costica
DEFAULT TABLESPACE ts_alfa
TEMPORARY TABLESPACE ts_temp
QUOTA UNLIMITED ON ts_alfa
QUOTA UNLIMITED ON ts_beta
QUOTA UNLIMITED ON ts_temp;
Caracteristicile unui utilizator pot fi schimbate folosind comanda SQL ALTER USER. Folosind
aceast comand se poate schimba, de exemplu, parola unui utilizator:
ALTER USER costel
IDENTIFIED BY costi;
Distrugerea unui utilizator se poate face folosind comanda SQL DROP USER. Dac exist obiecte
n schema utilizatorului, atunci acestea trebuie distruse nainte de distrugerea utilizatorului. Aceasta
pe poate face automat folosind opiunea CASCADE a acestei comenzi:
DROP USER costel CASCADE;
5.7 Crearea, modificarea i tergerea rolurilor
Un rol poate fi creat folosind comanda SQL CREATE ROLE, avnd sintaxa urmtoare:
CREATE ROLE rol
[ NOT IDENTIFIED | IDENTIFIED {BY parola | EXTERNALLY}]
unde
NOT IDENTIFIED arat c orice utilizator cruia i va fi acordat rolul creat nu va trebui
identificat n momentul cnd activeaz rolul (comanda SET ROLE, vezi seciunea 5.10)
IDENTIFIED arat c orice utilizator cruia i va fi acordat rolul creat va trebui verificat.
Aceast verificare poate fi fcut intern de ctre Oracle prin parol sau extern de ctre sistemul
de operare (EXTERNALLY). n acest ultim caz, n funcie de sistemul de operare, utilizatorul va
trebui s specifice o parol sistemului de operare la activarea rolului.

100

Dac ambele opiuni NOT IDENTIFIED i IDENTIFIED sunt omise, opiunea implicit este
NOT IDENTIFIED.
CREATE ROLE rol_costel;
CREATE ROLE tanta IDENTIFIED BY tantica;
Un utilizator poate crea un rol numai dac deine privilegiul de sistem CREATE ROLE.
Schimbarea modului de identificare a unui rol poate fi fcut folosind comanda SQL ALTER
ROLE:
ALTER ROLE tanta NOT IDENTIFIED;
Distrugerea unui rol se poate face folosind comanda SQL DROP ROLE:
DROP ROLE tanta;
5.8 Acordarea rolurilor i privilegiilor
Privilegiile de sistem, privilegiile la nivel de obiect sau rolurile pot fi acordate unui utilizator sau
unui rol folosind comanda SQL GRANT. Totui, sintaxa comenzii GRANT pentru acordarea de
privilegii de sistem sau roluri difer de sintaxa pentru acordarea de privilegii la nivel de obiect.
Bineneles, pentru a putea acorda un privilegiu sau un rol, utilizatorul respectiv trebuie s aib
acest drept. De exemplu, pentru a acorda un privilegiu de sistem sau un rol, utilizatorul trebuie fie
s aib privilegiul sau rolul respectiv acordat cu opiunea ADMIN OPTION sau s aib privilegiul
GRANT ANY PRIVILEGE, respectiv GRANT ANY ROLE.
Acordarea unui privilegiu de sistem sau a unui rol
Pentru acordarea de privilegii de sistem sau roluri sintaxa comenzii GRANT este urmtoarea:
GRANT {privilegiu_de_sistem| rol} [,{privilegiu_de_sistem | rol}]...
TO {utilizator |rol|PUBLIC} [,{utilizator|rol|PUBLIC}]...
[WITH ADMIN OPTION]
unde
PUBLIC este folosit pentru a acorda privilegiile de sistem sau rolurile specificate tuturor
rolurilor i utilizatorilor existeni.
WITH ADMIN OPTION permite utilizatorului (rolului) cruia i este acordat rolul (privilegiul)
s acorde la rndul lui rolul (privilegiul) altui utilizator (rol). De asemenea, dac unui utilizator
sau rol i este acordat un rol folosind WITH ADMIN OPTION, atunci utilizatorul sau rolul
respectiv poate modifica (ALTER ROLE) sau distruge (DROP ROLE) rolul acordat.
Un rol nu se poate acorda lui nsui n mod direct sau printr-un set circular de atribuiri. Dac se
ncearc acest lucru, Oracle va genera un mesaj de eroare.
n continuare vom prezenta cteva exemple de acordare a privilegiilor de sistem sau a rolurilor.

101

Acordarea privilegiilor de sistem CREATE


rol_costel:

CLUSTER

i CREATE

TABLE

pentru rolul

GRANT CREATE CLUSTER, CREATE TABLE


TO rol_costel;
Acordarea privilegiului de sistem CREATE SESSION pentru utilizatorul costel, permind
acestuia conectarea la baza de date:
GRANT CREATE SESSION
TO costel;
Acordarea rolului rol_costel pentru utilizatorul costel:
GRANT rol_costel
TO costel;
Acordarea unui privilegiu la nivel de obiect
Pentru acordarea de privilegii la nivel de obiect sintaxa comenzii GRANT este uor diferit deoarece
este nevoie s se identifice un obiect specific:
GRANT {privilegiu_de_obiect | ALL} [(coloana [,coloana]...)]
[,{privilegiu_de_obiect | ALL} [(coloana [,coloana]...)]]...
ON obiect
TO {utilizator | rol | PUBLIC}[,{utilizator| rol |PUBLIC}]...
[WITH GRANT OPTION]
unde:
ALL este folosit pentru a acorda toate privilegiile pentru obiectul respectiv
coloana reprezint coloana pentru care este acordat privilegiul. Coloanele pot fi specificate
numai cnd sunt acordate privilegiile INSERT, REFERENCES, UPDATE. Dac nu este listat
nici o coloan, atunci privilegiul se acord pe toate coloanele tabelei sau vederii n cauz.
WITH GRANT OPTION permite celui care i sunt acordate privilegiile de a le acorda la rndul lui
altui utilizator sau rol.
Pentru o mai bun nelegere a acestei comenzi, vom prezenta n continuare cteva exemple:
Acordarea privilegiului SELECT (dreptul de interogare) asupra tabelului studenti pentru
utilizatorul costel i rolul rol_costel:
GRANT SELECT ON studenti
TO costel, rol_costel
WITH GRANT OPTION;
Acordarea privilegiului UPDATE (dreptul de actualizare) asupra coloanelor nume i prenume ale
tabelului studenti pentru utilizatorul costel:
GRANT UPDATE(nume, prenume) ON studenti
TO costel;
102

Acordarea privilegiului INSERT (dreptul de inserare a nregistrrilor) i a privilegiului DELETE


(dreptul de tergere al nregistrrilor) asupra tabelului studenti pentru utilizatorul costel:
GRANT INSERT, DELETE ON studenti
TO costel;
Acordarea tuturor privilegiilor (SELECT, INSERT, UPDATE, DELETE,
ALTER,
REFERENCES, INDEX, vezi tabelul din figura 5.2) asupra tabelului studenti pentru
utilizatorul costel:
GRANT ALL ON studenti
TO costel.
Acordarea privilegiului SELECT (dreptul de interogare) asupra tabelului studenti pentru toi
utilizatorii i pentru toate rolurile existente:
GRANT SELECT ON studenti
TO PUBLIC;
Trebuie menionat c utilizatorul care este proprietarul schemei din care face parte obiectul are
automat toate privilegiile asupra obiectului cu opiunea WITH GRANT OPTION.
5.9 Revocarea rolurilor i privilegiilor
Pentru a revoca un privilegiu sau un rol unui rol sau unui utilizator se poate folosi comanda SQL
REVOKE. Comanda REVOKE trebuie folosit cu foarte mare atenie deoarece poate anula un
privilegiu propriu. Ca i n cazul comenzii GRANT, i comanda REVOKE are o sintax pentru
revocarea privilegiilor de sistem sau a rolurilor i alt sintax pentru revocarea privilegiilor la nivel
de obiect.
Revocarea unui privilegiu de sistem sau a unui rol
Pentru revocarea de privilegii de sistem sau roluri, sintaxa comenzii REVOKE este urmtoarea:
REVOKE {privilegiu_de_sistem | rol} [,{privilegiu_de_sistem | rol}]...
FROM {utilizator|rol|PUBLIC} [,{utilizator|rol|PUBLIC}]...
Dac se anuleaz un rol care conine alte roluri, ntregul set de privilegii asociat cu fiecare rol va fi
anulat. Dac oricare dintre rolurile i privilegiile coninute de rolul anulat a fost acordat i n mod
direct utilizatorului, atunci acesta va continua s aib privilegiile corespunztoare.
Vom prezenta n continuare cteva exemple.
Revocarea privilegiului CREATE CLUSTER pentru rolul rol_costel:
REVOKE CREATE CLUSTER
FROM rol_costel;
Revocarea rolului rol_costel pentru utilizatorul costel:

103

REVOKE rol_costel
FROM costel;
Revocarea unui privilegiu la nivel de obiect
Pentru a revoca un privilegiu la nivel de obiect, sintaxa comenzii REVOKE este urmtoarea:
REVOKE {privilegiu_de_obiect | ALL} [(coloana [, coloana]...)]
[,{privilegiu_de_obiect | ALL} [(coloana [,coloana]...)]]...
ON obiect
FROM {utilizator|rol|PUBLIC}, [{utilizator|rol|PUBLIC}]...
[CASCADE CONSTRAINTS]
[FORCE]
unde:

CASCADE CONSTRAINTS indic faptul c se va terge orice restricie de integritate


referenial definit asupra tabelului de ctre utilizatorul respectiv. Aceast opiune trebuie s
fie folosit dac privilegiul revocat este REFERENCES sau ALL PRIVILEGES i dac cel
cruia i se revoc privilegiul a definit o restricie de integritate referenial asupra tabelului.
FORCE foreaz revocarea privilegiul EXECUTE asupra unui tip de date definit de ctre
utilizator care are tabele dependente, aceste tabele devenind n acest caz invalide. n absena
aceste opiuni, dac exist tabele dependente, revocarea privilegiul EXECUTE asupra tipului de
date va eua.

Pentru a revoca toate privilegiile utilizatorului costel deinute pe tabelul persoana, se va folosi
urmtoarea comand:
REVOKE ALL ON persoana FROM costel;
Pentru a revoca numai privilegiul SELECT deinut de toi utilizatorii i rolurile existente pentru
tabelul persoana, se va folosi urmtoarea comand:
REVOKE SELECT ON persoana FROM PUBLIC;
5.10 Activarea i dezactivarea rolurilor unui utilizator
La conectarea unui utilizator, Oracle va activa toate rolurile implicite (default) ale utilizatorului.
Rolurile implicite ale utilizatorului sunt toate rolurile acordate acestuia, cu excepia situaiei n care
rolurile implicite se definesc folosind clauza DEFAULT ROLE a comenzii SQL ALTER USER.
Folosind comanda SQL ALTER USER cu clauza DEFAULT ROLE se pot identifica exact care din
rolurile acordate utilizatorului sunt active i care sunt inactive atunci cnd utilizatorul se conecteaz
la baza de date. Orice modificare a listei de roluri implicite va avea efect ncepnd cu urmtoarea
conectare a utilizatorului la baza de date.
n cadrul unei sesiuni, rolurile atribuite unui utilizator pot fi activate sau dezactivate folosind
comanda SQL SET ROLE, avnd sintaxa urmtoare:
SET ROLE {rol [IDENTIFIED BY parola] [, rol[IDENTIFIED BY parola]]...
| ALL[EXCEPT rol [,rol]...]
104

| NONE}
Aa cum se observ din sintaxa prezentat mai sus, exist trei opiuni alternative care au urmtoarea
semnificaie:
Lista rolurilor specific rolurile care sunt activate pentru seciunea curent. Toate rolurile care
nu sunt listate vor fi dezactivate pentru sesiunea curent (vezi primele dou exemple de mai
jos). n cazul cnd rolul are o parol, pentru activarea rolului este necesar specificarea acesteia.
ALL activeaz pentru sesiunea curent toate rolurile acordate utilizatorului, mai puin cele
enumerate n clauza EXCEPT, dac ea exist. Aceast opiune nu poate fi folosit pentru
activarea rolurilor cu parola.
NONE dezactiveaz toate rolurile pentru sesiunea curent
n continuare vom prezenta cteva exemple de folosire a acestei comenzi:
Activarea rolului rol_costel:
SET ROLE rol_costel;
Activarea rolului tanta identificat prin parola tantica:
SET ROLE tanta IDENTIFIED BY tantica;
Activarea tuturor rolurilor pentru sesiunea curent:
SET ROLE ALL;
Activarea tuturor rolurilor n afar de rolul tanta:
SET ROLE ALL EXCEPT tanta;
Dezactivarea tuturor rolurilor pentru sesiunea curent:
SET ROLL NONE;
Pentru a determina rolurile active din sesiunea curent se poate examina vederea
SESSION_ROLES din dicionarul de date (vezi Anexa 5). Numrul maxim de roluri care pot fi
active la un anumit moment este specificat de ctre parametrul de iniializare
MAX_ENABLED_ROLES.

105

Capitolul 6: Organizarea logic a bazei de date


Dezvoltatorul de aplicaii trebuie s fie profund contient de organizarea logic a bazei de date. La
nivel logic, baza de date este alctuit din scheme. O schem este o colecie de structuri logice de
date, numite i obiecte ale schemei. Dup cum am vzut n capitolul anterior, o schem este
proprietatea unui utilizator al bazei de date i are acelai nume cu acesta. De aceea se mai spune c
obiectele schemei sunt proprietatea utilizatorului respectiv.
Definiiile tuturor obiectelor schemei sunt pstrate n dicionarul bazei de date. Dup cum vom
vedea n continuare, unele dintre obiectele schemei (tabele, clustere, indeci) conin date, pentru
care este necesar un spaiu de stocare. Datele din fiecare astfel de obiect sunt stocate din punct de
vedere logic ntr-un spaiu tabel. Din punct de vedere fizic, aceste date sunt stocate ntr-unul sau
mai multe din fiierele de date asociate acelui spaiu tabel. n general, ntr-un spaiu tabel sunt
stocate mai multe obiecte. Dup cum am vzut n capitolul 4, la crearea tabelelor, clusterelor sau
indecilor se poate specifica spaiul tabel corespunztor i spaiul alocat obiectului creat (prin
intermediul parametrilor de stocare).
Obiectele schemei pot fi create i manipulate folosind comenzi SQL. Principalele obiecte ale
schemei sunt urmtoarele:
Tabele (tables)
vederi (views)
indeci (indexes)
clustere (clusters) i clustere hash (hash cluster)
secvene (sequences)
sinonime (synonyms)
proceduri i funcii stocate/rezidente (stored procedures and functions)
pachete stocate (stored packages)
declanatoare ale bazei de date (database triggers)
instantanee (snapshots)
legturi ale bazei de date (database link)
Acest capitol prezint pe larg fiecare dintre aceste obiecte. n plus, ultima seciune din capitol este
dedicat dicionarului bazei de date.
6.1. Tabele
Tabelul este principala structur logic de stocare a datelor. Dup cum am vzut n capitolul 1, un
tabel este o structur bidimensional format din coloane i rnduri. Coloanele mai sunt numite i
cmpuri, iar rndurile nregistrri. n general, fiecare tabel este stocat ntr-un spaiu tabel1. Dup
cum am vzut n seciunea 4.2.1, poriunea dintr-un spaiu tabel folosit pentru stocarea datelor unui
tabel se numete segment tabel. Cu alte cuvinte, segmentul tabel este omologul fizic al unui tabel.
n anumite situaii, pentru a mri eficiena operaiilor de scriere/citire a datelor, mai multe tabele pot
fi stocare mpreun, formnd clustere (grupuri de tabele). Despre acestea vom vorbi mai trziu, n
seciunea 6.4. O noutate adus de versiunea Oracle8 este posibilitatea de crea un tabel pe baza unui
index, reducnd astfel timpul de acces la date prin interogri care folosesc ca termen de comparaie
coloanele indexate. Despre acestea vom vorbi n seciunea 6.3.3, deocamdat referindu-ne doar la
tabele obinuite.
O noutate adus de Oracle8, despre care vom vorbi ceva mai trziu este posibilitatea de a
partiiona un tabel, fiecare parte putnd fi stocat ntr-un spaiu tabel diferit
1

106

6.1.1 Crearea tabelelor


Un tabel poate fi creat prin comanda SQL create table, n care trebuie specificat numele i
tipul de date pentru fiecare coloan a tabelului. De exemplu:
CREATE TABLE salariat(
cod_salariat
NUMBER(10),
nume
varchar2(10),
prenume
varchar2(10),
data_nastere
date,
salariu
number(10),
manager
number(10),
cod_dept number(10),
cod_tara
number(10));
O sintax simplificat a comenzii CREATE TABLE este prezentat n continuare:
CREATE TABLE nume_tabel
(nume_coloana tip_data [DEFAULT expresie]
[, nume_coloana tip_data [DEFAULT expresie] ... )
[PCTFREE ntreg] [PCTUSED ntreg]
[TABLESPACE spaiu_tabel]
[STORAGE parametrii_de_stocare]
unde:
DEFAULT desemneaz o valoare implicit pentru coloan, folosit n cazul n care la inserarea
unui rnd n tabel nu este specificat o valoare explicit pentru coloana n cauz.
TABLESPACE specific spaiul tabel n care va fi stocat tabelul. Dac acesta nu este menionat
explicit, se va folosi spaiul tabel implicit (default) al utilizatorului care este proprietarul schemei
din care face parte tabelul (vezi exemplul de mai sus).
Valorile parametrilor PCTFREE i PCTUSED determin gradul de utilizare a blocurilor din
extinderile segmentului tabel, vezi seciunea 4.4.
Clauza STORAGE este folosit pentru setarea parametrilor de stocare (INITIAL, NEXT,
PCTINCREASE, MINEXTENTS, MAXEXTENTS) prin intermediul crora se specific mrimea i
modul de alocare a extinderilor segmentului tabel, vezi seciunea 4.1.1.
CREATE TABLE salariat(
cod_salariat
NUMBER(10),
nume
varchar2(10),
prenume
varchar2(10),
data_nastere
date,
salariu
number(10),
manager
number(10),
cod_dept number(10),
cod_tara
number(10) DEFAULT 40)
PCTFREE 20 PCTUSED 70
TABLESPACE ts_alfa
STORAGE (INITIAL 100K NEXT 100K);
La crearea unui tabel este necesar specificarea tipului de dat pentru fiecare coloan a tabelului.
Urmtorul tabel arat tipurile de date scalare cel mai des folosite.

107

Tip de dat
VARCHAR2(n)
CHAR(n)

NUMBER(n, m)
NUMBER(n)
NUMBER
DATE

LONG
RAW(n)

LONG RAW

Descriere
iruri de caractere de lungime variabil avnd lungimea maxim n bytes.
Lungimea maxim n trebuie neaprat specificat. n versiunea Oracle 8,
valoarea maxim a lungimii n de 4000.
iruri de caractere de lungime fix n bytes. Valoarea implicita pentru n este 1.
Dac ntr-o coloan avnd acest tip se insereaz iruri de caractere mai scurte
dect lungimea specificat, atunci Oracle insereaz la dreapta numrul necesar
de spaii libere (blank-uri) pentru atingerea lungimii specificate. n versiunea
Oracle 8, valoarea maxim a lungimii n este de 2000.
Numere cu precizia n i scala m. Precizia reprezint numrul maxim de digii
permis, care nu poate depi 38. Scala reprezint numrul de zecimale pe care
le va avea numrul i poate avea valori ntre -84 i 127.
Numere ntregi avnd precizia maxim n. Valoarea maxim pentru n este de
38.
Numere n virgul mobil avnd o precizie (numr maxim de digii) de 38 de
digii.
Date calendaristice avnd valori ntre 1 Ianuarie 4712 .e. n i 31 Decembrie
4712 e.n. Pentru fiecare dat calendaristic sunt nregistrate urmtoarele
informaii: secolul, anul, luna, ziua, ora, minutul i secunda.
Pentru a specifica o valoare de tip dat calendaristic, este necesar
convertirea unui ir de caractere sau a unui numr folosind funcia TO_DATE.
Atunci cnd sunt folosite n expresii de tip dat calendaristic, Oracle
convertete automat iruri de caractere care au formatul implicit de dat
calendaristic. Formatul implicit de dat calendaristic este specificat de
parametrul de iniializare NLS_DATE FORMAT i este un ir de caractere.
De exemplu, acesta poate fi DD-MON-YY, care cuprinde un numr de doi
digii pentru ziua din lun, o abreviaie a numelui lunii i ultimii doi digii ai
anului de exemplu 01-JAN-99 reprezint 1 Ianuarie 1999.
iruri de caractere de dimensiune variabil pn la 2 Gbytes sau 231-1 bytes. O
singur coloan de tip LONG este admis n cadrul unui tabel.
Se folosete pentru a stoca date binare (iruri de bii) de lungime variabil,
avnd lungimea maxim n bytes. Valoarea lui n trebuie specificat i trebuie
s nu depeasc 2000. Se poate folosi pentru stocarea imaginilor grafice sau a
sunetului digital. Este similar cu VARCHAR2, cu excepia dimensiunii
maxime i a faptului c pentru tipul de dat RAW nu se pot interpreta datele.
Se folosete pentru a stoca date binare (iruri de bii) de lungime variabil de
pn la 2Gbytes. Tipul de dat LONG RAW este similar tipului de dat
LONG, excepie fcnd faptul c pentru tipul de dat LONG RAW nu se pot
interpreta datele.

Tipul de dat poate fi urmat de unul sau mai multe numere n parantez care furnizeaz informaii
despre dimensiunea coloanei. Dimensiunea coloanei determin dimensiunea maxim a oricrei
valori pe care o poate avea coloana. Coloanele de tip VARCHAR2 trebuie s aib specificat o
mrime. Coloanele NUMBER i CHAR pot avea o mrime specificat, dar n lipsa acesteia se
folosete o valoare implicit.
Alte date tipuri de date scalare furnizate de Oracle SQL sunt NCHAR i NVARCHAR2, folosite
pentru reprezentarea caracterelor limbilor naionale. Pentru o descriere mai detaliat a acestor tipuri
de date se poate consulta Anexa 3, care cuprinde toate tipurile de date din PL/SQL (printre care se
regsesc i tipurile de date Oracle SQL). n Oracle8, alturi de aceste tipuri de date scalare, exist i
tipuri de date LOB (Large Objects), care specific locaia unor obiecte de dimensiuni mari. O
108

descriere mai detaliat a tuturor acestor tipuri de date se gsete n Capitolul 10 i Anexa 3. n plus,
opiunea obiect din Oracle8 permite definirea de ctre utilizator a unor tipuri de date. Aceast
opiune va fi discutat n detaliu n Capitolul 10.
n Oracle, tabelele pot fi create sau modificate n orice moment, chiar dac n momentul respectiv
exist utilizatori care folosesc baza de date. La crearea unui tabel nu este nevoie s se specifice
dimensiunea maxim a acestuia, ea fiind determinat pn la urm de ct de mult spaiu a fost
alocat spaiului tabel n care este creat tabelul. Unui tabel i poate fi repartizat mai mult spaiu n
mod automat, n cazul n care spaiul alocat iniial a fost umplut.
6.1.2 Tabele partiionate
O noutate introdus n Oracle8 este posibilitatea de a partiiona tabele, adic de a mpri tabelul n
mai multe pri independente, fiecare cu parametri de stocare potenial diferii i cu posibilitatea ca
pri diferite ale tabelului s se gseasc pe spaii tabel diferite. Fiecare partiie a tabelului conine
nregistrri ce au valoarea cheii ntr-un anumit interval specificat. n acest sens, partiionarea este
foarte folositoare n cazul tabelelor de dimensiuni foarte mari.
Partiionarea este transparent pentru utilizatori i aplicaii. Utilizarea tabelelor partiionate ofer
cteva avantaje. Dac o parte a tabelului este inaccesibil, celelalte pari sunt disponibile pentru
inserare, selecie, modificare i tergere; numai acele nregistrri care sunt n acea partiie nu vor fi
accesibile. De asemenea, se poate bloca accesul la o parte a tabelului n timp ce restul nregistrrilor
sunt disponibile.
Fiecare partiie poate avea proprii si parametri de stocare PCTFREE i PCTUSED, INITIAL,
NEXT, PCTINCREASE, MINEXTENTS, MAXEXTENTS. Acest lucru este important deoarece o
parte a tabelului poate s conin un numr mult mai mare de nregistrri dect alta, necesitnd,
pentru o funcionare eficient, parametri diferii de stocare. Posibilitatea de a atribui n mod
individual parametri de stocare fiecrei pri ofer o mai mare flexibilitate n stocarea datelor. De
asemenea, fiecare parte poate fi stocat n spaii tabel diferite. Acest lucru este avantajos n cazul n
care unul dintre spaiile tabel este inaccesibil.
Crearea tabelelor partiionate
Sintaxa comenzii CREATE TABLE n cazul partiionrii tabelului este:
CREATE TABLE nume_tabel
(nume_coloan tip_dat [DEFAULT expresie]
[, nume_coloan tip_dat [DEFAULT expresie] ... )
PARTITION BY RANGE (list_coloane)
(PARTITION nume_partiie VALUES [LESS|GREATER] THAN (list_valori)
[PCTFREE ntreg] [PCTUSED ntreg]
[TABLESPACE spaiu_tabel]
[STORAGE parametrii_de_stocare]
[, PARTITION nume_partiie VALUES [LESS|GREATER] THAN (list_valori)
[PCTFREE ntreg] [PCTUSED ntreg]
[TABLESPACE spaiu_tabel]
[STORAGE parametrii_de_stocare]])
unde

109

list_coloane este o list ordonat de coloane care determin partiia


list_valori este o list ordonat de valori pentru coloanele din list_coloane

CREATE TABLE salariat_part(


cod_salariat
NUMBER(10),
nume
varchar2(10),
prenume
varchar2(10),
data_nastere
date,
salariu
number(10),
manager
number(10),
cod_dept
number(10),
cod_tara
number(10))
PARTITIONED BY RANGE(salariu)
(PARTITION salariu_mic VALUES LESS THAN (1000)
TABLESPACE ts_alfa
STORAGE (initial 50K next 50K),
PARTITION salariu_mediu VALUES LESS THAN (10000)
TABLESPACE ts_beta
STORAGE (initial 100K next 100K),
PARTITION salariu_mare VALUES LESS THAN (9999999999)
TABLESPACE ts_alfa
STORAGE (initial 50K next 50K));
Not: MAXVALUE are practic semnificaia de infinit, ultima parte a tabelului cuprinznd valorile
de peste 10000.
6.1.3 Constrngeri
Alturi de numele i tipurile de date ale coloanelor, la definirea unui tabel se pot specifica i
constrngeri (restricii) de integritate (constraints). n Oracle, constrngerile sunt folosite pentru a
impune anumite restricii asupra datelor tabelului sau pentru a pstra integritatea referenial a bazei
de date. Constrngerile se pot defini la nivel de coloan sau la nivel de tabel, dup cum ele se refer
la datele unei singure coloane sau la datele mai multor coloane. n Oracle exist urmtoarele tipuri
de constrngeri:
Constrngere
NOT NULL
UNIQUE

Nivel de
definire
Coloan
Coloan, tabel

PRIMARY KEY

Coloan, tabel

[FOREIGN KEY] Coloan, tabel


REFERENCES
CHECK

Coloan

Funcionalitate
Impune ca valorile coloanei s fie diferite de Null.
Impune unicitatea valorilor unei coloane sau a unei combinaii
de coloane.
Impune unicitatea valorilor unei coloane sau a unei combinaii
de coloane. n plus, valorile Null nu sunt permise n coloanele
care fac parte din PRIMARY KEY. ntr-un tabel poate exista
o singur cheie primar.
Impune regula de integritate referenial n cadrul aceluiai
tabel sau ntre tabele diferite. O cheie strin este folosit n
relaie cu o coloan sau combinaie de coloane definite ca
UNIQUE sau PRIMARY KEY
Definete explicit o condiie pe care trebuie s o satisfac
datele din fiecare rnd al tabelului

110

n cazul folosirii constrngerilor la definirea unui tabel, sintaxa comenzii SQL CREATE TABLE se
completeaz n modul urmtor:
CREATE TABLE nume_tabel
(nume_coloana tip_data [DEFAULT expresie] [constr_ coloana [constr_ coloana] ...]
[nume_coloana tip_data [DEFAULT expresie] [constr_ coloana [constr_ coloana]...]] ...
constrngere_tabel [,constrngere_tabel] ....)
...
Sintaxa unei constrngeri la nivel de coloan este:
[CONSTRAINT nume constrngere]
{NOT NULL | UNIQUE | PRIMARY KEY
| REFERENCES tabel (coloana) [ON DELETE CASCADE]
| CHECK (condiie) }
iar sintaxa unei constrngeri la nivel de tabel este:
[CONSTRAINT nume constrngere]
{UNIQUE | PRIMARY KEY
|{FOREIGN KEY (coloana [,coloana] ...) REFERENCES
CASCADE]}}

tabel (coloana) [ON

DELETE

unde
CONSTRAINT permite specificarea unui nume pentru integritatea definit. Dac aceast opiune
este omis, Oracle va genera n mod automat un nume, de forma SYS_Cn, unde n reprezint un
numr care face ca numele constrngerii s fie unic.
NOT NULL, UNIQUE, PRIMARY KEY, [FOREIGN KEY] REFERENCES, CHECK sunt tipurile
de constrngeri definite n tabelul de mai sus.
ON DELETE CASCADE este o clauz care se poate folosi la definirea unei restricii de
integritate referenial; n acest caz, n cazul tergerii unei nregistrri care conine cheia primar
sau unic la care face referire cheia strin, integritatea referenial este meninut prin tergerea
tuturor nregistrrilor ce conin chei strine dependente,.
n exemplul de mai jos sunt create dou tabele departament i salariat, fiind impuse
urmtoarele constrngeri:
combinaia (cod_dept, cod_tara) este cheia primar a tabelului salariat. n acest
caz, constrngerea este definit la nivel de tabel.
cod_salariat este cheia primar a tabelului salariat. n acest caz, constrngerea este
definit la nivel de coloan.
nume este o coloan a tabelului salariat care nu admite valori Null.
manager este o cheie strin a tabelului salariat care face referin la cheia primar
cod_salariat a aceluiai tabel. n acest caz, constrngerea este definit la nivel de coloan.
valorile pentru coloana salariu din tabelul salariat trebuie s fie mai mari ca 0
combinaia de coloane (nume, prenume, data_nastere) din tabelul salariat
trebuie s aib valori unice. n acest caz, constrngerea este definit la nivel de tabel.
combinaia (cod_dept, cod_tara) este o cheie strin a tabelului salariat care face
referin la cheia primar a tabelului departament. n acest caz, constrngerea este definit la
111

nivel de tabel. Remarcai c n cazul constrngerii de cheie strin, sintaxa difer n cazul
definirii la nivel de coloan fa de cel al definirii la nivel de tabel, n prima situaie lipsind
cuvintele FOREIGN KEY.
CREATE TABLE departament(
cod_dept
NUMBER(10),
cod_tara
NUMBER(10),
nume_dept
VARCHAR2(10),
CONSTRAINT dept_pk PRIMARY KEY(cod_dept, cod_tara));
CREATE TABLE salariat(
cod_salariat
NUMBER(10)
constraint sal_pk primary key,
nume
VARCHAR2(10) not null,
prenume
VARCHAR2(10),
data_nastere
DATE,
manager
NUMBER(10)
CONSTRAINT sal_sal_fk REFERENCES salariat(cod_salariat),
salariu
NUMBER(10)
CONSTRAINT sal_ck CHECK(salariu > 0),
cod_dept
NUMBER(10),
cod_tara
NUMBER(10),
UNIQUE(nume, prenume, data_nastere),
CONSTRAINT sal_dept_fk FOREIGN KEY(cod_dept, cod_tara)
REFERENCES departament(cod_dept, cod_tara));
Constrngerea FOREIGN KEY impune integritatea referenial ntre tabelul master
(departament) i tabelul detaliu (salariat). De exemplu, aceasta nseamn c un salariat nu
poate fi adugat dect dac departamentul corespunztor este fie NULL sau exist n tabelul
departament. La fel, nu poate fi ters un departament dac exist angajai n acel departament.
Exist ns i posibilitatea de a permite tergerea unui departament n care exist salariai; n acest
caz, pentru meninerea integritii, este necesar i tergerea tuturor angajailor dependeni. Acest
lucru se poate face prin adugarea clauzei ON DELETE CASCADE pentru constrngerea
FOREIGN KEY:
CREATE TABLE salariat
(cod_salariat
number(10)
CONSTRAINT sal_pk PRIMARY KEY,
nume
VARCHAR2(10)
NOT NULL,
prenume
VARCHAR2(10),
data_nastere
DATE,
manager
NUMBER(10)
CONSTRAINT sal_sal_fk REFERENCES salariat(cod_salariat),
salariu
NUMBER(10)
CONSTRAINT sal_ck CHECK(salariu > 1000),
cod_dept NUMBER(10),
cod_tara
NUMBER(10),
UNIQUE(nume, prenume, data_nastere),
CONSTRAINT sal_dept_fk FOREIGN KEY(cod_dept, cod_tara)
REFERENCES departament(cod_dept, cod_tara)
on delete cascade);

112

Toate detaliile despre constrngeri sunt stocate n dicionarul de date Oracle. De exemplu, pentru a
vizualiza toate constrngerile definite pentru tabelele de mai sus putem executa urmtoarea
interogare asupra vederii ALL_CONSTRAINTS:
SELECT CONSTRAINT_NAME, CONSTRAINT_TYPE, TABLE_NAME
FROM ALL_CONSTRAINTS
WHERE TABLE_NAME IN ('SALARIAT', 'DEPARTAMENT');
care va produce rezultatul:
CONSTRAINT_NAME
-----------------------------SYS_C002725
SAL_PK
SAL_CK
SYS_C002728
SAL_SAL_FK
SAL_DEPT_FK
DEPT_PK

C
C
P
C
U
R
R
P

TABLE_NAME
-----------------------------SALARIAT
SALARIAT
SALARIAT
SALARIAT
SALARIAT
SALARIAT
DEPARTAMENT

7 rows selected.
Fiecare constrngere are asociat un nume. n general este convenabil ca acesta s fie dat n mod
explicit de cel care creeaz tabelul (cum este cazul constrngerilor CHECK, PRIMARY KEY i
FOREIGN KEY din exemplul de mai sus) pentru c n acest mod constrngerea poate fi referit
mai uor dup aceea. n caz contrar (de exemplu constrngerile UNIQUE i NOT NULL din
exemplul de mai sus) numele este generat automat i are forma SYS_C....
Constrngeri amnate.
n versiunea Oracle7 fiecare constrngere este verificat de fiecare dat cnd este executat o
instruciune DML (inserare, actualizare sau tergere). n versiunea Oracle8 exist posibilitatea ca o
constrngere s fie amnat (DEFERRED). n cazul acesta, mai multe comenzi SQL pot fi executate
fr a se verifica restricia, acesta fiind verificat numai la sfritul tranzaciei, atunci cnd este
executat instruciunea COMMIT. Dac vreuna dintre comenzile DML ale tranzaciei ncalc
restricia, atunci ntreaga tranzacie este derulat napoi i este returnat o eroare.
n Oracle8, orice constrngere pe tabel sau pe coloan poate fi definit ca amnabil folosind
cuvntul cheie DEFERABLE; opiunea contrar este NOT DEFERABLE care este i opiunea
implicit:
{constrngere_tabel | constrngere_coloana} [NOT DEFERABLE | DEFERABLE [INITIALLY
IMMEDIATE | INITIALLY DEFERRED]]
Cnd o constrngere este specificat ca fiind DEFERRABLE, se poate specifica n plus starea
iniial a constrngerii, care poate fi INITIALLY DEFERRED sau INITIALLY IMMEDIATE,
setarea implicit fiind INITIALLY IMEDIATE. Dac o constrngere are starea iniial
INITIALLY IMMEDIATE, ea este pornit n modul fr amnare, fiind verificat imediat dup
fiecare instruciune executat. Dac starea iniial este INITIALLY DEFERRABLE, atunci
constrngerea este verificat la executarea unei comenzi COMMIT sau la schimbarea strii
constrngerii n IMMEDIATE.

113

Schimbarea strii unei constrngeri se poate face folosind comanda SQL SET CONSTRAINT:
SET CONSTRAINT [DEFERRED | IMMEDIATE]
Posibilitatea de a amna verificarea unei constrngeri este folositoare n special n cazul unor
restricii de integritate referenial, n acest mod fiind posibil inserarea unor rnduri n tabela copil
(detaliu), care conine cheia strin, naintea rndului corespunztor din tabela printe (master), care
conine cheia primar.
n exemplul de mai jos, cele dou restricii de integritate referenial au fost definite ca amnabile.
create table departament(
cod_dept number(10),
cod_tara
number(10),
nume_dept
varchar2(10),
constraint dept_pk primary key(cod_dept, cod_tara));
create table salariat(
cod_salariat
number(10)
constraint sal_pk primary key,
nume
varchar2(10) not null,
prenume
varchar2(10),
data_nastere
date,
manager
number(10)
constraint
sal_sal_fk
references
salariat(cod_salariat)
deferrable,
salariu
number(10)
constraint sal_ck check(salariu > 0),
cod_dept
number(10),
cod_tara
number(10),
unique(nume, prenume, data_nastere),
constraint sal_dept_fk foreign key(cod_dept, cod_tara)
references departament(cod_dept, cod_tara)
deferrable);
Deoarece starea iniial a restriciilor nu a fost precizat, ea va fi implicit INITIALLY
IMMEDIATE. Pentru a trece restriciile n starea DEFERRED se folosete instruciunea SET
CONSTRAINT:
SET_CONSTRAINT sal_sal_fk DEFERRED;
SET CONSTRAINT sal_dept_fk DEFERRED;
De exemplu, urmtoarea secven de instruciuni SQL se execut cu succes dac restricia
referenial sal_dept_fk este DEFERRED, dar eueaz n caz contrar.
insert into salariat(cod_salariat, nume, cod_dept, cod_tara)
values(100, 'Popescu', 1, 40);
insert into departament(cod_dept, cod_tara, nume_dept)
values(1, 40, 'IT');
commit;

114

6.1.4 Crearea i popularea simultan a tabelelor


Atunci cnd se creeaz un tabel exist posibilitatea ca n acelai timp tabelul s fie i populat.
Pentru aceasta, n cadrul comenzii SQL CREATE TABLE se va utiliza clauza AS urmat de o
interogare pe unul sau mai multe tabele. n mod evident, numrul coloanelor din definiia tabelului
trebuie s coincid cu acela din interogare.
Exemplul urmtor creeaz un tabel care conine toate nregistrrile din tabelul salariat avnd
ara cu codul 100:
create table salariat_100(
cod_salariat, nume, prenume, data_nastere, manager,
cod_dept)
as
select
cod_salariat,
nume,
prenume,
data_nastere,
salariu, cod_dept
from salariat
where cod_tara = 100;

salariu,
manager,

Atunci cnd la crearea unui tabel se folosete clauza AS nu este permis specificarea tipurilor de
date ale coloanelor, acestea fiind preluate automat de la tabelul de baz. Pe de alt parte ns,
restriciile definite pentru tabelul de baz, cu excepia celor NOT NULL nu sunt preluate automat
de noul tabel. De exemplu, tabelul salariat_100 va avea o singur restricie de integritate,
NOT NULL pentru coloana nume. Folosind clauza AS se pot crea tabele i din mai multe tabele
de baz, de exemplu un tabel care conine codul, numele i prenumele salariailor precum i numele
departamentului n care lucreaz se poate crea n modul urmtor:
CREATE TABLE sal_dept_temp(
cod_salariat, nume, prenume, nume_dept)
AS
SELECT s.cod_salariat, s.nume, s.prenume, d.nume_dept
FROM salariat s, departament d
WHERE s.cod_dept = d.cod_dept
AND s.cod_tara = d.cod_tara;
6.1.5 Modificarea tabelelor
Un tabel existent poate fi modificat folosind comanda SQL ALTER TABLE. Se pot efectua
urmtoarele tipuri de modificri:
Adugarea de noi coloane (mpreun cu eventualele constrngeri pentru aceste coloane):
ALTER TABLE departament
ADD (localitate VARCHAR2(10) NOT NULL);
Modificarea tipului de date sau a mrimii unor coloane existente:
ALTER TABLE departament
MODIFY (nume_dept VARCHAR2(20));
Not: schimbarea tipului de date al unei coloane sau scderea dimensiunii acesteia nu este posibil
dect dac acea coloan este goal; n caz contrar, o astfel de operaie ar putea duce la modificarea
datelor din tabel.
115

tergerea unor constrngeri existente:


ALTER TABLE salariat
DROP CONSTRAINT sal_ck;
Trebuie remarcat c o constrngere PRIMARY KEY la care face referin o constrngere FOREIGN
KEY nu poate fi tears dect dac mpreun cu constrngerea PRIMARY KEY sunt terse i toate
constrngerile refereniale asociate. Pentru acesta se folosete clauza CASCADE.
ALTER TABLE departament
DROP CONSTRAINT dept_pk CASCADE;
Comanda SQL de mai sus terge att constrngerea PRIMARY KEY dept_pk de pe tabelul
departament, ct i constrngerea FOREIGN KEY de pe tabelul salariat.
Adugarea de noi constrngeri:
ALTER TABLE salariat
ADD (CONSTRAINT data_ck CHECK(data_nastere > '1-Jan-1900'));
Activarea (ENABLE) sau dezactivarea (DISABLE) unor constrngeri existente;
ALTER TABLE salariat DISABLE CONSTRAINT sal_dept_fk;
La crearea unui tabel, toate constrngerile definite sunt implicit active daca nu a fost folosit
opiunea DISABLE. Dac o constrngere este dezactivat, atunci asupra datelor pot fi executate
operaii care ncalc acea constrngere. O constrngere care a fost dezactivat poate fi ulterior
activat numai dac datele care au fost introduse, actualizate sau terse ct timp ea a fost dezactivat
nu ncalc aceasta constrngere. De exemplu, constrngerea sal_dept_fk poate fi reactivat
numai dac dup execuia comenzii de mai sus nu au fost introduse date n tabelul salariat care
ncalc integritatea referenial:
ALTER TABLE salariat ENABLE CONSTRAINT sal_dept_fk;
n versiunea Oracle8, alturi de starea activ (ENABLED) i inactiv (DISABLED), o constrngere
poate avea o a treia stare: impus (ENFORCED). Att restriciile activate ct i cele dezactivate pot
fi trecute n starea ENFORCED. O restricie poate fi trecut n starea ENFORCED folosind comanda
ALTER TABLE cu clauza ENFORCE CONSTRAINT:
ALTER TABLE salariat ENFORCE CONSTRAINT sal_dept_fk;
n cazul executrii acestei comenzi, restricia este impus dup executarea comenzii. Deci comanda
ALTER TABLE ... ENFORCE CONSTRAINT nu va eua dac n tabel exist nregistrri care
ncalc restricia respectiv (cum se ntmpl n cazul executrii unei comenzi ALTER TABLE
... ENABLE CONSTRAINT). Dar, dup ce restricia a fost impus, ea nu va mai permite
inserarea sau actualizarea nregistrrilor care nu o respect, cum s-ar fi ntmplat dac restricia era
dezactivat.
Not: Comanda SQL ALTER TABLE nu permite tergerea dintr-un tabel a unei coloane existente.
Dac totui se dorete acest lucru, se poate folosi comanda CREATE TABLE cu clauza AS, n care
116

se selecteaz coloanele dorite. De asemenea, comanda SQL ALTER


modificarea definiiei unei constrngeri existente.

TABLE nu permite

Din punct de vedere fizic, comanda ALTER TABLE permite schimbarea parametrilor
PCTFREE i PCTUSED i a parametrilor din clauza STORAGE folosind sintaxa:
ALTER TABLE nume_tabel
[PCTFREE ntreg] [PCTUSED ntreg]
[STORAGE parametrii_de_stocare]
De asemenea, comanda ALTER TABLE permite alocarea i dealocarea manual a spaiului
utilizat de ctre un tabel. Alocarea manual a spaiului pentru un tabel se face prin adugarea de
noi extinderi. Alocarea manual se poate face n general:
- nainte de o ncrcare masiv a datelor;
- pentru a controla distribuia extinderilor unui tabel n cadrul fiierelor.
Dealocarea spaiului asociat unui tabel reprezint eliberarea spaiului nefolosit de acesta (care
nu a fost niciodat folosit sau care a devenit ntre timp gol datorit tergerii de rnduri).
Pentru a aloca sau dealoca spaiul utilizat de un tabel se folosete comanda ALTER TABLE cu
urmtoarele sintaxe:
ALTER TABLE nume_tabel
ALLOCATE EXTENT [([SIZE ntreg [K|M]]
[DATAFILE nume_fiier_de_date] )]
respectiv
ALTER TABLE nume_tabel
DEALLOCATE UNUSED [KEEP ntreg [K|M]]
unde:
DATAFILE specific fiierul de date (din spaiul tabel asociat tabelului) care va cuprinde noua
extindere. Dac aceast opiune este omis, fiierul este ales de ctre Oracle
SIZE specific dimensiunea noii extinderi. Dac opiunea SIZE este omis atunci Oracle va
stabili dimensiunea extinderii pe baza parametrilor de stocare a tabelului.
Cu ajutorul opiunii KEEP se poate specifica un numr de bytes (Kbytes, Mbytes) din spaul liber
al tabelului ce nu vor fi dealocai.
6.1.6 Distrugerea tabelelor
Pentru a distruge un tabel n Oracle se poate folosi comanda SQL drop table:
DROP TABLE salariat;
Pe de alt parte ns, dac vom folosi o comand similar pentru a distruge un tabel a crui cheie
primar face referin la o cheie strin a altui tabel, adic ultimul tabel are definit o constrngere
FOREIGN KEY corespunztoare, de exemplu
DROP TABLE departament;
atunci existena constrngerii de integritate referenial va mpiedica distrugerea tabelului, astfel
nct la ncercarea de a executa comanda de mai sus se va genera un mesaj de eroare. n astfel de
117

situaii, tabelul trebuie distrus mpreun cu toate constrngerile FOREIGN KEY care fac referire la
cheia primar a acestuia. Acest lucru se poate face prin folosirea comenzii SQL DROP TABLE cu
clauza CASCADE CONSTRAINTS:
DROP TABLE departament CASCADE CONSTRAINTS;
Execuia comenzii de mai sus va duce la distrugerea tabelului departament i a constrngerii
refereniale sal_dept_fk.
n momentul n care un tabel este distrus, vor fi terse automat i toate datele din tabel ct i indecii
asociai lui. Vederile i sinonimele asociate unui tabel care a fost distrus vor rmne dar vor deveni
invalide.

118

6.2. Vederi
O vedere este un tabel logic, fiind de asemenea organizat n rnduri i coloane. Ea preia
rezultatul unei interogri i l trateaz ca pe un tabel, de unde i numele de tabel logic. De exemplu,
dac din tabelul salariat se dorete vizualizarea doar a cinci coloane (cod_salariat,
nume, prenume, data_nastere, cod_dept) i numai a rndurilor pentru care
cod_tara = 40, se poate crea o vedere care conine numai aceste linii i coloane, vezi figura 6.1.
tabel de baz salariat
cod_
nume
prenume
salariat
101
Popescu
Ion
102
Vasilescu Vasile
103
Georgescu Ilie
104
Enescu
Gic
105
Georgescu Viorel

data_
natere
11-DEC-77
12-JAN-77
01-MAY-78
11-JUN-66
02-APR-77

salariu

vedere salariat_40
cod_
nume
salariat
102
Vasilescu
104
Enescu
105
Georgescu

data_
natere
12-JAN-77
11-JUN-66
02-APR-77

cod_
dept
1
1
2

prenume
Vasile
Gic
Viorel

5000
3000
3000
2000
2000

manager Cod_
Dept
1
101
1
101
1
102
1
104
2

cod_tara
44
40
44
40
40

Figura 6.1: Un exemplu de vedere.


O vedere poate fi construit din una sau mai multe tabele sau chiar alte vederi i permite ca datele
din mai multe tabele s fie rearanjate, reunite logic sau ca noi date s fie calculate pe baza acestora.
Din punct de vedere al aplicaiei, vederile au acelai comportament ca i tabelele: vederile pot i
interogate i, cu anumite excepii care vor fi menionate mai trziu, asupra vederilor se pot efectua
operaii DML (INSERT, DELETE, UPDATE). Vederea este un instrument foarte puternic pentru
dezvoltatorul de aplicaii. Ea poate fi bazat pe mai multe tabele sau vederi care se pot gsi pe
maini diferite sau pot aparine unor utilizatori diferii, acestea fiind prezentate ca i cum ar fi un
singur tabel logic.
Spre deosebire de tabel, vederea nu stocheaz date i nici nu are alocat vreun spaiu de stocare;
vederea doar extrage sau deriv datele din tabelele la care aceasta se refer. Aceste tabele poart
numele de tabele de baz ale vederii. Acestea pot fi tabele sau pot fi ele nsele vederi. Oracle
stocheaz definiia vederii n dicionarul de date sub forma textului interogrii care definete
vederea, de aceea o vedere poate fi gndit ca o interogare stocat. Pentru vizualizarea definiiilor
vederilor se poate folosi coloana TEXT a vederilor ALL_VIEWS, DBA_VIEW i USER_VIEW
din dicionarul de date.
Vederile pot fi interogate exact la fel ca tabelele, folosind comanda SELECT. Cnd o interogare
SQL se refer la o vedere, Oracle combin aceast interogare cu interogarea care definete vederea.
n general, vederile sunt create pentru urmtoarele scopuri:
Asigurarea unui nivel mai mare de securitate a bazei de date prin limitarea accesului la un numr
mai restrns de linii i coloane ale unui tabel.
Simplificarea interogrilor SQL, permind vizualizarea unor date care n mod normal necesit
interogri SQL destul de complicate. De exemplu, o vedere poate permite utilizatorilor
118

vizualizarea datelor din mai multe tabele fr ca acetia s fie obligai s foloseasc un SELECT
pe mai multe tabele.
Prezentarea diferit a datelor fa de cea din tabelele de baz. De exemplu, coloana unei vederi
poate avea alt nume dect coloana corespunztoare din tabelul de baz, acest lucru neafectnd n
nici un fel tabelul de baz.
Efectuarea unor interogri care nu ar putea fi efectuate fr existena unei vederi. De exemplu,
este posibil definirea unei vederi care realizeaz un join ntre o vedere care include clauza
GROUP BY i un alt tabel; acest lucru nu poate fi fcut ntr-o singur interogare.
Pentru a menine calcule mai complicate. Interogarea care definete vederea poate efectua
calcule complicate aspra datelor dintr-un tabel; prin meninerea acestei interogri ca o vedere,
calculele pot fi efectuate de fiecare dat cnd se face referire la vedere.
Asigurarea transparent a datelor pentru anumii utilizatori i aplicaii. O vedere poate conine
date din mai multe tabele, care pot fi proprietatea mai multor utilizatori.

6.2.1 Crearea vederilor


O vedere este creat folosind comanda SQL CREATE VIEW. De exemplu, pentru vederea de mai
sus vom avea:
CREATE VIEW salariat_40
AS SELECT cod_salariat, nume, prenume, salariu, cod_dept
FROM salariat
WHERE cod_tara = 40;
O sintax simplificat a comenzii CREATE VIEW este urmtoarea:
CREATE [OR REPLACE] [FORCE | NOFORCE] VIEW nume_vedere
[(alias [,alias]...)]
AS subinterogare
[WITH READ ONLY]
[WITH CHECK OPTION [CONSTRAINT nume_cosntrangere]]
unde
OR REPLACE recreeaz vederea dac ea exist deja. Aceast opiune poate fi folosit pentru a
schimba definiia unei vederi existente fr a o distruge n prealabil. Avantajul recrerii vederii
prin opiunea REPLACE este c n acest caz se pstreaz toate privilegiile acordate asupra
acestei vederi. De exemplu, s presupunem c dup crearea unei vederi, au fost acordate
privilegii asupra vederii pentru anumite roluri sau pentru anumii utilizatori. Dac dup aceea
vederea este distrus i recreat, atunci toate privilegiile asupra vederii au fost pierdute i trebuie
acordate din nou. Dac vederea este ns recreat folosind opiunea OR REPLACE, atunci
privilegiile acordate sunt pstrate i nu mai este necesar acordarea lor nc o dat.
FORCE este o opiune care permite crearea vederii indiferent dac tabelele de baz i coloanele
la care se face referire exist sau nu, sau dac utilizatorul posed sau nu privilegiile
corespunztoare n legtur cu tabelele respective. Opiunea opus, NOFORCE, creeaz vederea
numai dac tabelele de baz exist i dac utilizatorul posed privilegiile corespunztoare n
legtur cu tabelele respective; NOFORCE este opiunea implicit. Dac se folosete opiunea
FORCE i un tabel de baz nu exist sau una dintre coloane nu este valid, atunci Oracle va crea
vederea cu erori de compilare. Dac mai trziu tabelul n cauz este creat sau coloana este
corectat, atunci vederea poate fi folosit, Oracle recompilnd-o dinamic nainte de folosire.

119

alias specific numele expresiilor selectate de interogarea vederii. Numrul alias-urilor trebuie
s fie acelai cu numrul de expresii selectate de ctre interogarea vederii. Un alias trebuie s fie
unic n cadrul unei interogri. Dac sunt omise alias-urile, Oracle va folosi denumirile coloanelor
din interogare. Atunci cnd interogarea vederii conine i expresii, nu doar simple coloane,
trebuie folosite alias-uri.
AS indic interogarea vederii. Aceasta poate fi orice instruciune SELECT care nu conine
clauzele ORDER BY i FOR UPDATE.
opiunea WITH READ ONLY asigur c nici o operaie DML (inserare, tergere, modificare) nu
va fi asigurat asupra vizualizrii.
WITH CHECK OPTION este o constrngere care arat c toate actualizrile efectuate prin
intermediul vederii vor afecta tabelele de baz numai dac actualizrile respective vor avea ca
rezultat numai rnduri care pot fi vizualizate prin intermediul vederii. CONSTRAINT furnizeaz
un nume pentru constrngerea CHECK OPTION. Asupra acestor opiuni vom reveni puin mai
trziu.
Exemplul urmtor ilustreaz crearea unei vederi care conine codul, numele, prenumele, salariul i
sporul salarial pentru toi salariaii din departamentul 1 i ara cu codul 40.
CREATE OR REPLACE VIEW salariat_1
(cod, nume, prenume, salariu, spor_salariu)
AS SELECT cod_salariat, nume, prenume, salariu, salariu*0.1
FROM salariat
WHERE cod_dept = 1
AND cod_tara = 40;
Dac datele din tabelul salariat sunt cele din figura 6.1, atunci vederea salariat_1 va conine
urmtoarele date:
salariat_1
cod
nume
102
Vasilescu
104
Enescu
Figura 6.2

prenume
Vasile
Gic

salariu
3000
3000

spor_salariu
300
300

6.2.2 Operaii DML asupra vederilor


n momentul n care n tabelele de baz sunt adugate noi date sau sunt actualizate sau terse cele
existente, aceste modificri se reflect corespunztor n vederile bazate pe aceste tabele. Acest lucru
este adevrat i viceversa, cu singura meniune c exist anumite restricii la inserarea, actualizarea
sau tergerea datelor dintr-o vedere. Aceste restricii sunt redate pe scurt n continuare:
Nu pot fi inserate, terse sau actualizate datele din vederi care conin una dintre urmtoarele:
operatorul DISTINCT (pentru eliminarea duplicatelor);
clauzele GROUP BY, HAVING, START WITH, CONNECT BY;
pseudo-coloana ROWNUM (aceast pseudo-coloan conine un numr ce indic ordinea n
care Oracle selecteaz nregistrrile dintr-un tabel);
funciile de grup (COUNT, SUM, MAX, MIN, AVG, STDDEV, VARIANCE, GLB);
operatorii de mulimi (UNION, UNION ALL, INTERSECT, MINUS).
Nu pot fi inserate sau actualizate valorile coloanelor care rezult prin calcul, de exemplu coloana
spor_salariu de mai sus. De asemenea nu se pot efectua operaii DML asupra valorilor
coloanelor care au fost calculate folosind funcia DECODE
120

Nu pot fi inserate sau actualizate date care ar nclca constrngerile din tabele de baz. De
exemplu, daca n tabela salariat coloana nume este definit ca NOT NULL, atunci n orice
vedere bazat pe acest tabel care nu conine coloana nume (de exemplu salariat_exemplu
definit mai jos) nu va fi posibil inserarea de date deoarece aceasta ar duce la nclcarea
constrngerii NOT NULL.
CREATE VIEW salariat_exemplu
AS SELECT cod_salariat, prenume, data_nastere
FROM salariat;
n versiunea Oracle 7 nu pot fi inserate, terse sau actualizate datele din vederi bazate pe mai
multe tabele; n versiunea Oracle 8 acest lucru este posibil, ns cu anumite excepii, care vor fi
discutate ntr-una dintre seciunile urmtoare.
n plus fa de regulile de mai sus, la crearea unei vederi se poate utiliza clauza WITH CHECK
OPTION care impune ca singurele date care pot fi inserate sau actualizate prin intermediul vederii
s fie numai acelea care pot fi vizualizate de aceasta.
Pentru a clarifica acest aspect, s considerm vederea salariat_2000 definit mai jos i
posibilitile existente de a insera rnduri n aceast vedere.
CREATE VIEW salariat_2000
AS SELECT cod_salariat, nume, prenume, data_nastere, salariu
FROM salariat
WHERE salariu > 2000;
Prima comand SQL de mai jos va duce la inserarea unui rnd n tabela de baz salariat, care
poate fi vizualizat i prin intermediul vederii salariat_2000, deoarece valoarea
corespunztoare coloanei salariu este mai mare dect 2000. Pe de alt parte, a doua comand
SQL va duce la inserarea unui rnd n tabelul de baz care nu poate fi ns vizualizat prin
intermediul vederii.
INSERT INTO salariat_2000
(cod_salariat, nume, prenume, data_nastere, salariu)
VALUES (106, 'Ionescu', 'Vasile', '11-JUL-60' , 3000);
INSERT INTO salariat_2000
(cod_salariat, nume, prenume, data_nastere, salariu)
values (107, 'Popescu', 'Viorel', '22-JAN-69' , 1000);
De exemplu, dac naintea executrii acestor comenzi n tabelul salariat exist datele din
figura 6.1, atunci dup executarea acestor comenzi, datele din tabelul salariat i vederea
salariat_2000 vor fi urmtoarele:
tabel de baz salariat
cod_
Nume
prenume
salariat
101
Popescu
Ion
102
Vasilescu Vasile
103
Georgescu Ilie
104
Enescu
Gic

data_
nastere
11-DEC-77
12-JAN-77
01-MAY-78
11-JUN-66

121

salariu
5000
3000
3000
2000

manager cod_
dept
1
101
1
101
1
102
1

cod_tara
44
40
44
40

105
106
107

Georgescu
Ionescu
Popescu

Viorel
Vasile
Viorel

vedere salariat_2000
Cod_
nume
prenume
Salariat
101
Popescu
Ion
102
Vasilescu Vasile
103
Georgescu Ilie
106
Ionescu
Vasile
Figura 6.3

02-APR-77
11-JUL-60
22-JAN-69

2000
3000
1000

data_
nastere
11-DEC-77
12-JAN-77
01-MAY-78
11-JUL-60

salariu

104

40

5000
3000
3000
3000

S presupunem acum c aceeai vedere, salariat_2000, este creat folosind clauza WITH
CHECK OPTION:
CREATE VIEW salariat_2000
AS SELECT cod_salariat, nume, prenume, data_nastere, salariu
FROM salariat
WHERE salariu > 2000
WITH CHECK OPTION;
i n acest caz, inserarea n vedere a unui rnd pentru care valoarea coloanei salariu este mai mare
dect 2000 se face fr probleme. Pe de alt parte ns, orice ncercare de a insera n vedere rnduri
pentru care salariul este mai mic sau egal cu 2000 va produce o eroare indicnd nclcarea
constrngerii WITH CHECK OPTION, comanda nemodificnd tabelul de baz. De exemplu,
executarea celor dou comenzi de INSERT de mai sus va avea n acest caz ca rezultat urmtoarele
date din salariat i salariat_2000.
tabel de baz salariat
cod_
nume
prenume
salariat
101
Popescu
Ion
102
Vasilescu Vasile
103
Georgescu Ilie
104
Enescu
Gic
105
Georgescu Viorel
106
Ionescu
Vasile
vedere salariat_2000
cod_
nume
prenume
salariat
101
Popescu
Ion
102
Vasilescu Vasile
103
Georgescu Ilie
106
Ionescu
Vasile
Figura 6.4.

data_
nastere
11-DEC-77
12-JAN-77
01-MAY-78
11-JUN-66
02-APR-77
11-JUL-60

salariu

data_
nastere
11-DEC-77
12-JAN-77
01-MAY-78
11-JUL-60

salariu

5000
3000
3000
2000
2000
3000

manager cod_
dept
1
101
1
101
1
102
1
104
2

cod_tara
44
40
44
40
40

5000
3000
3000
3000

n cazul folosirii constrngerii CHECK OPTION, acesteia i se poate atribui un nume folosind
opiunea CONSTRAINT din cadrul comenzii CREATE VIEW. De exemplu:
CREATE VIEW salariat_2000
122

AS SELECT cod_salariat, nume, prenume, data_nastere, salariu


FROM salariat
WHERE salariu > 2000
WITH CHECK OPTION CONSTRAINT salariu_2000;
Dac opiunea CONSTRAINT este omis, Oracle atribuie n mod automat constrngerii CHECH
OPTION un nume de forma SYS_Cn unde n este un ntreg care face ca numele constrngerii
s fie unic n baza de date.
6.2.3 Operaii DML asupra vederilor bazate pe mai multe tabele (Join-Views)
Aa cum am menionat mai sus, n versiunea Oracle8 este posibil inserarea, actualizarea sau
tergerea datelor dintr-o vedere bazat pe mai multe tabele, cu anumite restricii ns. Alturi de
restriciile generale, aplicabile tuturor vederilor, prezentate n seciunea precedent, exist i
restricii specifice numai vederilor bazate pe mai multe tabele. Acestea sunt redate de urmtoarele
reguli:
Regula general: Orice operaie de INSERT, UPDATE sau DELETE pe o vedere bazat pe mai
multe vederi poate modifica datele din doar unul dintre tabelele de baz.
nainte de a enuna regulile specifice pentru fiecare dintre operaiile INSERT, UPDATE sau
DELETE este necesar definirea conceptului de tabel protejat de cheie (key-preserved table). Dat
fiind o vedere bazat pe mai multe tabele, un tabel de baz al vederii este protejat prin cheie dac
orice cheie selectat a tabelului este de asemenea i cheie a vederii. Deci, un tabel protejat prin
cheie este un tabel ale crui chei se pstreaz i la nivel de vedere. Trebuie reinut c, pentru a fi
protejat prin cheie, nu este necesar ca un tabel s aib toate cheile selectate n vedere. Este suficient
ca, atunci cnd cheia tabelului este selectat, aceasta s fie i cheie a vederii. Proprietatea unui tabel
de a fi protejat prin cheie nu este o proprietate a datelor din tabel, ci o proprietate a schemei. n
exemplul de mai jos, dac pentru fiecare combinaie (cod_tara, cod_dept) ar exista un singur
salariat, atunci combinaia (cod_tara, cod_dept) din tabelul departament ar fi unic pentru
datele din vederea rezultat, dar tabelul departament tot nu ar fi protejat prin cheie.
Pentru a ilustra aceast noiune ct i regulile urmtoare, s considerm o definiie simplificat a
tabelelor departament i salariat n care pstrm doar constrngerile de cheie primar i
integritate referenial.
CREATE TABLE departament(
cod_dept
NUMBER(10),
cod_tara
NUMBER(10),
nume_dept
VARCHAR2(10),
PRIMARY KEY(cod_dept, cod_tara));
CREATE TABLE salariat(
cod_salariat
NUMBER(10)
nume
VARCHAR2(10),
prenume
VARCHAR2(10),
data_nastere
DATE,
manager
NUMBER(10)
salariat(cod_salariat),
salariu
NUMBER(10),
cod_dept
NUMBER(10),
cod_tara
NUMBER(10),
123

PRIMARY KEY,

REFERENCES

FOREIGN KEY(cod_dept,
cod_tara));

cod_tara)

REFERENCES

departament(cod_dept,

S mai considerm i urmtoarea vedere bazat pe aceste dou tabele:


CREATE VIEW sal_dept
(cod_salariat,
nume,
prenume,
salariu,
cod_dept,
nume_dept)
AS
SELECT
s.cod_salariat,
s.nume,
s.prenume,
s.cod_dept, s.cod_tara, d.nume_dept
FROM salariat s, departament d
WHERE s.cod_dept = d.cod_dept
AND s.cod_tara = d.cod_tara;

cod_tara,
s.salariu,

n exemplul de mai sus, tabelul salariat este protejat prin cheie. Regulile specifice pentru
fiecare dintre operaiile DML (INSERT, UPDATE sau DELETE) sunt redate n continuare:
Reguli de actualizare (UPDATE):
Toate coloanele care pot fi actualizate printr-o vedere trebuie s corespund coloanelor dintr-un
tabel protejat prin cheie. Dac o coloan provine dintr-o tabel neprotejat prin cheie, atunci
Oracle nu va putea identifica n mod unic nregistrarea care va trebui actualizat. De exemplu,
comanda SQL de mai jos se va executa cu succes.
UPDATE sal_dept
SET salariu = salariu + 100
WHERE cod_tara = 40;
Pe de alt parte, comanda urmtoare va eua:
UPDATE sal_dept
SET nume_dept = IT
WHERE cod_dept = 1
AND cod_tara = 40;
Comanda de mai sus va eua pentru c ea ncearc s actualizeze o coloan din tabelul
departament, tabel care nu este protejat prin cheie.
Dac vederea este definit folosind clauza WITH CHECK OPTION, atunci toate coloanele de
jonciune i toate coloanele tabelelor repetate nu pot fi modificate. De exemplu, dac vederea
sal_dept ar fi fost definit folosind clauza WITH CHECK OPTION, atunci comanda
urmtoare va eua deoarece ncearc modificarea unei coloane de jonciune.
UPDATE sal_dept
SET cod_dept = 2
WHERE cod_salariat = 101
AND cod_tara = 40;
Reguli de inserare (INSERT):
O comand INSERT nu poate s se refere n mod explicit sau implicit la coloane dintr-un tabel
care nu este protejat prin cheie. De exemplu, dac n tabelul departament exist o linie cu
cod_dept = 3 i cod_tara = 40, atunci urmtoarea comand SQL va fi executat cu
succes:
124

INSERT INTO sal_dept


(cod_salariat, nume, cod_dept, cod_tara)
VALUES(110, Marinescu, 3, 40);
n caz contrar, comanda va eua, fiind nclcat constrngerea de integritate referenial. Pe de
alt parte, comanda urmtoare va eua deoarece ea ncearc inserarea de date n mai multe
tabele.
INSERT INTO sal_dept
(cod_salariat, nume, nume_dept)
VALUES(111, Georgescu, IT);
Dac o vedere este definit folosind clauza WITH CHECK OPTION, atunci nu se pot executa
comenzi INSERT n acea vedere.
Reguli de tergere (DELETE)
Rndurile dintr-o vedere pot fi terse numai dac n jonciune exist un tabel protejat prin cheie
i numai unul. Dac ar exista mai multe tabele, Oracle nu ar ti din care tabel s tearg rndul.
De exemplu, comanda SQL de mai jos se va executa cu succes deoarece ea poate fi tradus ntr-o
operaie de tergere pe tabelul salariat:
DELETE FROM sal_dept
WHERE nume = Popescu;
Pe de alt parte, dac se ncearc executarea unei comenzi DELETE pe vederea de mai jos, ea va
eua deoarece ambele tabele de baz, s1 i s2, sunt protejate prin cheie:
CREATE VIEW emp_emp AS
SELECT s1.nume, s2.prenume
FROM salariat s1, salariat s2
WHERE s1.cod_salariat = s2.cod_salariat;
Dac vederea este definit folosind clauza WITH CHECK OPTION, atunci nu pot fi terse
rnduri din vedere. De exemplu, nu se poate executa o instruciune DELETE pe vederea de mai
jos deoarece ea este definit ca auto-jonciune a unui tabel protejat prin cheie.
CREATE VIEW emp_manag AS
SELECT s1.nume, s2.nume nume_manager
FROM salariat s1, salariat s2
WHERE s1.manager = s2.cod_salariat
WITH CHECK OPTION;
Vederile
ALL_UPDATABLE_COLUMNS,
DBA_UPDATABLE_COLUMNS
i
USER_UPDATABLE_COLUMNS ale dicionarului de date conin informaii care arat care dintre
coloanele vederilor existente pot fi actualizate. Vederile care nu pot fi actualizate direct pot fi
actualizate folosind triggere INSTEAD OF, vezi seciunea 9.16.
6.2.4 Recompilarea vederilor
Recompilarea unei vederi permite detectarea eventualelor erori referitoare la vederea respectiv
naintea executrii vederii. Dup fiecare modificare a tabelelor de baz este recomandabil ca
125

vederea s se recompileze. Acest lucru se poate face folosind comanda SQL alter view ...
compile:
alter view salariat_2000 compile;
6.2.5 Distrugerea vederilor
Pentru distrugerea unei vederi se folosete comanda drop view:
drop view salariat_2000;
Utilizarea unei vederi este cteodat o sabie cu dou tiuri. Dei vederile constituie un instrument
extrem de convenabil pentru dezvoltatorul de aplicaii, ele pot avea un impact negativ asupra
performanei acestora. Dac pentru vederi simple (de exemplu simple copii ale unui tabel) impactul
asupra performantei nu este sesizabil, pentru vederi complexe, care cuprind interogri pe mai multe
tabele, acest impact poate fi foarte sever. De aceea folosirea vederilor trebuie planificat cu grija,
pentru a se vedea dac avantajul creat de simplitatea n manipulare a acestora compenseaz
impactul negativ asupra performanei.

126

6.3. Indeci
Un index este o structur opional a bazei de date care permite accesarea direct a unui rnd dintrun tabel. Indecii pot fi creai pentru una sau mai multe coloane a unui tabel, n acest ultim caz
folosindu-se denumirea de indeci compui sau indeci concatenai. Un index este utilizat de ctre
baza de date pentru a gsi rapid valori pentru coloana sau coloanele pentru care a fost creat indexul,
n acest mod furniznd o cale de acces direct la liniile asociate acestora fr a mai fi necesar
investigarea fiecrui rnd din tabel. Practic, n momentul n care se dorete cutarea anumitor
nregistrri ale cror valori ndeplinesc un anumit criteriu, n loc s se parcurg tabelul, se parcurge
indexul, acesta din urm furniznd localizarea exact a nregistrrilor ce ndeplinesc criteriul de
cutare prin precizarea ROWID. Aa cum am mai precizat n seciunea 4.5, identificatorul de rnd
ROWID reprezint n primul rnd cel mai rapid mod de a localiza o anumit nregistrare. Prin
urmare pentru a gsi o anumit nregistrare n modul cel mai rapid se determin ROWID-ul acesteia
n loc s se parcurg secvenial tabelul respectiv. Fr indeci, operaii precum determinarea
unicitii sau ordonarea valorilor unei coloane ar putea consuma multe resurse i timp.
Prezena indecilor este transparent pentru utilizator i aplicaie, ei neputnd fi referii n mod
direct prin interogri. n plus, sintaxa unei comenzi SQL nu este n nici un fel influenat de
existena indecilor, iar rezultatele oricrei interogri vor fi aceleai indiferent dac exist indeci
sau nu. Pe de alt parte ns, utilizarea corect a acestora poate influena n cel mai mare grad
eficiena unei interogri: diferena va consta n rapiditatea cu care se execut comanda i nu n
rezultatele acesteia. Foarte multe sisteme ce raporteaz probleme de performan sufer din cauza
lipsei unui index sau din cauza absenei unui index optim. Informaia coninut n indeci este
redundant, ea fiind derivat din informaia care exist n tabele.
Indecii sunt independeni din punct de vedere fizic i logic de datele din tabelul de baz. Un index
poate fi creat i distrus fr ca datele din tabelul de baz sau ceilali indeci s aib de suferit.
Singurul lucru pe care indexul l va modifica va fi durata accesului la datele tabelului, acesta
devenind mai lent n absena indexului. Evident, odat cu tergerea unui tabel sunt teri i indecii
asociai acestuia.
Indecii pot s fie unici sau ne-unici. Indecii unici garanteaz faptul c nu va exista nici o pereche
de linii care s aib valori identice pentru coloana sau grupul de coloane pentru care a fost definit
indexul. Valorile Null nu sunt considerate pentru unicitate. Un rnd cu valoarea Null n coloana
indexat nu va fi nregistrat n index, deci un index unic nu va mpiedica stocarea mai multor
rnduri cu o valoare Null n coloana indexat. Un index ne-unic nu impune nici o restricie n
legtur cu valorile din coloanele care l definesc.
Odat definit, un index este actualizat de ctre baza de date ori de cte ori au loc modificri ale
datelor tabelului. Aceasta nseamn, c ori de cte ori au loc inserri, tergeri sau modificri ale
datelor unui tabel, toi indecii acelui tabel trebuie actualizai n mod automat, acest lucru avnd ca
efect ncetinirea acestor operaii asupra datelor tabelului. Cu alte cuvinte, existena indecilor
sporete viteza accesului la datele tabelului pe de o parte, dar n acelai timp ncetinete operaiile
de modificare ale acestora. De aceea, nu trebuie creat un index pentru fiecare coloan a unui tabel
(dei acest lucru este posibil), ci pentru anumite coloane cheie ale acestuia. De exemplu, se
recomand indexarea coloanelor care conin n majoritate valori unice sau un domeniu larg de valori
sau coloane dup care se fac dese cutri sau ordonri. Deoarece prezena indecilor poate avea un
impact semnificativ asupra eficienei aplicaiei n continuare prezentm cteva sugestii privind
folosirea acestora:
Ce tabele trebuie indexate:

127

Indexai tabelele pentru care majoritatea interogrilor selecteaz doar un numr redus de rnduri
(sub 5%). Interogrile care selecteaz un numr mare de rnduri nu folosesc n mod eficient
indecii.
Nu indexai tabele ce conin puine nregistrri deoarece n acest caz accesul secvenial va fi mai
rapid.
Indexai tabelele care sunt interogate folosind clauze SQL simple. Clauzele SQL mai complexe
nu folosesc cu aceeai eficien indecii.
Nu indexai tabelele care sunt actualizate frecvent. Inserrile, modificrile i tergerile sunt
ngreunate de existena indecilor. Decizia de a indexa un tabel trebuie luat pe baza raportului
dintre numrul de interogri i cel de actualizri efectuat asupra acestuia.
Indexai tabelele care nu au valori duplicate n coloanele care apar n clauza WHERE a celor mai
frecvente interogri.
Ce coloane trebuie indexate:
Folosii coloanele cele mai frecvent folosite n clauza WHERE a interogrilor.
Nu indexai coloane care nu au multe valori unice. Totui, ncepnd cu versiunea Oracle8 se pot
indexa coloane care nu au multe valori distincte cu ajutorul indexului de tip bitmap asupra cruia
vom reveni n cuprinsul acestui capitol.
Coloanele care au valori unice sunt candidate foarte bune pentru indexare. De altfel, Oracle
creeaz n mod automat indeci unici pentru coloanele definite ca PRIMARY KEY sau UNIQUE.
n plus, din punct de vedere logic, este preferabil ca indecii unici s nu fie definii n mod
explicit, ci prin intermediul constrngerilor PRIMARY KEY i UNIQUE - acesta deoarece
unicitatea este un concept logic i ar trebui s fie asociat cu definiia tabelului.
Coloanele care sunt folosite pentru a face legtura dintre tabele sunt n general candidate pentru
indexare. n general, se recomand indexarea cheilor strine.
n anumite situaii, folosirea indecilor compui poate fi mai eficient dect a celor individuali.
De exemplu, crearea indecilor compui este recomandabil cnd dou coloane nu sunt unice
fiecare n parte dar combinaia lor este unic sau are n majoritate valori unice. De asemenea, se
recomand crearea indecilor compui atunci cnd interogrile uzuale ale tabelului conin n
clauza WHERE mai multe coloane individuale legate prin AND.
Indecii consum spaiu n baza de date la fel ca i tabelele i exist ntr-un spaiu tabel la fel ca i
acestea. Spaiul necesar indecilor pentru tabele mari este de obicei semnificativ, aa c trebuie
planificat din momentul n care se proiecteaz baza de date.
6.3.1 Crearea, modificarea i distrugerea indecilor
n SQL un index se creeaz folosind comanda CREATE INDEX. O sintax simplificat a acestei
comenzi este prezentat n continuare:
CREATE [UNIQUE] INDEX nume_index
ON tabel (coloana [,coloana] ...)
[PCTFREE ntreg] [PCTUSED ntreg]
[TABLESPACE spaiu_tabel]
[STORAGE parametrii_de_stocare]
unde:
Dac este specificat opiunea UNIQUE, indexul creat este unic, altfel nu.
Valorile parametrilor PCTFREE i PCTUSED determin gradul de utilizare a blocurilor din
extinderile segmentului de index, vezi seciunea 4.4.

128

TABLESPACE specific spaiul tabel n care va fi stocat indexul. Dac acesta nu este menionat
explicit, se va folosi spaiul tabel implicit (default) al utilizatorului care este proprietarul schemei
din care face parte indexul. n general, se recomand stocarea indexului ntr-un spaiu tabel
diferit de cel n care este stocat tabelul su; n acest caz Oracle poate accesa tabelul i indexul n
paralel, obinndu-se astfel o cretere a performanelor interogrilor.
Clauza STORAGE este folosit pentru setarea parametrilor de stocare (INITIAL, NEXT,
PCTINCREASE, MINEXTENTS, MAXEXTENTS) prin intermediul crora se specific mrimea i
modul de alocare a extinderilor segmentului de index, vezi seciunea 4.1.1.
Urmtoarele comenzi SQL creeaz un index compus sal_dept_ind pentru coloanele
cod_dept i cod_tara din tabelul salariat i respectiv un index unic pentru coloana
nume_dept a tabelului departament.
CREATE INDEX sal_dept_ind ON salariat(cod_dept, cod_tara);
CREATE UNIQUE INDEX nume_dept_ind

ON departament(nume_dept);

Crearea indecilor unui tabel se recomand a se face dup ce tabelul a fost populat cu date - aceasta
deoarece existena indecilor ncetinete n mod evident inserarea datelor.
La definirea constrngerilor PRIMARY KEY sau UNIQUE sau la activarea acestora, Oracle creeaz
n mod automat indeci unici pentru coloanele sau grupurile de coloane respective. n acest caz
numele indexului coincide cu numele constrngerii.
La fel ca i n cazul tabelelor, parametrii de stocare a indecilor pot fi modificai ulterior. Pentru
aceasta se folosete comanda ALTER INDEX cu urmtoarea sintax:
ALTER INDEX nume_index
STORAGE parametrii_de_stocare
De exemplu:
ALTER INDEX sal_dept_ind
STORAGE (NEXT 400K MAXEXTENTS 100);
De asemenea, Oracle8 permite alocarea i dealocarea manual a spaiului utilizat de un index.
Alocarea manual a spaiului pentru un index nseamn adugarea manual a unei noi extinderi. De
exemplu, alocarea manual se poate face naintea unei perioade n care se va nregistra o activitate
intens de inserri n tabela pe care este bazat indexul. n acest caz, alocarea manual previne
extinderea dinamic a indexului (alocarea dinamic a unei noi extinderi), mpiedicnd astfel
creterea timpului de execuie. Dealocarea spaiului asociat unui index reprezint eliberarea
spaiului nefolosit de acesta.
Pentru a aloca sau dealoca spaiul utilizat de un index se folosete comanda ALTER TABLE cu
urmtoarele sintaxe:
ALTER INDEX nume_index
ALLOCATE EXTENT ([SIZE ntreg [K|M]]
[DATAFILE specificaie_fiier_de_date] )
respectiv

129

ALTER INDEX nume_index


DEALLOCATE UNUSED [KEEP ntreg [K|M]]
Semnificaia parametrilor din aceste comenzi este aceeai ca i n cazul tabelelor, vezi seciunea
6.1.5.
Un index poate fi distrus folosind comanda SQL DROP INDEX cu urmtoarea sintax:
DROP INDEX nume_index;
De exemplu:
DROP INDEX sal_dept_ind;
Un index nu poate fi ters dac el a fost creat n mod automat, ca parte a definirii sau a activrii unei
restricii PRIMARY KEY sau UNIQUE. n acest caz indexul este ters automat la tergerea sau
dezactivarea constrngerii.
tergerea unui index se face de obicei dac indexul nu mai este necesar, dac se dorete
reconstruirea sa (despre care vom discuta n continuare) sau nainte de ncrcarea masiv a datelor
ntr-un tabel; tergerea unui index nainte de ncrcarea masiv a datelor i recrearea lui dup
terminarea ncrcrii va duce la mbuntirea performanei ncrcrii precum i la utilizarea
spaiului alocat indexului n mod mai eficient.
Pentru a reconstrui un index se pot folosi dou metode. Prima este de a terge indexul folosind
comanda DROP INDEX i de a l recrea folosind comanda CREATE INDEX. A doua este folosirea
ALTER INDEX cu opiunea REBUILD folosind sintaxa:
ALTER INDEX nume_index REBUILD
[PCTFREE ntreg] [PCTUSED ntreg]
[TABLESPACE spaiu_tabel]
[STORAGE parametrii_de_stocare]
[REVERSE|NOREVERSE];
Reconstruirea unui index se face n urmtoarele situaii:
- indexul existent trebuie mutat ntr-un spaiu tabel diferit (de exemplu, dac indexul a fost creat
n mod automat de o constrngere de integritate, caz n care el se gsete n acelai spaiu tabel
cu tabelul).
- un index normal trebuie convertit ntr-un index cu cheie invers (despre tipurile de indeci vom
vorbi n continuare). Pentru a converti un index obinuit ntr-un index cu cheie invers se
folosete comanda ALTER INDEX REBUILD cu opiunea REVERSE (opiunea contrar
este NOREVERSE, care este si opiunea implicit)
- pentru a recupera spaiul de stocare sau pentru a schimba atributele fizice de stocare.
n cazul reconstruirii indexului folosind comanda ALTER INDEX REBUILD, n timpul crerii
noului index este pstrat i indexul original, astfel c indexul poate fi folosit de interogri i n
timpul acestei operaii. Principalele avantaje ale fiecrei dintre cele dou metode sunt rezumate n
tabelul de mai jos:
terge i recreeaz
Poate redenumi indexul.

Folosete opiunea REBUILD


Nu poate redenumi indexul.

130

Poate schimba ntre UNIQUE i non-UNIQUE.


Poate schimba ntre tipul de index bazat de arbore
B* i indexul de tip bitmap (vezi paragrafele
urmtoare)
Are nevoie de spaiu doar pentru o copie a
indexului.
Necesit sortare.
Index este indisponibil n perioada dintre tergere
i recreare.
Nu se poate folosi aceast metod dac indexul a
fost creat de o constrngere PRIMARY KEY sau
UNIQUE. n acest caz tergerea indexului se
poate face prin tergerea sau dezactivarea
constrngerii respective.

Nu poate schimba ntre UNIQUE i non-UNIQUE


Nu poate schimba ntre tipul de index bazat de
arbore B* i indexul de tip bitmap.
Are nevoie de spaiu suplimentar pentru a duplica
indexul n mod temporar.
Nu necesit sortare, folosindu-se indexul iniial.
Indexul este disponibil interogrilor.
Se poate folosi aceast metod dac indexul a fost
creat de o constrngere PRIMARY KEY sau
UNIQUE.

6.3.2 Tipuri de indeci


Index de tip arbore B*
Cel mai ntlnit tip de index folosit de Oracle este indexul de tip arbore B* (B*-tree index sau
balanced tree index). Acesta este tipul de index creat la executarea unei comenzi standard CREATE
INDEX i tipul de index la care ne-am referit n seciunea de mai sus. Un arbore B*, este un arbore
n care pentru gsirea oricrei valori din arbore sunt necesari acelai numr de pai, indiferent de
valoarea cutat. Figura 6.5 ilustreaz structura unui index de tip arbore B*.
Algoritmul de cutare ntr-un astfel de arbore compar valoarea cerut cu valorile din nivelul
superior de blocuri; n funcie de aceast comparaie, valoarea cutat este apoi comparat cu unul
din blocurile inferioare i comparaia continu pn cnd se ajunge la ultimul nivel de blocuri,
numite blocuri frunz. Blocurile frunz ale indexului conin toate valorile datelor indexate i
valoarea ROWID a rndului asociat pentru fiecare dintre aceste valori. Un arbore B* este
ntotdeauna balansat, adic distana de la vrf la oricare nod frunz este aceeai pentru toate
nodurile. Cu ct este mai mare aceast distan, cu att este mai mare numrul de blocuri ce trebuie
examinate pentru a ajunge la un bloc frunz i, prin urmare cu att mai lent este indexul. Pentru un
index unic, exist un singur ROWID pentru fiecare valoare. Cnd un bloc frunz se umple, atunci
este creat un bloc nou. Unele informaii din blocul plin sunt mutate n noul bloc, acesta din urm
devenind bloc frunz. Deoarece un arbore B* este un arbore balansat, activitile ntr-un index nu se
termin aici, ducnd uneori pn la schimbarea informaiilor din nodul rdcin al arborelui sau
chiar pn la nlocuirea nodului rdcin cu un altul. Teoria indecilor de tip arbore B* este dincolo
de scopul acestei cri, pentru mai multe informaii se poate consulta [3] [Basca97] sau literatura de
specialitate care se ocup cu structuri de date.

131

< ION
ION

ION
MIHAI
TUDOR
TUDOR
VASILE
VIOREL

MIHAI
PAUL
SERGIU

< COSTEL
COSTEL
GABRIEL

ION
MARIN

GABRIEL
GIGI

COSTEL
DAN
DUMITRU

ANTON
AUREL

COSTEL-ROWID
DAN-ROWID
DUMITRU-ROWID
Figura 6.5 : structura intern a unui index de tip arbore B*.
Pentru indeci neunici, dac exist mai multe ROWID pentru aceeai valoare a datelor indexate,
atunci i acestea sunt sortate, deci indecii neunici sunt sortai nti dup valoarea datelor i apoi
dup ROWID. Valorile nule nu sunt indexate, cu excepia indecilor de cluster, vezi mai jos.
Index partiionat
O noutate adus de versiunea Oracle8 este posibilitatea de partiionare a unui index. Aa cum un
tabel poate fi partiionat, la rndul lui un index de tip arbore B* poate fi i el partiionat. Indecii
partiionai sunt folosii n cazul tabelelor mari pentru a stoca valorile coloanei indexate n mai
multe segmente. Practic, pentru fiecare partiie a tabelului poate fi creat o partiie a unui index.
Prin urmare, partiionarea permite stocarea unui index n mai multe spaii tabel. Unul din avantajele
partiionrii este descreterea domeniului de valori n care indexul caut o anumit valoare.
Pentru a crea un index partiionat se folosete comanda CREATE index cu clauza PARTITION. Un
index partiionat, la fel ca i un tabel partiionat (vezi seciunea 6.1.2) permite definirea unor spaii
table i parametrii de stocare diferii pentru fiecare parte. Exist dou moduri de a defini un index
partiionat: local i global.
- local: partiiile indexului sunt similare cu partiiile tabelului; n acest caz indexul este partiionat
n funcie de aceeai coloan, pe acelai interval de valori ca i tabelul la care se refer; partiiile
trebuiesc enunate n aceeai ordine ca i partiiile tabelului la care se refer. Aceasta este
metoda cel mai des folosit deoarece partiionarea este dirijat de tabelul de baz. Sintaxa
pentru crearea unui index partiionat local este urmtoarea:
CREATE INDEX nume_index
ON tabel (coloana [,coloana] ...)
LOCAL
(PARTITION nume_partiie
[PCTFREE ntreg] [PCTUSED ntreg]
[TABLESPACE spaiu_tabel]
[STORAGE parametrii_de_stocare]
[, PARTITION nume_partiie VALUES [LESS|GREATER] THAN (list_valori)
132

[PCTFREE ntreg] [PCTUSED ntreg]


[TABLESPACE spaiu_tabel]
[STORAGE parametrii_de_stocare]])
Urmtorul exemplu creeaz un index partiionat local pe baza tabelului partiionat
salariat_part din seciunea 6.1.2.
CREATE INDEX nume_sal_part_ind
LOCAL
(PARTITION salariu_mic
TABLESPACE ts_ind_alfa
STORAGE (initial 10K next
PARTITION salariu_mediu
TABLESPACE ts_ind_beta
STORAGE (initial 20K next
PARTITION salariu_mare
TABLESPACE ts_ind_alfa
STORAGE (initial 10K next
-

ON salariat_part(nume)

10K),
20K),
10K));

global: partiiile indexului sunt definite de utilizator i nu sunt similare cu partiiile tabelului la
care se refer indexul. Sintaxa pentru crearea unui index partiionat global este urmtoarea:
CREATE INDEX nume_index
ON tabel (coloana [,coloana] ...)
PARTITION BY RANGE (list_coloane)
(PARTITION nume_partiie VALUES [LESS|GREATER] THAN (list_valori)
[PCTFREE ntreg] [PCTUSED ntreg]
[TABLESPACE spaiu_tabel]
[STORAGE parametrii_de_stocare]
[, PARTITION nume_partiie VALUES [LESS|GREATER] THAN (list_valori)
[PCTFREE ntreg] [PCTUSED ntreg]
[TABLESPACE spaiu_tabel]
[STORAGE parametrii_de_stocare]])

Urmtoarea comand creeaz indexul global nume_sal_ind pentru tabela salariat, index ce
va avea dou partiii:
CREATE INDEX nume_sal_ind ON salariat(nume) GLOBAL PARTITION BY
RANGE (nume)
(PARTITION VALUES LESS THAN ('N')
TABLESPACE ts_alfa_ind,
PARTITION VALUES LESS THAN (MAXVALUE)
TABLESPACE ts_beta_ind);
Index de cluster
Un index de cluster (index de grup) este un index bazat pe coloanele comune ale unui cluster. Nu se
pot efectua nici un fel de comenzi DML asupra unui cluster pn cnd nu a fost creat un index de
cluster. Clusterele i indecii de cluster sunt prezentai pe larg n seciunea 6.4. Gruparea tabelelor

133

n cluster nu afecteaz crearea de indeci suplimentari pentru tabele individuale; acetia pot fi creai
sau distrui ca de obicei.
Index cu cheie invers
Un index cu cheie invers (reverse-key index) reprezint o nou metod (adus de versiunea
Oracle8) de a mbunti anumite tipuri de cutri. Aa cum s-a discutat pn acum, pentru sporirea
eficienei cutrilor unor valori n baza de date se folosesc de obicei arborii B*. Exist totui unele
cazuri n care acetia ngreuneaz accesul la date. De exemplu, presupunem c avem o coloan
indexat ce conine prenumele a mii de persoane. S presupunem de asemenea c n aceast coloan
exist mii de prenume ce ncep cu litera S. n momentul n care se dorete inserarea mai multor
nregistrri ce ncep cu litera S pot aprea trangulri ale operaiilor de citire/scriere deoarece
modificrile n index-ul asociat coloanei vor aprea n acelai nod al arborelui. Indecii cu cheie
invers sunt folosii tocmai n aceast situaie deoarece ei stocheaz datele n mod invers. Prin
urmare, prenumele SANDU va fi stocat tot ntr-un arbore B* ca UDNAS. Acest tip de index este
folositor numai n cazul cutrii n arbore a unor valori exacte.
Un index cu cheie invers se creeaz folosind comanda CREATE INDEX cu opiunea REVERSE, de
exemplu:
CREATE INDEX sal_prenume_ind ON salariat(prenume) REVERSE;
Un index obinuit se poate tranforma n index cu cheie invers folosind comanda ALTER INDEX
REBULD cu opiunea REVERSE. De exemplu:
ALTER INDEX sal_prenume_ind REBUILD REVERSE;
Index de tip bitmap
Un alt tip de index, introdus n Oracle8, este indexul de tip bitmap. ntr-un astfel de index, n loc de
a se stoca valorile propriu-zise ale coloanei indexate, indexul stocheaz un bitmap format pe baza
acestor valori. Cu alte cuvinte, indexul ine un bitmap pentru fiecare rnd, bitmap care conine un
bit pentru fiecare rnd din tabel. Bitul este 1 dac valoarea respectiv este coninut n acel rnd i 0
dac nu este. De exemplu, s presupunem c avem un index de tip bitmap creat pe baza coloanei
culoare dintr-un tabel masina, vezi figura 6.6.
Tabel masina
Nr_masina Marca
1
Ford Mondeo
2
Dacia Nova
3
Daewoo Cielo
4
Daewoo Tico
5
Ford Mondeo
6
Ford Mondeo
7
Dacia Nova
8
Dacia Nova
9
Daewoo Cielo
10
Ford Mondeo
11
Dacia Nova
12
Daewoo Tico

Culoare
Alb
negru
alb
verde
rou
albastru
alb
negru
verde
verde
verde
verde
134

13
14
15
16
17
18
19
29

Ford Mondeo
Dacia Nova
Daewoo Tico
Dacia Nova
Ford Mondeo
Daewoo Tico
Dacia Nova
Ford Mondeo

albastru
verde
albastru
verde
alb
negru
verde
verde

Index de tip bitmap pentru coloana culoare


Culoare = alb Culoare = negru Culoare = verde
1
0
0
0
1
0
1
0
0
0
0
1
0
0
0
0
0
0
1
0
0
0
1
0
0
0
1
0
0
1
0
0
1
0
0
1
0
0
0
0
0
1
0
0
0
0
0
1
1
0
0
0
1
0
0
0
1
0
0
1
Figura 6.6

Culoare = albastru
0
0
0
0
0
1
0
0
0
0
0
0
1
0
1
0
0
0
0
0

Culoare = rou
0
0
0
0
1
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0

n acest exemplu, coloana culoare poate avea numai cinci valori: alb, negru, rou, verde,
albastru, iar n tabel sunt 20 de rnduri. Bitmap-ul corespunztor fiecrei culori va avea 20 de bii,
fiecare dintre acetia avnd valoarea 1 cnd maina va avea culoarea respectiv i 0 n caz contrar.
Deci bitmap-ul corespunztor culorii alb va avea 1 pe poziiile 1, 3, 7, 17, cel corespunztor culorii
negru va avea 1 pe poziiile 2, 8, 18, etc. De exemplu, pentru aflarea numrului de maini albe se va
executa interogarea:
SELECT COUNT(*) FROM masina
WHERE culoare = alb;
Un index de tip bitmap poate procesa foarte eficient o astfel de interogare prin simpla numrare a
valorilor 1 din bitmap-ul corespunztor valorii alb.
Un index de tip bitmap se creeaz folosind comanda CREATE INDEX cu opiunea BITMAP, de
exemplu:
CREATE BITMAP INDEX culoare_ind ON masina(culoare);

135

Spre deosebire de indecii tradiionali de tip arbore B*, folosirea indecilor de tip bitmap se
recomand atunci cnd:
numrul de valori distincte ale coloanei indexate este relativ mic (coloana are cardinalitate
mic); de exemplu, n cazul unei coloane ce conine starea civil sau sexul unei persoane.
majoritatea interogrilor conin combinaii multiple de condiii WHERE ce implic operatorul
OR.
n acest caz, indecii de tip bitmap pot avea o dimensiune mult mai mic dect indecii de tip
arbore B*. Pe de alt parte ns, indecii de tip bitmap sunt ineficieni n cazul unor coloane cu
numr mare de valori.
6.3.3 Tabele organizate pe baz de index
Tabelele organizate pe baz de index (index-organised tables) sunt o noutate adus de versiunea
Oracle 8. Un tabel organizat pe baz de index difer fa de un tabel obinuit prin faptul c datele
tabelului sunt stocate n indexul asociat. Ori de cte ori se vor face modificri asupra datelor din
tabel, precum adugarea de noi rnduri, modificarea sau tergerea rndurilor existente, se va
modifica doar indexul.
Mai exact, un tabel organizat pe baz de index este ca un tabel obinuit avnd un index de tip arbore
B* pe una sau mai multe coloane, dar n loc de a folosi spaii separate de stocare pentru tabel i
index, Oracle folosete doar un singur index de tip B*, care conine att valorile coloanelor
indexate, ct i valorile celorlalte coloane pentru rndul corespunztor. Deci, n loc ca fiecare
intrare a indexului s conin valoarea coloanei sau coloanelor indexate i valoarea ROWID pentru
rndul corespunztor, ea conine ntreg rndul. Coloana sau coloanele dup care se face indexarea
sunt cele care constituie cheia primar a tabelului. Din aceast cauz, tabelele organizate pe index
sunt eficiente pentru accesarea datelor prin intermediul cheii primare sau un prefix valid al acesteia.
Un tabel organizat pe baz de index poate fi manipulat de ctre aplicaii la fel ca un tabel obinuit,
folosind comenzi SQL. Diferena const n faptul c n cazul tabelului organizat pe baz de index,
toate operaiile sunt efectuate numai asupra indexului.
Urmtorul tabel rezum diferenele cele mai importante dintre un tabel obinuit i un tabel organizat
pe baz de index.
Tabel Obinuit
ROWID identific n mod unic un rnd;
specificarea cheii primare este opional.
Are coloana implicit ROWID.
Accesul la date se face prin intermediul ROWID.

Tabel organizat pe baza de index


Cheia primar identific n mod unic un rnd;
specificarea cheii primare este obligatorie.
Nu are coloana implicit ROWID.
Accesul la date se face prin intermediul cheii
primare.
Permite definirea de indeci pentru coloane care Nu permite definirea de indeci pentru coloane
nu fac parte din cheia primar.
care nu fac parte din cheia primar.
Permite definirea constrngerii UNIQUE i a Nu permite definirea constrngerii UNIQUE, dar
triggerelor.
permite definirea triggerelor.
Poate fi stocat ntr-un cluster coninnd alte Nu poate fi stocat ntr-un cluster coninnd alte
tabele.
tabele.
Poate fi partiionat.
Nu poate fi partiionat.
Principalele avantaje ale tabelelor organizate pe baza de index sunt urmtoarele:
Se reduce timpul de acces la date prin interogri care folosesc ca termen de comparaie coloanele
indexate

136

Se reduce spaiul de stocare datorit faptului ca nu mai este creat un index suplimentar pentru
cheia primar a tabelului.
6.3.4. Crearea tabelelor organizate pe baza de index
Pentru a crea un tabel organizat pe baz de index, se folosete comanda SQL CREATE TABLE cu
specificaia ORGANIZATION INDEX. La crearea unui tabel organizat pe baz de index, trebuie
neaprat specificat cheia primar a tabelului. n plus, se pot folosi clauzele OVERFLOW,
THRESHOLD i INCLUDING prezentate mai jos, care sunt opionale.
O intrare dintr-un index de tip arbore B* este de obicei destul de mic, constnd dintr-o pereche
(valoare indexat, ROWID). Pe de alt parte ns, ntr-un tabel organizat pe baz de index, intrrile
din indexul arborelui B* corespunztor pot fi foarte mari deoarece ele constau dintr-o pereche
(cheie_primar, coloane_secundare), adic un rnd ntreg. Dac acestea sunt foarte mari, se poate
ajunge la situaia n care fiecare nod frunz s conin doar un singur rnd sau o poriune de rnd,
distrugndu-se astfel densitatea indexului de tip arbore B*.
Pentru a evita aceast problem, la crearea unui tabel organizat pe index se poate folosi clauza
OVERFLOW, care specific un spaiu tabel de depire (OVERFLOW TABLESPACE). Alturi de
aceast clauz se mai poate specifica i o valoare de prag (PCTTHRESHOLD). Valoarea de prag este
specificat ca procent din mrimea unui bloc. Dac dimensiunea rndului depete valoarea de
prag specificat, atunci coloanele care nu fac parte din cheia primar pentru rndurile care depesc
valoarea de prag vor fi stocate n spaiul tabel de depire specificat. n acest caz, intrrile din index
vor conine perechea (cheie_primar, capt_rnd), unde capt_rnd conine partea de nceput a
restului de coloane; acesta este exact ca o poriune normal de rnd, cu excepia faptului c face
referin la poriunea rmas de rnd, care este stocat n spaiul tabel de depire. Dac nu este
specificat clauza OVERFLOW, atunci toate liniile care depesc valoarea de prag sunt eliminate
complet i nu mai sunt inserate n tabela organizat pe index.
Clauza INCLUDING, dac este specificat, determin coloana care va mpri tabelul n poriunea
de index i poriunea de depire. Fiecare coloan dup coloana INCLUDING este stocat n
poriunea de depire a tabelului organizat pe index.
Deci, sintaxa comenzii CREATE TABLE pentru un tabel organizat pe index este urmtoarea:
CREATE TABLE nume_tabel
(nume_coloana tip_data ... PRIMARY KEY ...)
ORGANIZATION INDEX
TABLESPACE spaiu_tabel
[PCTTHRESHOLD ntreg]
[INCLUDING nume_coloana]
[OVERFLOW TABLESPACE spaiu_tabel_depire]
CREATE TABLE carte
(serie
VARCHAR2(5),
numar
NUMBER(7),
titlu
VARCHAR2(20),
cod_autor
VARCHAR2(10),
editura
VARCHAR2(10),
descriere
VARCHAR2(200),
CONSTRAINT pk_carte PRIMARY KEY (serie, numar))
137

ORGANIZATION INDEXED
TABLESPACE ts_alfa
PCTTHRESHOLD 40
INCLUDING editura
OVERFLOW TABLESPACE ts_beta;

138

6.4 Clustere
6.4.1 Clusterul de index
Clusterul (grupul de tabele), uneori numit i clusterul de index, reprezint o metod opional de
stocare a datelor tabelelor. Tabelele care sunt accesate frecvent mpreun pot fi stocate fizic
mpreun n aceleai blocuri de date. Tabelele dintr-un grup sunt stocate mpreun pentru a reduce
numrul de operaii de I/O cu discul. Cu alte cuvinte, clusterul de index este o regrupare fizic a
dou sau mai multe tabele, relativ la una sau mai multe coloane, cu scopul creterii performanelor.
Cheia unui cluster este definit ca fiind coloana sau coloanele pe care tabelele grupate le au n
comun. Cheia unui cluster nu trebuie confundat cu cheia primar a tabelelor grupate. Cheia
clusterului poate fi i cheia unuia sau mai multora dintre tabelele grupate, dar acest lucru nu este
obligatoriu. Valorile cheii clusterului sunt stocate o singur dat n schem, reducndu-se astfel
spaiul de stocare necesar i procesrile suplimentare. Rndurile care au aceeai valoare pentru
cheia clusterului sunt stocate de ctre Oracle n acelai bloc de date.
Aa cum s-a discutat mai devreme, operaiile de I/O cu discul sunt efectuate de ctre Oracle la nivel
de bloc, nu la nivel de rnd; dac datele sunt stocate mpreun, ele vor fi copiate de pe disc n
memorie n cadrul aceluiai bloc. Cnd blocul de date este citit, sunt citite toate datele din tabelele
clusterului din blocul de date. Acest lucru poate reprezenta un avantaj real dac datele din tabelele
clusterului se folosesc mpreun n mod frecvent. De exemplu, folosirea clusterelor este benefic n
cazul jonciunilor pentru c toate datele sunt citite n cadrul aceleiai operaii de I/O. Dac clusterul
este ns utilizat pentru tabele actualizate sau terse n mod frecvent, se va nregistra o scdere a
performanelor.
Clusterul este un mecanism transparent aplicaiilor ce utilizeaz tabelele acestuia. Datele din tabele
sunt manipulate ca i cnd acestea ar fi stocate ntr-un tabel normal numai c n momentul
interogrii se va observa o cretere semnificativ a performanelor.
6.4.2 Crearea clusterului de index
Pentru a crea un tabel ntr-un cluster de index se parcurg n mod obligatoriu urmtorii pai:
1. Crearea clusterului de index
2. Adugarea tabelelor la cluster
3. Crearea indexului de cluster
Adugarea tabelelor la cluster se poate face i dup ce indexul de cluster a fost creat.
Crearea clusterului de index
Pentru crearea clusterelor de index se folosete comanda SQL CREATE CLUSTER n care trebuie
specificat coloana sau grupul de coloane dup care sunt grupate tabelele. O sintax simplificat a
comenzii CREATE CLUSTER este prezentat n continuare:
CREATE CLUSTER nume_cluster
(nume_coloan tip_dat [, nume_coloan tip_dat] ... )
[PCTFREE ntreg] [PCTUSED ntreg]
[SIZE ntreg]
[TABLESPACE spaiu_tabel]
[STORAGE parametrii_de_stocare]

139

unde clauza opional SIZE specific spaiul (n bytes, Kbytes sau Mbytes) folosit pentru a stoca
toate rndurile avnd aceeai valoare pentru cheia clusterului. Aceast valoare nu trebuie s
depeasc mrimea unui bloc de date. Dac se omite aceast opiune, Oracle rezerv un bloc de
date pentru fiecare valoarea a cheii.
Exemplul urmtor creeaz un cluster sal_dept, n care tabele sunt grupate dup coloanele
cod_dept i cod_tara.
CREATE CLUSTER sal_dept
(cod_dept NUMBER(10),
cod_tara NUMBER(10));
Adugarea tabelelor la cluster
Dup crearea clusterului, adugarea tabelelor la cluster se face folosind comanda CREATE TABLE
cu clauza CLUSTER:
CREATE TABLE nume_cluster
(nume_coloana tip_data ... [, nume_coloana tip_data ...] ... )
CLUSTER nume_cluster
CREATE TABLE departament
(cod_dept
NUMBER(10),
cod_tara
NUMBER(10),
nume_dept
VARCHAR2(10),
PRIMARY KEY(cod_dept, cod_tara))
CLUSTER sal_dept(cod_dept, cod_tara);
CREATE TABLE salariat
(cod_salariat NUMBER(10) PRIMARY KEY,
nume
VARCHAR2(10)
NOT NULL,
prenume
VARCHAR2(10),
data_nastere DATE,
salariu
NUMBER(10),
cod_dept
NUMBER(10),
cod_tara
NUMBER(10),
FOREIGN KEY(cod_dept, cod_tara)
REFERENCES
departament(cod_dept, cod_tara))
CLUSTER sal_dept(cod_dept, cod_tara);
Datorit faptului c tabelele clusterului folosesc alocarea de spaiu a acestuia, la folosirea comenzii
CREATE TABLE cu opiunea CLUSTER nu trebuie specificai parametrii PCTFREE, PCTUSED
i nici opiunea TABLESPACE sau parametrii de stocare.
Nu se poate asocia un cluster pentru un tabel care exist deja. Dac se dorete totui acest lucru, se
creeaz un nou tabel ce va fi grupat n cluster i care va conine nregistrrile tabelului existent
(folosind opiunea AS SELECT). Tabelul vechi se terge iar cel nou va fi redenumit cu numele
celui vechi.
Index de cluster

140

Pentru coloanele cheie ale clusterului trebuie creat n mod explicit un index de cluster (index de
grup). Indexul este utilizat pentru localizarea univoc a liniilor. Indexul de cluster trebuie creat
naintea efecturii oricrei operaii de interogare sau DML asupra clusterului. Deci, indexul de
cluster trebuie creat nainte de ncrcarea datelor n tabelele clusterului; n absena indexului,
tabelele nu pot fi utilizate.
Pentru a localiza un rnd dintr-un cluster, nti este folosit indexul de cluster pentru a gsi valoarea
cheii clusterului, care face referire la blocul de date asociat.
Spre deosebire de un index de tip arbore B*, un index de cluster include i valorile nule ale cheii. n
plus, fiecare element din indexul de cluster conine o intrare pentru fiecare valoare a cheii, i nu o
intrare pentru fiecare rnd, ca un index de tip B* obinuit.
Pentru crearea unui index de cluster se folosete comanda SQL CREATE INDEX cu opiunea ON
CLUSTER:
CREATE INDEX nume_index
ON CLUSTER nume_cluster
[TABLESPACE spaiu_tabel]
[STORAGE parametrii_de_stocare]
[PCTFREE ntreg]
Urmtoarea comanda SQL creeaz indexul pentru clusterul sal_dept:
CREATE INDEX sal_dept_ind
ON CLUSTER sal_dept;
6.4.3. Clusterul hash
Un alt tip de cluster pe care l ofer Oracle este clusterul hash. Spre deosebire de clusterul obinuit,
pentru a accesa o nregistrare, clusterul hash nu folosete un index, ci o funcie numeric, numit
funcia hash. Aceast funcie are ca parametru cheia clusterului i returneaz o anumit valoare
numit valoare hash. Valoarea hash corespunde blocului de date din cluster pe care Oracle l va citi
sau l va scrie pe baza comenzii executate. De exemplu n momentul n care un rnd este inserat n
tabel, acesta va fi stocat n funcie de valoarea hash asociat. Numrul de valori hash este specificat
atunci cnd se creeaz clusterul. Deci, ntr-un cluster hash, rndurile care au aceeai valoare hash
sunt depozitate mpreun pentru a activa accesul rapid.
De exemplu, considerm un sistem de plat a telefonului n care un anumit tabel depoziteaz
informaii despre numrul de telefon al fiecrui client, durata apelurilor efectuate, precum i data
fiecrei convorbiri. Dac regulile de plat indic faptul c toate apelurile efectuate de un client ntro anumit lun vor fi facturate mpreun, putei depozita aceste apeluri ntr-un cluster hash a crui
cheie este format din coloanele ce conin numrul telefonului, anul i luna n care a avut loc
convorbirea. n momentul n care acest tabel va fi interogat n vederea ntocmirii facturii lunare, se
va observa o cretere semnificativ a performanelor.
Un cluster hash poate fi folosit pentru a stoca unul sau mai multe tabele. Ca i n cazul unui cluster
de index, pentru clusterul hash cheia poate fi alctuit din una sau mai multe coloane.
Folosirea clusterelor hash se recomand n special pentru tabele statice (ale cror date nu se
modific prea mult n timp) i care sunt interogate frecvent cu condiii de filtrare ce sunt egaliti
care conin cheia clusterului.
141

Pentru a gsi sau stoca un rnd ntr-un tabel indexat sau ntr-un cluster obinuit sunt necesare cel
puin dou operaii de I/O (de obicei chiar mai multe): una sau mai multe pentru a afla sau stoca
valoarea cheii i alta pentru a citi sau scrie rndul n tabel sau cluster. n contrast, Oracle folosete
funcia hash pentru a localiza rndul ntr-un cluster hash (pentru aceasta nu este necesar nici o
operaie de I/O). Ca rezultat, pentru a citi sau a scrie un rnd ntr-un cluster hash este necesar doar
o operaie de I/O.
6.4.4 Crearea clusterului hash
Pentru a crea un cluster hash se parcurg urmtorii pai:
1. Crearea clusterului hash
2. Adugarea tabelului la cluster
Crearea clusterului hash
Pentru crearea clusterelor hash se folosete comanda SQL CREATE CLUSTER cu clauza
HASHKEYS. O sintax simplificat a acestei comenzi este prezentat n continuare:
CREATE CLUSTER nume_cluster
(nume_coloan tip_dat [, nume_coloan tip_dat} ... )
HASHKEYS ntreg
[HASH IS expresie]
[SIZE ntreg]
[PCTFREE ntreg] [PCTUSED ntreg]
[TABLESPACE spaiu_tabel]
[STORAGE parametrii_de_stocare]
unde:
Clauza HASHKEYS specific faptul c clusterul ce urmeaz a fi creat este de tip hash i
furnizeaz numrul de valori hash distincte ce pot fi returnate de funcia hash. Valoarea minim
a numrului de valori distincte este 2. De fapt Oracle rotunjete numrul specificat n aceast
clauz la primul numr prim mai mare dect valoarea specificat. De exemplu, dac acest numr
furnizat de clauza HASHKEYS este 100, nseamn c pentru orice valoare pe care o are cheia
clusterului funcia hash va returna o valoare ntre 0 i 100 (adic vor fi 101 valori hash). Dac
clauza HASHKEY lipsete Oracle va crea implicit un cluster de index.
HASH IS specific o expresie ce va fi utilizat de funcia hash a clusterului. Funcia hash va
reprezenta restul mpririi valorii aceste expresii la valoarea specificat de HASHKEYS
(expresie MOD valori_hash). Valorile expresiei specificate trebuie s fie valori numerice fr
zecimale (ntregi) i uniform distribuite pe domeniul acesteia. Dac acest lucru nu este posibil,
atunci clauza HASH IS nu trebuie folosit, caz n care Oracle va folosi implicit o funcie hash
intern. De obicei acesta clauz se folosete atunci cnd cheia clusterului este format dintr-o
singur coloan care ia valori ntregi uniform distribuite (vezi exemplul de mai jos).
SIZE specific spaiul (n bytes, Kbytes sau Mbytes) folosit pentru a stoca toate rndurile avnd
aceeai valoare pentru funcia hash. Aceast valoare nu trebuie s depeasc mrimea unui bloc
de date. De exemplu, dac spaiul disponibil dintr-un bloc este de 1700 bytes iar valoarea
specificat de SIZE este de 500 bytes, atunci unui bloc i vor reveni 3 valori hash. Dac se
omite aceast opiune, Oracle rezerv un bloc de date pentru fiecare valoarea a funciei hash.
CREATE CLUSTER test_cls(cod NUMBER(5))
HASHKEYS 1000
HASH IS cod
142

SIZE 500;
Adugarea tabelului la cluster
Dup crearea clusterului hash, adugarea tabelului sau tabelelor la cluster se face folosind comanda
CREATE TABLE cu clauza CLUSTER. Aceast operaie este identic cu operaia de adugare unui
tabel la un cluster de index, de aceea nu necesit lmuriri suplimentare.
CREATE TABLE test
(cod NUMBER(5) PRIMARY KEY,
..)
CLUSTER test_cls(cod);
6.4.5 Modificarea clusterelor
Comanda ALTER CLUSTER poate fi folosit pentru a modifica parametrii de stocare ai clusterului
(PCTFREE, PCTUSED i parametrii din clauza STORAGE). Tot cu aceast comand se poate
realiza alocarea i dealocarea spaiului aferent unui cluster. n cazul unui cluster hash nu se poate
schimba valoarea parametrului SIZE, precum i HASH IS sau HASHKEY. Comanda ALTER
CLUSTER urmeaz aceeai sintax ca i n cazul modificrii tabelelor.
6.4.6 Distrugerea clusterelor
Pentru distrugerea unui cluster se folosete comanda SQL DROP CLUSTER:
DROP CLUSTER sal_dept;
Totui, folosind comanda de mai sus clusterul nu poate fi distrus dac exist tabele n el. Pentru a
permite acest lucru se folosete clauza opional INCLUDING TABLES:
DROP CLUSTER sal_dept
INCLUDING TABLES;
n plus, dac exist tabele din afara clusterului care conin restricii de integritate care se refer la
chei din tabele clusterului, acestea trebuie de asemenea eliminate. Pentru acest lucru se folosete
clauza opional CASCADE CONSTRAINTS;
DROP CLUSTER sal_dept
INCLUDING TABLES CASCADE CONSTRAINTS;

143

6.5 Secvene
De multe ori este necesar crearea unei secvene de numere pentru a fi folosite ca valori ale cheii
unui tabel, de exemplu coloana cod_salariat din tabelul salariat. n loc de a genera aceste
numere manual, Oracle ofer o facilitate pentru generarea unei astfel de secvene n mod automat.
Pentru a crea manual o secven de numere, ar fi necesar blocarea rndului care conine ultima
valoare a secvenei (pentru a evita preluarea acestei valori de mai multe ori) generarea noii valori i
apoi deblocarea rndului. Blocarea acestor rnduri poate fi evitat prin folosirea generatorului de
secvene furnizat de Oracle. Acesta poate genera secvene de numere de pn la 38 de digii, fr a
fi necesar blocarea manual a rndurilor. Secvenele sunt memorate i generate indiferent de
tabele. Prin urmare, aceeai secven poate fi utilizat pentru mai multe tabele. O secven este
practic un obiect al bazei de date care servete la generarea unor numere ntregi unice care poate fi
folosit simultan de mai muli utilizatori, evitnd apariia conflictelor i a blocrii. Ca orice alt
obiect al bazei de date, o secven poate fi creat, modificat sau distrus. Oracle stocheaz
definiiile secvenelor n dicionarul de date.
6.5.1 Crearea, modificarea i distrugerea secvenelor.
Pentru a crea o secven se folosete comanda SQL CREATE SEQUENCE, avnd urmtoarea
sintax:
CREATE SEQUENCE nume_secven
[INCREMENT BY ntreg]
[START WITH ntreg]
[MAXVALUE ntreg | NOMAXVALUE]
[MINVALUE ntreg | NOMINVALUE]
[CYCLE | NOCYCLE]
[CACHE ntreg | NOCACHE]
[ORDER | NOORDER]
unde
INCREMENT BY specific intervalul dintre dou numere ale secvenei. Aceasta poate fi orice
valoare pozitiv sau negativ, dar nu poate fi 0. Dac valoarea este pozitiv atunci secvena este
n ordine descresctoare, dac este pozitiv, atunci secvena este n ordine cresctoare. Valoarea
implicit (default) este 1.
START WITH specific prima valoare generat de secven. Aceast opiune poate fi folosit
pentru a ncepe o secven cresctoare cu o valoare mai mare dect valoarea sa minim sau
pentru a ncepe o secven descresctoare cu o valoare mai mic dect valoarea sa maxim.
Pentru secvene cresctoare valoarea implicit este valoarea minim a secvenei, iar pentru
secvene descresctoare valoarea implicit este valoarea maxim a secvenei.
MINVALUE specific valoarea minim a secvenei. NOMINVALUE specific o valoare minim
de 1 pentru o secven cresctoare sau -10 pentru o secven descresctoare. NOMINVALUE este
valoarea implicit.
MAXVALUE specific valoarea maxim a secvenei. NOMAXVALUE specific o valoare maxim
de 10 pentru o secven descresctoare i 1027 pentru o secven cresctoare. NOMAXVALUE
este valoarea implicit.
CYCLE arat c secvena continu s genereze valori i dup ce a atins valoarea maxim (n
cazul secvenelor cresctoare) sau valoarea minim (n cazul secvenelor descresctoare). n
acest caz, dup ce o secven cresctoare a atins valoarea maxim, ea va genera valoarea sa
minim; dup ce o secven descresctoare a atins valoarea minim, ea va genera valoarea sa
144

maxim. NOCYCLE arat c secvena nu mai poate genera valori dup ce a atins valoarea
maxim (n cazul secvenelor cresctoare) sau valoarea minim (n cazul secvenelor
descresctoare). Valoarea implicit este NOCYCLE.
CACHE arat cte valori ale secvenei sunt prealocate de ctre Oracle i inute n memorie
pentru acces mai rapid. Valoarea minim a acestui parametru este 2. NOCACHE arat ca nu
exist valori prealocate ale secvenei. Dac se omit amndou opiunile, CACHE i NOCACHE,
Oracle prealoc implicit 20 de valori.
Urmtorul exemplu creeaz secvena sal_seq:
CREATE SEQUENCE sal_seq
INCREMENT BY 1
START WITH 1
NOMAXVALUE
NOCYCLE
CACHE 10;
Fiecare dintre parametrii specificai la crearea unei secvene pot fi modificai prin executarea
comenzii SQL ALTER SEQUENCE:
ALTER SEQUENCE sal_seq
MAXVALUE 100000
CYCLE
CACHE 20;
O secven poate fi distrus folosind comanda SQL DROP SEQUENCE:
DROP SEQUENCE sal_seq;
6.5.2 Utilizarea secvenelor
Dup definirea unei secvene, aceasta poate fi utilizat i incrementat de mai muli utilizatori.
Oracle nu ateapt ncheierea unei tranzacii care acceseaz secvena pentru a permite utilizarea ei
de ctre un alt utilizator.
O secven poate fi referit ntr-o comand SQL cu ajutorul pseudo-coloanelor NEXTVAL i
CURRVAL, sub forma nume_secventa.NEXT_VAL i respectiv nume_secventa.CURRVAL.
Valoarea urmtoare este generat de pseudo-coloana NEXTVAL, n timp ce valoarea curent este
repetat la folosirea pseudo-coloanei CURRVAL.
n exemplul urmtor, secvena sal_seq este folosit pentru a insera o noua linie n tabelul
salariat:
INSERT INTO salariat (cod_salariat, nume, prenume, data_nastere)
VALUES (sal_seq.NEXTVAL, 'Georgescu', 'Vasile', '11-MAY-69');
La generarea unui nou numr din secven, acesta este disponibil numai sesiunii care l-a creat.
Orice alt sesiune care folosete aceeai secven va obine o nou valoare din secven - evident,
tot prin intermediul pseudo-coloanei NEXTVAL.

145

Pentru a utiliza valoarea curent a secvenei n sesiunea curent de lucru se folosete pseudocoloana CURRVAL. Valoarea CURRVAL este disponibil numai dac NEXTVAL a fost folosit n
sesiunea curent - n caz contrar ncercarea de a folosi pseudo-coloana CURRVAL va produce o
eroare. De exemplu, s presupunem c i generarea de valori pentru coloana cod_dept din tabelul
departament se face prin intermediul unei secvene dept_seq. Atunci, urmtoarele comenzi
SQL vor insera dou departamente i cte doi salariai pentru fiecare departament:
INSERT INTO departament (cod_dept, cod_tara, nume_dept)
VALUES (dept_seq.NEXTVAL, 40, 'Proiectare');
INSERT INTO salariat (cod_salariat, nume, prenume, data_nastere,
cod_dept, cod_tara)
VALUES
(sal_seq.NEXTVAL,
'Vasilescu',
'Costel',
'17-MAY-70',
dept_seq.CURRVAL, 40);
INSERT INTO salariat (cod_salariat, nume, prenume, data_nastere,
cod_dept, cod_tara)
VALUES
(sal_seq.NEXTVAL,
'Popescu',
'Vasile',
'17-JUN-72',
dept_seq.CURRVAL, 40);
INSERT INTO departament (cod_dept, cod_tara, nume_dept)
VALUES (dept_seq.NEXTVAL, 40, 'Vanzari');
INSERT INTO salariat (cod_salariat, nume, prenume, data_nastere,
cod_dept, cod_tara)
VALUES
(sal_seq.NEXTVAL,
'Ionescu',
'Gheorghe',
'12-MAY-71',
dept_seq.CURRVAL, 40);
INSERT INTO salariat (cod_salariat, nume, prenume, data_nastere,
cod_dept, cod_tara)
values (sal_seq.NEXTVAL, 'Diaconescu', 'Marian', '15-MAY-57',
dept_seq.CURRVAL, 40);
CURRVAL i NEXTVAL pot fi folosite n urmtoarele locuri:
clauza VALUES a unei comenzi INSERT, ca n exemplul de mai sus.
clauza SET a unei comenzi UPDATE, ca n exemplul de mai jos:
UPDATE salariat
SET cod_salariat = sal_seq.NEXTVAL
WHERE cod_salariat = 7;
lista unei comenzi SELECT, ca n exemplul de mai jos:
SELECT sal_seq.NEXTVAL
FROM dual;
Nota: In PL/SQL, pentru a atribui unei variabile valorile NEXTVAL sau CURRVAL se folosete o
comanda SELECT de forma:
SELECT sal_seq.NEXTVAL
INTO sal_var
FROM DUAL

146

CURRVAL i NEXTVAL nu pot fi folosite n urmtoarele locuri:


o subinterogare;
interogarea unei vederi sau a unui instantaneu;
o comand SELECT cu operatorul DISTINCT;
o comand SELECT cu clauza GROUP BY sau ORDER BY;
o comand SELECT care este combinat cu alt comand SELECT printr-un operator de
mulime (UNION, INTERSECT, MINUS);
clauza WHERE a unei comenzi SELECT;
valoarea DEFAULT a unei coloane ntr-o comand CREATE TABLE sau ALTER TABLE;
condiia unei constrngeri CHECK.
Atunci cnd un numr este generat de ctre o secven, aceasta este incrementat indiferent dac
tranzacia a fost actualizat permanent (commited) sau derulat napoi (rolled back). Dac doi sau
mai muli utilizatori incrementeaz aceeai secven n mod concurent, numerele generate la cererea
unuia dintre ei pot s nu fie consecutive deoarece ntre timp au putut fi generate alte valori la
cererea celorlali utilizatori. Un utilizator nu poate avea niciodat acces la un numr generat de o
secven la cererea unui alt utilizator. n plus, un utilizator nu poate tii dac dac un alt utilizator
genereaz numere folosind aceeai secven. Dac numerele generate de ctre o secven sunt
folosite la popularea unui cmp, este posibil ca valorile din acel cmp s nu fie numere consecutive
n cazul cnd o tranzacie a fost derulat napoi. De exemplu, dac valoarea CURRVAL este 10 n
cazul secvenei sal_seq de mai sus, acest lucru nu implic neaprat faptul c tabelul salariat
conine 10 nregistrri.
6.6 Sinonime
Un sinonim este un obiect care face referire la un alt obiect din baza de date, cu alte cuvinte un alias
al acestuia. Cu alte cuvinte, Oracle ofer posibilitatea de a atribui mai multe nume aceluiai obiect.
n Oracle se pot crea sinonime pentru tabele, vederi, instantanee, secvene, funcii, proceduri sau
pachete din baza de date sau chiar pentru alte sinonime din baza de date. Deoarece un sinonim este
doar un alias, el nu necesit nici un spaiu de stocare, n afara de definiia sa din dicionarul bazei de
date.
Sinonimele sunt folosite de obicei pentru a permite unui utilizator s foloseasc obiecte din schema
altui utilizator, fr a specifica proprietarul acestora. Cnd un utilizator folosete un sinonim, acesta
trebuie s cunoasc doar numele sinonimului, nu i proprietarul sau numele obiectului referit de
sinonim. Sinonimele sunt mecanisme puternice prin intermediul crora se realizeaz independena
unui obiect al bazei de date fa de utilizatorul care este proprietarul su.
Un sinonim este de dou feluri: public sau privat. Un sinonim public este proprietatea grupului
special de utilizatori numit PUBLIC i poate fi folosit de ctre toi utilizatorii bazei de date. Un
sinonim privat este proprietatea numai a unui utilizator, putnd fi accesat la fel ca orice obiect din
schema acestuia. Pe de alt parte, trebuie reinut c definirea unui sinonim, fie el public sau privat,
nu implic accesul la obiectul referit de acesta de ctre ali utilizatori. Pentru a accesa respectivul
obiect, utilizatorul trebuie s posede privilegiile adecvate pentru accesarea obiectului.
6.6.1 Crearea, modificarea i distrugerea sinonimelor.
Pentru a crea un sinonim se folosete comanda SQL create synonym, avnd sintaxa:
CREATE [PUBLIC] SYNONYM [schema.]nume_sinonim
147

FOR [schema.]obiect
Dac se specific opiunea PUBLIC, atunci sinonimul creat este public, altfel sinonimul este privat.
Pentru a nelege cum funcioneaz sinonimele, s considerm, de exemplu c tabelul salariat
aparine schemei utilizatorului costica i c un al utilizator, mitica, creeaz un sinonim
public, sal1, i un sinonim privat, sal2, pentru acesta:
CREATE PUBLIC SYNONYM sal1 FOR costica.salariat;
CREATE SYNONYM sal2 FOR costica.salariat;
Atunci, pentru a vizualiza toate datele din tabela salariat, orice utilizator poate folosi
urmtoarea comand SQL:
SELECT * FROM sal1;
n schimb, doar utilizatorul mitica poate folosi comanda SQL de mai jos pentru a vizualiza datele
din tabelul salariat - aceasta deoarece sal2 face parte din schema acestui utilizator.
SELECT * FROM sal2;
n plus, aa cum s-a menionat mai devreme, pentru a putea executa comenzile de mai sus,
utilizatorii respectivi trebuie s posede privilegiul SELECT pe tabelul de baz salariat.
Numele atribuite sinonimelor pot fi aceleai cu ale obiectelor de baz (bineneles, cu excepia
situaiei cnd sinonimul este privat i aparine aceleiai scheme ca i obiectul de baz).
Pentru a distruge un sinonim din baza de date se folosete comanda:
DROP [PUBLIC] SYNONYM [schema.]nume_sinonim
De exemplu:
DROP PUBLIC SYNONYM sal1;
DROP SYNONYM sal2
6.7 Proceduri, funcii i pachete stocate.
Dup cum vom vedea n capitolul 9, n PL/SQL se pot defini subprograme, acestea fiind blocuri
PL/SQL crora li se pot transmite parametrii i care pot fi apoi apelate. Exist dou feluri de
subprograme PL/SQL: proceduri i funcii. Funciile returneaz n mod explicit un parametru, pe
cnd procedurile nu returneaz n mod explicit nici un parametru.
Subprogramele pot fi definite de orice utilitar Oracle care folosete limbajul PL/SQL. Utilitare
precum Forms i Reports pot stoca aceste subprograme local, n acest caz ele fiind accesibile numai
aplicaiei i utilitarului respectiv. Pentru ca aceste subprograme s poat fi folosite de orice utilitar
Oracle, ele trebuie stocate n baza de date. Astfel de proceduri sau funcii se numesc proceduri sau
funcii stocate. Odat ce sunt compilate i stocate n dicionarul de date, procedurile i funciile
devin obiecte ale bazei de date care pot fi accesate de orice numr de aplicaii conectate la acea baz
de date.
148

Un pachet este un obiect care grupeaz mai multe tipuri, obiecte i subprograme PL/SQL. n mod
similar cu procedurile i funciile de sine stttoare, pentru ca un pachet s poat fi utilizat de orice
utilitar sau aplicaie Oracle, este necesar ca acesta s fie stocat n baza de date dup ce a fost n
prealabil compilat. Astfel de pachete se numesc pachete stocate.
Pachetele, procedurile i funciile stocate sunt prezentate pe larg n capitolul 9, seciunile 9.14 i
9.15
6.8. Declanatoare ale bazei de date
Un trigger (declanator) al bazei de date este un bloc PL/SQL stocat n baza de date, care este
asociat unui tabel. Diferena dintre un trigger i o procedur stocat const n faptul c triggerul este
executat n mod implicit ori de cte ori asupra tabelului este lansat o anumit comand DML
(INSERT, UPDATE sau DELETE). O noutate adus de versiunea Oracle8 sunt triggerele INSTEAD
OF. Acestea se execut n locul instruciunilor DML efectuate asupra unei vederi, furniznd astfel o
modalitate de a actualiza vederi ce nu pot fi actualizate direct prin comenzi SQL.
Triggerele bazei de date sunt prezentate pe larg n seciunea 9.16.
6.9 Instantanee
Conceptul de instantaneu (snapshot) este strns legat de conceptele de baz de date distribuit i
replicarea unei baze de date. O baz de date distribuit este o colecie de baze de date stocate
fiecare pe calculatoare diferite dar care la nivelul unei aplicaii sunt vzute ca o baz de date
singular. Practic pe fiecare calculator exist un server Oracle care gestioneaz baza de date local
dar coopereaz i la meninerea consistenei datelor din celelalte baze de date situate la distan,
asigurnd astfel funcionarea unei baze de date distribuite. Prin urmare o aplicaie poate accesa i
modifica prin intermediul unei reete datele coninute n mai multe baze de date, acestea fiind
vzute ca o baz de date singular ce are proprietatea de a avea datele distribuite pe mai multe
calculatoare. Replicarea unei baze de date reprezint facilitatea de a putea copia datele dintr-o baz
de date n locaii multiple i sisteme situate la distan. Aceste date pot fi modificate i accesate
numai n anumite mprejurri. Replicarea unei baze de date poate fi fcut la nivelul ntregii baze de
date sau la nivelul unor anumite tabele. Replicarea constituie o modalitatea foarte folosit de a spori
performanele unei baze de date distribuite, minimiznd traficul prin reea. Exist mai multe opiuni
de replicare a unei baze de date dar opiunea de baz o reprezint folosirea instantaneelor.
Instantaneul este un tabel care conine rezultatele unei interogri asupra unuia sau mai multor tabele
care n general se regsesc ntr-o baz de date situat la distan. Tabelele coninute n interogare se
mai numesc i tabele master iar baza de date ce conine aceste tabele se numete baz de date
master. Interogarea pe care se bazeaz instantaneul nu poate conine tabele sau vederi care au ca
proprietar userul SYS.
Instantaneul reprezint n esen o imagine static a datelor, de unde i numele de instantaneu.
Practic, instantaneul este o copie local a unei baze de date situate la distan i este utilizat n
contextul bazelor de date distribuite. Existnd aceste copii locale a datelor, baza de date nu trebuie
s transmit date prin intermediul reelei n mod repetat, reducnd n acest fel traficul n reea i
mbuntind performanele aplicaiei. n plus, instantaneul protejeaz mpotriva pierderii accesului
la baza de date situat la distan i d posibilitatea de a continua lucrul indiferent de starea reelei.
Instantaneele ofer avantaje n cazul n care tabelele master sunt:
actualizate rar dar interogate masiv;
149

interogate de mai muli utilizatori situai la distan.

Exist dou tipuri de instantanee: simple i complexe. Un instantaneu simplu este un instantaneu a
crui interogare de definire este realizat astfel nct fiecare rnd din instantaneu corespunde cu un
rnd sau o parte de rnd din tabelul master. n mod specific, interogarea unui instantaneu simplu nu
poate conine urmtoarele elemente:
- clauza GROUP BY sau CONNECT BY;
- funcii de grup sau operatorul DISTINCT
- operatori de mulimi (UNION, UNION ALL, INTERSECT, MINUS).
- jonciuni, cu excepia subinterogrilor permise (care nu conin elementele de mai sus);
Instantaneele simple pot conine subinterogri n interogarea prin care sunt definite (cu excepia
celor nepermise) deoarece, practic, subinterogarea filtreaz anumite nregistrri selectate de
interogarea bazat pe un singur tabel master. Acest lucru nu implic obligativitatea subinterogrii de
a se baza pe acelai tabel master pe care se bazeaz interogarea principal.
Dac un instantaneu conine unul din elementele enumerate de mai sus atunci acesta este un
instantaneu complex. mprosptarea unui instantaneu simplu este mai eficient dect n cazul unui
instantaneu complex ns n momentul interogrii instantaneele complexe sunt mai eficiente dect
cele simple.
Din punctul de vedere al unui utilizator un instantaneu este considerat drept un singur obiect ns n
reprezentarea intern a serverului Oracle acesta este vzut ca o colecie de obiecte. Obiectele create
se afl n baza de date local sau n baza de date situat la distan localizate n cadrul schemei unde
a fost creat instantaneul. Prin urmare n momentul crerii unui instantaneu se vor crea urmtoarele
obiecte:
n baza de date situat la distan, un tabel de baz denumit SNAP$_numeinstantaneu,
tabel care va conine rezultatele interogrii;
pentru cheia primar a acestui tabelului de mai sus va fi creat un index.;
pentru fiecare instantaneu, Oracle creeaz o vedere ce va avea acelai nume ca i instantaneul;
aceast vedere va furniza accesul read-only la instantaneu;
pentru anumite tipuri de instantanee vor fi creai indeci adiionali.
6.9.1. Remprosptarea instantaneelor
Datele dintr-un instantaneu nu sunt neaprat identice cu datele curente din tabelele master. Un
instantaneu reflect datele din tabelele master la un anumit moment. Datele dintr-un instantaneu nu
pot fi actualizate deoarece un instantaneu este un tabel read-only. Dac datele din tabelele master se
modific, instantaneul nu va reflecta aceste modificri pn cnd nu este remprosptat (refresh). n
acest sens existena instantaneelor prezint i unele dezavantaje. Pentru fiecare instantaneu serverul
Oracle trebuie s efectueze procesri suplimentare care s remprospteze periodic datele. Pe lng
toate acestea se adaug o cretere a necesarului de spaiu de stocare datorit prezenei
instantaneului. Prin urmare, trebuie inut cont de faptul c utilizarea instantaneelor poate duce la
mbuntirea sau la scderea performanelor sistemului.
n cazul unui instantaneu, utilizatorul trebuie s decid cnd i cum s aib loc fiecare operaiune de
mprosptare a acestuia. De exemplu, dac tabelul master pe care se bazeaz un instantaneu este
actualizat frecvent atunci este necesar ca procesul de mprosptare s aib loc n mod frecvent. Cu
alte cuvinte trebuiesc analizate cu atenie caracteristicile i cerinele unei aplicaii pentru a
determina intervalele de timp la care trebuie s aib loc mprosptarea unui instantaneu. Pentru a se
pstra integritatea referenial i consistena tranzaciilor n cazul instantaneelor ce se bazeaz de
tabele master cu legturi ntre ele, Oracle organizeaz i remprospteaz instantaneele ca parte a

150

unui grup. Crearea unui grup de remprosptare pentru instantanee se face folosind procedura
DBMS_REFRESH.MAKE().

Remprosptarea unui instantaneu se poate face n dou moduri:


manual prin folosirea procedurii DBMS_SNAPSHOT.REFRESH()
automat prin specificarea modului i a intervalului la care are loc mprosptarea n momentul
crerii instantaneului. Acest lucru se realizeaz folosind clauza REFRESH a comenzii CREATE
SNAPSHOT.
n cazul n care remprosptarea unui instantaneu este fcut n mod automat trebuie specificat
momentul de timp la care se va face prima remprosptare precum i dup ct timp se va repeta
aceast operaiune. La rndul ei, mprosptarea automat a unui instantaneu se poate face n dou
moduri: complet sau rapid (fast).
Remprosptarea complet
Pentru a realiza o mprosptare complet serverul va gestiona executarea interogrii instantaneului.
Rezultatul acestei execuii va nlocui datele existente i astfel se va realiza practic mprosptarea
instantaneului. mprosptarea complet poate fi fcut pentru orice tip de instantaneu.
Remprosptarea rapid
Pentru a realiza o mprosptare rapid, serverul ce gestioneaz instantaneul identific mai nti
schimbrile care au avut loc n tabela master din momentul n care a avut loc ultima mprosptare i
pn n prezent iar apoi efectueaz aceste modificri i n instantaneu. mprosptrile rapide sunt
mult mai eficiente dect cele complete n cazul n care modificrile fcute n tabelele master sunt
puine. mprosptarea rapid nu poate fi disponibil pentru un instantaneu dect dac tabelul master
are asociat un jurnal al instantaneului.
Jurnalul unui instantaneu este practic un tabel asociat tabelului master pe care se bazeaz
instantaneul i conine evidena modificrilor datelor din tabelul master. Acest jurnal al
instantaneului stocheaz cheia primar, data calendaristic i ora modificrii iar n mod opional
poate conine i identificatorul de rnd ROWID al acelor nregistrri care au suferit anumite
schimbri ale datelor. Jurnalul unui instantaneu nu poate fi folosit dect n cazul unui instantaneu
simplu i se poate crea cu ajutorul comenzii CREATE SNAPSHOT LOG. Numele unui jurnal este de
forma MLOG$_nume_tabel_master i este localizat n baza de date de la distan, n aceeai
schem ca i tabelul master pe care se bazeaz instantaneul. Dac exist mai multe instantanee
simple create prin interogarea aceluiai tabel, toate aceste instantanee vor utiliza n comun acelai
jurnal de instantaneu. Datorit faptului c jurnalul unui instantaneu nu poate fi folosit dect n cazul
unui instantaneu simplu, mprosptarea rapid nu se poate aplica dect acestui tip de instantaneu.
Totodat remprosptarea rapid nu poate avea loc dect dac jurnalul instantaneului a fost creat
nainte de crearea sau de ultima remprosptare a instantaneului.
Pentru un instantaneu se pot specifica segmentele de rollback ce vor fi folosite n nodul local sau n
nodul situat la distan n timpul unei mprosptri. ncepnd cu versiunea Oracle8, instantaneele
pot fi partiionate n acelai mod ca tabelele pentru c n esen ele sunt de fapt tabele.
Un instantaneu creat n versiunea Oracle8 este n mod implicit un instantaneu de tip cheie primar,
deoarece un instantaneu identific rndurile din tabelul master n funcie de cheia primar a
acestuia. Pentru compatibilitatea cu versiunile anterioare Oracle8 suport i instantanee de tip

151

ROWID. Pentru mai multe informaii vezi documentaia Oracle [26] [Oracle Documentation]/
Oracle8 Database/ Oracle8 Replication.
6.9.1 Crearea instantaneelor
Datorit faptului c n reprezentarea intern a serverului Oracle un instantaneu este alctuit dintr-o
colecie de obiecte, un utilizator nu poate crea un instantaneu n propria schem dect dac deine
privilegiile de sistem CREATE SNAPSHOT, CREATE TABLE, CREATE VIEW precum i
privilegiul SELECT pe tabelele master. Pentru a crea un instantaneu se folosete comanda
CREATE SNAPSHOT cu urmtoarea sintax simplificat:
CREATE SNAPSHOT nume_instantaneu
[REFRESH[FAST|COMPLETE|FORCE][START WITH dat][NEXT dat]
[WITH PRIMARY KEY|WITH ROWID]]
[FOR UPDATE]
AS subinterogare
unde:
clauza REFRESH - specific modul i intervalul la care se va face mprosptarea automat a
instantaneului:
- FAST - va avea loc o remprosptare rapid.
- COMPLETE - va avea loc o remprosptare complet.
- FORCE - Oracle decide n momentul n care are loc remprosptarea dac aceasta poate
s fie rapid sau nu.
Dac se omite una din opiunile de mai sus, Oracle va considera implicit opiunea FORCE.
- START WITH - specific data la care va avea loc prima remprosptare automat.
- NEXT - specific data la care va avea loc urmtoarea remprosptare automat. Aceast
dat este folosit la calcularea intervalului dintre dou remprosptri.
Cele dou opiuni de mai sus trebuie s conin o dat n viitor. Dac se omite opiunea
START WITH, Oracle determin la crea instantaneului momentul n care va avea loc prima
remprosptare prin evaluarea opiunii NEXT. Dac se omite opiunea NEXT,
remprosptarea automat a instantaneului va avea loc doar o singur dat. n schimb, dac
sunt omise ambele opiuni, remprosptarea automat nu va avea loc niciodat, aceasta
fcndu-se
n
mod
manual
prin
utilizarea
programatic
a
procedurii
DBMS_SNAPSHOT.REFRESH().
- WITH PRIMARY KEY specific faptul c instantaneul va fi de tip cheie primar.
- WITH ROWID specific faptul c instantaneul va fi de tip ROWID.
clauza FOR UPDATE - permite ca datele coninute de instantaneu simplu s poat fi modificate.
Pentru mai multe informaii, vezi documentaia Oracle [26] [Oracle Documentation]/ Oracle8
Database/ Oracle8 Replication.

AS subinterogare specific interogarea pe care se bazeaz instantaneul. Aceast subinterogare


se supune acelorai restricii ca i interogarea ce st la baza unei vederi.
Urmtorul exemplu creeaz un instantaneu numit salariati_ro care s conin toate
nregistrrile din tabela angajai aflat n schema utilizatorului scott din baza de date
denumit romania. mprosptarea instantaneului va fi de tip rapid. Prima mprosptare a
instantaneului va avea loc la o or dup ce instantaneul a fost creat, urmtoarele mprosptri
fcndu-se la interval de 7 zile.

152

CREATE SNAPSHOT salariati_ro


REFRESH FAST
START WITH sysdate +1/24
NEXT sysdate + 7
AS
SELECT * FROM scott.angajati@romania;
6.9.2 Modificarea instantaneelor
Un instantaneu poate fi modificat ntr-unul din urmtoarele sensuri:
Schimbarea caracteristicilor de stocare
Schimbarea modului i a intervalului la care poate avea loc remprosptarea automat
Modificarea unui instantaneu se realizeaz cu ajutorul comenzii ALTER SNAPSHOT. Exemplul
urmtor modific modul de remprosptare al instantaneului de mai sus, adic aceasta va fi o
remprosptare complet, precum i intervalul la care va avea loc:
ALTER SNAPSHOT salariati_ro
REFRESH COMPLETE
NEXT sysdate + 1;
6.9.3 Distrugerea instantaneelor
tergerea unui instantaneu se realizeaz cu comanda DROP SNAPSHOT. n cazul unui instantaneu
simplu, n momentul n care instantaneul este ters, toate informaiile din jurnalul aferent
instantaneului sunt i ele eliminate. Dac jurnalul unui instantaneu este distrus, nu se va mai putea
efectua o remprosptare rapid iar instantaneul va trebui remprosptat complet.
Dac tabelele master ale unui instantaneu sunt terse, Oracle nu va distruge automat instantaneele
bazate pe aceste tabele. De aceea, atunci cnd se va ncerca o nou remprosptare, va surveni o
eroare deoarece tabelele principale au fost eliminate.
6.10 Legturile bazei de date
Fiecare baz de date coninut ntr-o baz de date distribuit are propriul su nume, numit nume
global al bazei de date, format prin prefixarea numelui de domeniu al reelei pe care se afl baza de
date cu numele individual al bazei de date. Numele de domeniu i numele bazei de date este dat de
parametrul de iniializare DB_DOMAIN, respectiv DB_NAME. Pot exista mai multe baze de date ce
au acelai nume individual, dar fiecare baz de date trebuie s aib propriul nume global. De
exemplu, dac domeniile de reea romania.ro i europa.ro conin fiecare o baz de date cu
denumirea vanzari, aceste baze de date vor avea numele global vanzari.romania.ro
respectiv vanzari.europa.ro.
Pentru a facilita cererile unei aplicaii ce ruleaz pe o bat de date distribuit Oracle utilizeaz
legturile unei baze de date. O legtura a unei baze de date este un obiect al bazei de date locale
care permite accesul la obiecte dintr-o baz de date la distan. Practic legtura definete calea ctre
baza de date situat la distan. Atunci cnd o instruciune conine o referire la numele global al
unui obiect, sistemul Oracle ncearc s gseasc o legtur la baza de date specificat n numele
global al obiectului. Dac n baza de date local este gsit o legtur la baza de date specificat, se
ncearc realizarea unei conexiuni. n caz contrar, nu este realizat conexiunea i instruciunea nu
este executat.
153

Legtura unei baze de date este transparent utilizatorului deoarece numele su este acelai cu
numele global al bazei de date la care face referin. Dac parametrul de iniializare
GLOBAL_NAMES este setat pe valoarea TRUE, Oracle asigur c numele unei legturi este aceleai
ca i numele global al bazei de date. Acesta este un mecanism vital pentru bazele de date distribuite,
legturile devenind astfel total transparente pentru utilizatori.
Exist trei tipuri de legturi la baze de date:
private legtura este creat pentru un anumit utilizator i nu poate fi folosit dect de
utilizatorul specificat. O legtur privat este mult mai sigur dect o legtur public sau
global deoarece numai proprietarul legturii sau subprogramele ce se gsesc n aceeai schem
cu legtura pot accesa baza de date corespunztoare situat la distan.
public legtura este creat pentru grupul de utilizatori PUBLIC i poate fi folosit de ctre toi
utilizatorii bazei de date. Legturile publice se folosesc atunci cnd mai muli utilizatori necesit
accesarea unei baze de date situat la distan.
global legtura este creat i gestionat automat de ctre un serviciu de reea n momentul n
care reeaua Oracle folosete numele globale ale unei baze de date. O legtur global la o baz
de date poate fi folosit de orice utilizator care specific numele global al unei obiect ntr-o
instruciune. Gestionarea legturilor globale este centralizat i simpl.
Tipul legturilor dintr-o baz de date distribuit depinde de cerinele specifice aplicaiei ce
utilizeaz sistemul.
6.10.1 Crearea legturilor bazei de date
Pentru a crea o legtur se folosete comanda CREATE DATABASE LINK. O sintax simplificat
a acestei comenzi este urmtoarea:
CREATE [PUBLIC] DATABASE LINK nume_legtur
[CONNECT TO user IDENTIFIED BY parola]
unde:
opiunea PUBLIC face ca legtura creat s fie public. Dac aceast opiune este omis atunci
legtura creat va fi privat;
[CONNECT TO user IDENTIFIED BY parola] este numele utilizatorului i parola
acestuia utilizat pentru conectarea la baza de date situat la distan. Dac aceast clauz este
omis, se utilizeaz numele i parola utilizatorului care folosete aceast legtur.
De exemplu, urmtoarea comand creeaz o legtur privat la baza de date cu numele global
vanzari.romania.ro. Legtura are acelai nume ca i baza de date i poate fi folosit de
utilizatorul costel identificat de parola costica:
CREATE DATABASE LINK vanzari.romania.ro
CONNECT TO costel IDENTIFIED BY costica
Odat creat legtura, utilizatorii pot accesa datele bazei de date respective prin folosirea numelor
globale ale obiectelor. De exemplu, dup crearea legturii utilizatorul costel poate interoga
tabela salariati n urmtoarea manier:
SELECT * FROM salariati@ vanzari.romania.ro;

154

O legtur global se creeaz cu ajutorul Oracle Name Server. Pentru mai multe amnunte vezi
documentaia Oracle [26] [Oracle Documentation]/ Network/ Net8 Administrators Guide.
Legturile nu se pot crea dect dac utilizatorul deine privilegiul de sistem CREATE DATABASE
LINK sau CREATE PUBLIC DATABASE LINK, iar n baza de date situat la distan privilegiul
CREATE SESSION. Net8 trebuie instalat att n nodul local ct i n nodul situat la distan.
6.10.2. tergerea legturilor bazei de date
O legtur la o baz de date situat la distan se poate terge din baza de date local cu ajutorul
comenzii:
DROP DATABASE LINK nume_legtur
Nu se pot terge legturile la o baz de date aflate n schema altui utilizator. Acest lucru nu este
posibil deoarece Oracle interpreteaz, de exemplu, costel.legatura drept numele unei
legturi din schema proprie i nu ca legtura legatura din schema utilizatorului costel.

155

6.11 Dicionarul de Date


Dicionarul de date este o component esenial a unei baze de date Oracle. Dicionarul de date
reprezint o mulime de tabele care pot fi doar vizualizate (read-only) i care furnizeaz informaii
despre baza de date. El este creat automat la crearea bazei de date i conine:
definiiile tuturor obiectelor de schem din baza de date (tabele, vederi, indeci, sinonime,
secvene, proceduri, funcii, pachete, triggere, etc.);
ct spaiu a fost alocat i ct spaiu este utilizat n prezent de obiectele de schem;
valori implicite (default) pentru coloane;
informaii despre constrngeri de integritate;
numele utilizatorilor bazei de date;
privilegiile i rolurile acordate fiecrui rol;
alte informaii generale despre baza de date;
Dicionarul de date este structurat n tabele i vederi, exact ca oricare alte date ale bazei de date.
Toate tabelele i vederile dicionarului de date pentru o anumit baz de date sunt stocate n spaiul
tabel SYSTEM al bazei de date respective i sunt proprietatea utilizatorului SYS. Din aceast cauz,
asupra obiectelor din schema SYS nu trebuie niciodat efectuate operaii de UPDATE, DELETE sau
INSERT, deoarece acestea pot avea efecte distrugtoare asupra bazei de date.
Dicionarul de date este un element esenial pentru fiecare baz de date Oracle, dar este n acelai
timp i un mijloc foarte important care poate fi utilizat de dezvoltatori de aplicaii sau
administratorul bazei de date pentru a afla informaii despre aceasta. Deci, asupra obiectelor
dicionarului de date exist dou moduri de acces:
de ctre utilizatorii bazei de date: tabelele sau vederile dicionarului de date pot fi interogate de
utilizatorii bazei de date prin comenzi SQL SELECT pentru a afla informaii. Utilizatorii bazei
de date nu pot modifica obiectele dicionarului de date, ci le pot doar vizualiza.
de ctre Oracle Server: acesta modific dicionarul de date pentru a reflecta schimbrile din
structura bazei de date. De asemenea, n timpul operaiilor bazei de date, Serverul Oracle de
asemenea citete informaii din dicionarul de date pentru a verifica dac obiectele bazei de date
exist i dac utilizatorii au acces la ele.
Oracle creeaz sinonime publice pentru multe din vederile dicionarului de date pentru a permite un
acces convenabil la acestea utilizatorilor bazei de date. Pentru dezvoltatorii de aplicaii care se
refer la obiectele dicionarului de date, se recomand ca acetia s foloseasc sinonimele publice n
loc de obiectele propriu-zise: este mai puin probabil ca numele sinonimelor s se schimbe de la o
versiune la alta.
Obiectele dicionarului de date se mpart n urmtoarele dou categorii:
tabele de baz: acestea stocheaz informaii despre baza de date asociat. n general, aceste
tabele sunt folosite doar de Oracle, utilizatorii le acceseaz direct foarte rar deoarece informaiile
coninute n acestea sunt greu de neles.
vederi accesibile utilizatorilor: acestea prezint informaiile din tabelele de baz ntr-un format
uor de neles pentru utilizatori. Acestea sunt folosite de utilizatorii bazei de date pentru a
accesa informaiile din dicionarul de date.
Vederile dicionarului de date au nume care reflect tipul de utilizare pentru care sunt destinate.
Vederile sunt clasificate n trei grupe care se disting ntre ele prin prefixele USER, ALL i DBA:

156

USER_xxxxx: Acestea conin informaii despre schema utilizatorului curent, incluznd


obiectele schemei, privilegiile acordate de ctre utilizator, etc. De exemplu, urmtoarea
interogare ntoarce numele tuturor tabelelor coninute n schema curent:
SELECT table_name FROM user_tables;
ALL_xxxxx: Acestea conin informaii despre obiectele care pot fi accesate de ctre utilizatorul
curent, adic obiectele din propria schem plus obiectele pentru care are acordate privilegii de
acces. De exemplu, urmtoarea interogare ntoarce proprietarul i numele tuturor tabelelor care
pot fi accesate de utilizatorul curent:
SELECT owner, table_name FROM all_tables;
DBA_xxxxx: Acestea conin informaii despre toate obiectele bazei de date, deci ele sunt
destinate pentru a fi folosite de ctre administratorul bazei de date; aceste vederi pot fi folosite
doar de utilizatori care au acordat privilegiul de sistem SELECT ANY TABLE sau rolul de DBA.
Fiind destinate exclusiv administratorul bazei de date, pentru aceste vederi nu sunt create
sinonime, deci numele lor trebuie prefixat cu cel al proprietarului, SYS, de exemplu:
SELECT owner, table_name FROM dba_tables;
Ca regul general, vederile a cror nume difer doar prin prefix (de exemplu USER_TABLES,
ALL_TABLES i DBA_TABLES) au coloane identice i prin urmare conin informaii similare, cu
excepia faptului c vederile cu prefix USER nu conin coloana OWNER.
O list a vederilor dicionarului de date se gsete n Anexa 5. Urmtorul tabel rezum principalele
vederi ale dicionarului de date care conin informaii despre fiierele de date i structurile logice de
stocare, utilizatorii, privilegiile i rolurile bazei de date precum i despre obiectele schemei. Sunt
listate doar vederile cu prefixul DBA, ns n majoritatea cazurilor exist i vederi similare cu
prefixele USER i ALL.
Fiiere de date, spaii tabel, segmente,
extinderi
Utilizatori, roluri i privilegii
Toate obiectele bazei de date
Tabele
Constrngeri
Vederi
Indeci
Clustere i clustere hash
Secvene
Sinonime
Pachete, Proceduri i Funcii
Triggere
Instantanee

DBA_TABLESPACES, DBA_DATA_FILES,
DBA_SEGMENTS, DBA_EXTENTS
DBA_USERS, DBA_ROLES, DBA_ROLE_PRIVS,
DBA_COL_PRIVS, DBA_ROLE_PRIVS,
DBA_SYS_PRIVS, DBA_TAB_PRIVS
DBA_OBJECTS, DBA_OBJECT_SIZE
DBA_TABLES
DBA_CONSTRAINTS
DBA_VIEWS
DBA_INDEXES, DBA_IND_COLUMNS
DBA_CLUSTERS, DBA_CLU_COLUMNS,
DBA_CLUSTER_HASH_EXPRESION
DBA_SEQUENCES
DBA_SYNONYMS
DBA_SOURCE, DBA_ERRORS,
DBA_TRIGGERS, DBA_TRIGGER_COLS
DBA_REGISTERED_SNAPSHOTS,
DBA_REGISTERED_SNAPSHOT_GROU,
DBA_SNAPSHOTS,
DBA_SNAPSHOT_LOGS,
157

Legturi ale bazei de date


Tipuri de date

DBA_SNAPSHOT_LOG_FILTER_COLS,
DBA_SNAPSHOT_REFRESH_TIMES
DBA_DB_LINKS
DBA_TYPES, DBA_TYPE_ATTRS,
DBA_DEPENDENCIES, DBA_TYPE_METHODS,
DBA_OBJECT_TABLES,
DBA_METHOD_PARAM,
DBA_METHOD_RESULTS

Alturi de vederile menionate mai sus, Oracle mai pstreaz nite vederi care conin informaii
despre activitatea curent a bazei de date. Acestea au prefixul V_$ i sunt numite tabele de
performan dinamic (dynamic performance tables). De exemplu V_$DATAFILE conine
informaii despre fiierele de date ale bazei de date. Aceste vederi nu trebuie n general accesate
dect de administratorul bazei de date. i pentru aceste vederi sunt create sinonime publice, acestea
fiind prefixate cu V$ (deci sinonimul public pentru V_$DATAFILE se va numi V$DATAFILE).
n dicionarul de date exist i vederi ale cror nume nu folosesc prefixele menionate mai sus.
Printre acestea menionm:
DICTIONARY: Acesta conine toate tabelele, vederile i sinonimele din dicionarul de date.
DICT_COLUMNS: Acesta conine toate coloanele din obiectele dicionarului de date.
De exemplu, dac ne intereseaz s obinem informaii referitoare la vederile ce conin date despre
tabelele bazei de date vom utiliza urmtoarea comand:
SELECT * FROM dictionary WHERE table_name LIKE %TABLE%;
DUAL: Acesta este un mic tabel, avnd o singur coloana numit DUMMY de tip VARCHAR2(1)
i un singur rnd coninnd valoarea X. El este folosit n interogri pentru a returna un rezultat
i aceasta datorit faptului c ntr-o instruciune SELECT trebuie specificat neaprat i clauza
FROM. Tabelul DUAL este pur i simplu un tabel standard Oracle care este utilizat ca un tabel de
test. De exemplu, pentru a afia data curent se folosete urmtoarea interogare:
SELECT sysdate FROM dual;
i pentru aceste vederi sunt create sinonime publice. De exemplu, vederea DICTIONARY are
sinonimul public DICT.
Pentru obiectele unei baze de date exist posibilitatea de a face anumite comentarii asupra lor prin
inserarea unui text n dicionarul de date. Comentariul este creat prin comanda:
COMMENT
ON
{TABLE
nume_obiect
nume_obiect.nume_coloana}
nume_obiect IS 'text comentariu';

COLUMN

unde nume_obiect reprezint numele unui tabel, vederi sau instantaneu. Comentariul se poate referi
la tabele, vederi, instantanee sau coloane.

158

Capitolul 7: Accesul concurent la date i pstrarea


consistenei acestora
Baza de date Oracle permite acces concurent, adic poate fi accesat simultan de mai muli
utilizatori n cadrul mai multor sesiuni de lucru. O problem fundamental ntr-o baz de date cu
acces concurent este pstrarea consistenei datelor Aceasta nseamn pe de o parte c n cadrul
fiecrei sesiuni de lucru, utilizatorul trebuie s aib o vedere consistent asupra bazei de date,
incluznd modificrile vizibile fcute de ctre ali utilizatori, iar pe de alt parte Oracle trebuie s
mpiedice modificrile incorecte ale datelor, care ar putea compromite integritatea acestora.
Modalitatea cea mai simpl de a gestiona problema accesului concurent la date ar fi ca fiecare
utilizator s-i atepte rndul pentru a accesa baza de date. Evident, aceast soluie este total
neconvenabil, scopul unui SGBD fiind de a reduce aceste ateptri astfel nct ele s fie inexistente
sau neglijabile pentru ali utilizatori. Cu alte cuvinte, nu se pot face compromisuri nici n ceea ce
privete consistena datelor, dar nici n ceea ce privete performanele sistemului. Mecanismul prin
care Oracle gestioneaz accesul concurent la date folosete un model de consisten multiversiune i
diverse tipuri de blocri, care vor fi discutate mai trziu n acest capitol. Aceste mecanisme au la
baz conceptul de tranzacie.
7.1 Tranzaciile i asigurarea consistenei la scriere
Conceptul de tranzacie este fundamental pentru modul n care Oracle asigur consistena datelor. O
tranzacie este alctuit din una sau mai multe instruciuni SQL. O tranzacie este cea mai mic
unitate de lucru n Oracle, n sensul c pentru orice tranzacie, fie sunt executate toate schimbrile
fcute bazei de date de ctre tranzacie, fie nu este executat nici una dintre modificri. Cu alte
cuvinte, o tranzacie nu poate fi executat parial. La sfritul unei tranzacii, schimbrile fcute
bazei de date sunt fie permanentizate (commited), fie sunt anulate, n acest ultim caz spunndu-se c
tranzacia a fost derulat napoi (rolled back). Dup ce o tranzacie a fost permanentizat sau
derulat napoi, urmtoarea tranzacie va ncepe cu urmtoarea instruciune SQL.
n timpul executrii unei tranzacii, modificrile fcute asupra bazei de date de ctre acestea nu sunt
vizibile altor sesiuni de lucru. Dac tranzacia este permanentizat, atunci schimbrile fcute de
aceasta devin vizibile pentru alte sesiuni care ncep dup permanentizarea acesteia. Dac tranzacia
este derulat napoi, atunci modificrile asupra datelor efectuate de ctre aceasta sunt anulate, astfel
nct datele afectate vor rmne neschimbate, ca i cnd instruciunile SQL din tranzacie nu au fost
niciodat executate.
S lum de exemplu o baz de date a unei bnci. Cnd un client transfer o suma de bani dintr-un
cont de depozit ntr-un cont curent, tranzacia poate s conin trei operaii separate: retragerea
sumei din contul de depozit, depunerea sumei n contul curent i nregistrarea operaiunii ntr-un
jurnal:
UPDATE cont_depozit
SET balanta = balanta - 700
WHERE nr_cont = 87410;
UPDATE cont_depozit
SET balanta = balanta + 700
WHERE nr_cont = 87411;
INSERT
INTO
cont_creditor)

jurnal(nr_operatiune,

159

suma,

cont_debitor,

VALUES (jurnal_seq.NEXTVAL, 700, 87410, 87411);


COMMIT;
Pentru a asigura corectitudinea datelor, Oracle trebuie s garanteze c toate cele trei operaii sunt
efectuate. Dac ceva neateptat, de exemplu o defeciune hard, mpiedic executarea uneia dintre
instruciuni, atunci celelalte instruciuni ale tranzaciei trebuiesc anulate, adic tranzacia trebuie
derulat napoi. Deci, dac una dintre instruciuni nu se poate executa cu succes, atunci celelalte
trebuiesc anulate pentru a menine consistena bazei de date.
O tranzacie ncepe cu prima comand executabil SQL i se ncheie cnd apare una dintre
urmtoarele comenzi sau evenimente:
COMMIT [WORK] sau ROLLBACK [WORK]. Comanda COMMIT sau COMMIT WORK
permanentizeaz modificrile fcute de ctre tranzacie. Comanda ROLLBACK sau ROLLBACK
WORK deruleaz napoi tranzacia;
o comand DDL (CREATE,ALTER,DROP). Deci orice comand DDL este implicit
permanentizat, astfel nct orice tranzacie nu poate conine dect cel mult o comand DDL;
sfritul sesiunii curente de lucru, n acest caz fcndu-se implicit o permanentizare;
defeciune hard sau soft, caz n care tranzacia este derulat napoi pentru recuperarea datelor
(rollback on recovery) i pstrarea integritii acestora.
Dup terminarea tranzaciei, urmtoarea comand executabil SQL va ncepe n mod automat o
nou tranzacie.
7.1.1 Comanda AUTOCOMMIT
Dac se folosete utilitarul SQL*Plus, exist posibilitatea ca dup fiecare comand DML s aib loc
o permanentizare automat a datelor (un COMMIT implicit). Acest lucru se poate realiza folosind
comanda SQL SET AUTO[COMMIT], avnd sintaxa:
SET AUTO[COMMIT] [ON|OFF]
n cazul folosirii acestei comenzi cu opiunea ON (SET AUTO ON sau SET AUTOCOMMIT ON) o
tranzacie nu va putea conine dect cel mult o singur comand DML, iar instruciunea ROLLBACK
nu va mai avea nici un efect, datele fiind permanentizate implicit ori de cte ori este executat o
comand DML. Permanentizarea implicit a unei comenzi DML este anulat la executarea
comenzii SET AUTO[COMMIT] cu opiunea OFF (SET AUTO OFF sau SET AUTOCOMMIT OFF).
7.1.2 Puncte de salvare
n cazul tranzaciilor mai lungi, care conin multe instruciuni SQL, pentru a mpri tranzacia n
pri mai mici, pot fi declarai delimitatori intermediari, numite puncte de salvare (savepoints). Un
punct de salvare poate fi declarat folosind comanda SAVEPOINT, avnd sintaxa:
SAVEPOINT nume_punct_salvare.
Declararea unor puncte de salvare n interiorul unei tranzacii permite posibilitatea ca la un moment
ulterior s fie derulate napoi toate instruciunile executate ncepnd cu un punct de salvare
specificat. Acest lucru se poate face cu comanda ROLLBACK sau ROLLBACK WORK cu specificaia
TO [SAVEPOINT]:
ROLLBACK [WORK] TO [SAVEPOINT] nume_punct_salvare
160

De exemplu, s considerm urmtoarea secven de comenzi SQL:


INSERT INTO departament (cod_dept, cod_tara, nume_dept)
VALUES (dept_seq.NEXTVAL, 40, 'Proiectare');
SAVEPOINT alfa;
INSERT INTO departament (cod_dept, cod_tara, nume_dept)
VALUES (dept_seq.NEXTVAL, 40, 'Vanzari');
SAVEPOINT beta;
INSERT INTO departament (cod_dept, cod_tara, nume_dept)
VALUES (dept_seq.NEXTVAL, 40, 'IT');
n acest punct, anularea celei de-a treia inserri n tabelul departament se poate face folosind
comanda:
ROLLBACK TO beta;
Anularea ultimelor dou inserri se poate face folosind comanda:
ROLLBACK TO alfa;
Anularea tuturor celor trei inserri i ncheierea tranzaciei se face folosind comanda:
ROLLBACK;
7.2 Asigurarea consistenei cu ajutorul tranzaciilor
Tranzaciile furnizeaz utilizatorului bazei de date sau dezvoltatorului de aplicaii capacitatea de a
garanta consistena modificrilor operate asupra datelor. Pentru a asigura aceast consisten,
comenzile SQL trebuie s fie grupate n mod logic n tranzacii. O tranzacie trebuie s fie o unitate
logic de lucru, nici mai mult, nici mai puin. Datele din baza de date trebuie s fie consistente
nainte de nceperea tranzaciei i la sfritul acesteia. n plus, o tranzacie trebuie s cuprind doar
o singur modificare consistent a datelor.
De exemplu, s considerm exemplul transferului bancar de la nceputul acestei seciuni. Cele trei
aciuni efectuate (retragerea sumei din contul de depozit, depunerea ei n contul curent i
nregistrarea n jurnal) trebuiau fie s fie toate executate, fie nici una. Pentru a asigura consistena
datelor, orice alt aciune fr legtur cu operaiunea dat (de exemplu, un nou depozit ntr-un alt
cont) nu trebuie inclus n aceeai tranzacie.
7.2.1 Modelul multiversiune i consistena la citire
Modelul multiversiune, furnizat de ctre Oracle, asigur consistena la citire (read consistency),
adic:
Garanteaz c setul de date vzut de orice instruciune SQL este consistent i nu se schimb n
timpul execuiei unei instruciuni; cu alte cuvinte - se spune c Oracle asigur o consisten la
citire la nivel de instruciune;
Operaiile de citire (SELECT) nu trebuie s vad datele care sunt n proces de schimbare;

161

Operaiile de scriere (INSERT, UPDATE, DELETE) nu trebuie s afecteze consistena datelor i


s ntrerup sau s intre n conflict cu alte operaii de scriere concurente.
Cea mai simpl modalitate de a ne imagina un sistem care asigur consistena la citire este de ne
nchipui c fiecare utilizator opereaz asupra unei copii proprii a bazei de date - de unde i numele
de model multiversiune.
7.2.2 Implementarea modelului multiversiune
Consistena la citire este implementat de ctre Oracle prin pstrarea unei copii a datelor n
segmentele de revenire. Cnd este efectuat o operaie de INSERT, UPDATE sau DELETE asupra
unui tabel, Oracle va face o copie a datelor nainte ca acestea s se modifice ntr-un segment de
revenire. Toate operaiile de citire efectuate asupra tabelului n alte sesiuni de lucru vor vedea datele
aa cum erau ele nainte de schimbare - deci vor vedea datele din segmentul de revenire. nainte ca
datele fie permanentizate (prin COMMIT explicit sau implicit), doar utilizatorul din sesiunea curent
va vedea datele modificate, toi ceilali vor vedea datele din segmentul de revenire. Dac
schimbrile sunt permanentizate, atunci ele vor deveni vizibile i pentru ceilali utilizatori. n acest
caz, spaiul ocupat de datele vechi n segmentul de revenire este eliberat i poate fi utilizat din nou.
Dac tranzacia este derulat napoi (prin ROLLBACK sau n cazul unei defeciuni) atunci datele din
segmentul de revenire sunt scrise napoi n baza de date, iar ceilali utilizatori vd n continuare
datele iniiale, ca i cum modificrile fcute de ctre tranzacie nu s-ar fi efectuat.
7.2.3 Tranzacii de citire i consistena la citire la nivel de tranzacie
n mod implicit consistena la citire asigurat de ctre Oracle este la nivel de instruciune, adic
datele nu se schimb n timpul efecturii unei instruciuni. n acest caz, putem avea, n cadrul
aceleiai sesiuni de lucru, dou interogri identice care produc rezultate diferite - aceasta se poate
ntmpla dac ntre cele dou interogri au fost permanentizate schimbrile fcute de ctre o alt
tranzacie. n anumite situaii ns, dac o tranzacie cuprinde mai multe interogri, se poate dori ca
toate aceste interogri s aib o vedere consistent asupra datelor n raport cu acelai moment de
timp. Cu alte cuvinte, interogrile din aceast tranzacie nu vor simi efectul permanentizrilor
fcute de ctre alte tranzacii dup nceperea tranzaciei curente. n acest caz se spune c tranzacia
este de citire (read only transaction) iar consistena la citire asigurat de ctre Oracle este la nivel de
tranzacie (transaction-level read consistency). Consistena la citire la nivel de tranzacie este
implementat similar cu cea la nivel de instruciune, adic folosind segmente de revenire.
Pentru a ncepe o tranzacie de citire se folosete comanda SET TRANSACTION READ ONLY.
Aceast comand trebuie s fie prima instruciune din tranzacie. Dup executarea acestei
instruciuni, toate permanentizrile fcute de ctre alte tranzacii nu vor fi vizibile n tranzacia
curent. O tranzacie de citire nu poate conine dect interogri (instruciuni SELECT); comenzile
DML nu sunt permise iar comanda SELECT ... FOR UPDATE va produce o eroare. O tranzacie de
citire se va termina atunci cnd se vor executa comenzile COMMIT [WORK], ROLLBACK [WORK]
sau la executarea unei comenzi DDL - deoarece o comand DDL realizeaz un COMMIT implicit. n
timpul unei tranzacii de citire, ali utilizatori pot continua s interogheze i s modifice datele.
7.3. Blocri
Blocrile (locks) sunt folosite de Oracle pentru a asigura integritatea datelor, permind n acelai
timp accesul concurent la date de ctre un numr infinit de utilizatori.
n principal, blocrile folosite de Oracle sunt de dou feluri:

162

Blocri de date sau blocri DML: Aceste blocri protejeaz datele i le vom discuta pe larg n
aceast seciune.
Blocri de dicionar sau blocri DDL: Acestea protejeaz definiia unui obiect al schemei (de
exemplu a unui tabel) n timp ce o operaia DDL acioneaz asupra acestuia sau face referire la
acesta (dup cum am menionat nainte, fiecare operaie DDL permanentizeaz implicit
tranzacia din care face parte, astfel nct blocarea este necesar doar pe durata unei astfel de
operaii). De exemplu, dac un utilizator creeaz o procedur atunci toate obiectele la care se
face referin n acea procedur vor fi blocate, prevenindu-se modificarea sau distrugerea lor
nainte de ncheierea compilrii procedurii.
Comenzile SQL de interogare (SELECT fr clauza FOR UPDATE) nu provoac nici un fel de
blocare.
Din punct de vedere al resursei blocate, blocrile DML pot fi de dou feluri:
blocri la nivel de rnd, atunci cnd blocarea afecteaz un singur rnd
blocri la nivel de tabel, atunci cnd blocarea afecteaz ntreg tabelul
Din punct de vedere al modului de declanare a blocrii, blocrile DML sunt de dou feluri
Implicite, atunci cnd blocarea este fcut n mod automat de ctre Oracle n urma efecturii
unor operaii de INSERT, UPDATE sau DELETE i nu necesit nici o aciune din partea
utilizatorului. Rndul asupra cruia se efectueaz o astfel de operaie este blocat pentru evitarea
unor alte operaii DML simultane asupra sa.
Explicite, atunci cnd ele apar ca urmare a executrii de ctre utilizator a urmtoarelor comenzi
SQL
SELECT cu clauza FOR UPDATE
LOCK TABLE
O blocare a unei resurse este obinut de ctre o tranzacie, deci blocarea va fi eliberat la ncheierea
tranzaciei. Deci toate blocrile obinute n timpul unei tranzacii sunt eliberate atunci cnd
tranzacia este permanentizat sau derulat napoi. n plus, toate blocrile obinute dup un punct de
salvare sunt eliberate atunci cnd tranzacia este derulat napoi pn la acel punct de salvare.
7.3.1 Blocri la nivel de rnd
Blocrile la nivel de rnd apar n mod implicit la efectuarea unor operaii de INSERT, UPDATE i
DELETE, ct i n mod explicit la executarea comenzii SELECT cu clauza FOR UPDATE. n aceast
seciune ne vom referi la blocrile implicite la nivel de rnd, comanda SELECT FOR UPDATE
urmnd s fie prezentat mai trziu.
n momentul efecturii unor operaii de INSERT, UPDATE sau DELETE asupra datelor, rndul sau
rndurile afectate de aceste operaii sunt blocate. Blocarea se efectueaz la nivel de rnd, adic la
nivelul cel mai de jos posibil, i nu la nivel de tabel, asigurndu-se astfel cel mai bun acces
concurent posibil. Combinaia ntre modelul multiversiune descris mai sus i blocrile la nivel de
rnd asigur faptul c utilizatorii nu intr n competiie pentru date dect dac ncearc accesarea
aceluiai rnd. Mai precis, mecanismul folosit de Oracle pentru gestionarea concurenei asigur
urmtoarele:
Operaiile de citire (SELECT) nu trebuie s atepte pn la terminarea operaiilor de scriere
(INSERT, UPDATE, DELETE) sau a altor operaii de citire efectuate asupra acelorai rnduri.
Operaiile de scriere nu trebuie s atepte pn la terminarea operaiilor de citire efectuate asupra
acelorai rnduri, cu excepia situaiei cnd acest lucru este cerul explicit de o comand SELECT
FOR UPDATE
163

Operaiile de scriere trebuie doar s atepte pentru alte operaii de scriere care ncerc s
modifice aceleai rnduri n tranzacii concurente.
La nivel de rnd, blocrile se pot face numai n modul exclusiv (X), adic un utilizator nu poate
modifica un rnd pn ce tranzacia care l-a blocat s-a terminat (prin permanentizare sau derulare
napoi).
Dac o tranzacie obine o blocare pentru un rnd, atunci ea obine i o blocare la nivel de tabel
pentru tabelul corespunztor. O blocare la nivel de tabel este de asemenea necesar pentru a preveni
operaii DDL care ar interaciona cu modificrile de date din tranzacia curent. Urmtoarea
seciune explic blocrile la nivel de tabel.
7.3.2. Blocrile la nivel de tabel
O tranzacie obine o blocare la nivel de tabel n mod implicit atunci cnd asupra tabelului este
executat una dintre comenzile INSERT, UPDATE sau DELETE sau n mod explicit, prin comenzile
SELECT FOR UPDATE i LOCK TABLE. Blocrile la nivel de tabel au urmtoarele dou scopuri:
rezervarea accesului la tabel pentru tranzacia curent i prevenirea de operaii DDL care ar intra n
conflict cu aceast tranzacie de exemplu, asupra unui tabel nu pot fi executate operaiile ALTER
sau DROP dac exist o tranzacie neterminat care deine asupra acestuia o blocare la nivel de
tabel.
Blocrile la nivel de tabel pot fi fcute n mai multe moduri, n funcie de caracterul mai mult sau
mai puin restrictiv al blocrii:
RS - row share
RX - row exclusive
S - share
SRX - share row exclusive
X - exclusive
Modul de blocare al unui tabel determin modurile n care alte tranzacii pot bloca acelai tabel.
Enumerarea de mai sus este fcut n ordinea cresctoare a caracterului restrictiv al modului de
blocare, de la cel mai puin restrictiv (RS) la cel mai restrictiv (X). n continuare trecem n revist
fiecare dintre aceste moduri, artnd aciunile care produc modul respectiv de blocare i ce aciuni
sunt permise sau nu n alte tranzacii concurente cu tranzacia care deine blocarea.
Mod de blocare RS la nivel de tabel
O blocare n mod RS la nivel de tabel arat c tranzacia care blocheaz tabelul a blocat rnduri din
tabel i intenioneaz s le modifice. O blocare n mod RS se obine la executarea comenzilor
SELECT cu clauza FOR UPDATE i LOCK TABLE cu opiunea ROW SHARE. Modul de blocare RS
este cel mai puin restrictiv dintre toate modurile de blocare, permind gradul cel mai mare de
acces concurent pentru un tabel.
Operaii permise: O blocare n mod RS permite acces (SELECT, INSERT, UPDATE, DELETE)
concurent la tabel i blocarea concurent a tabelului de ctre alt tranzacie n orice mod, n afara de
cel X.
Operaii nepermise: O blocare n mod RS nu permite altor tranzacii concurente de a bloca tabelul
n mod X.
Mod de blocare RX la nivel de tabel
164

O blocare n mod RX la nivel de tabel arat n general c tranzacia care deine blocarea a fcut una
sau mai multe modificri asupra rndurilor din tabel. O blocare n mod RX este obinut la
executarea comenzilor DML (INSERT, UPDATE i DELETE) i a comenzii LOCK TABLE cu
opiunea ROW EXCLUSIVE. Blocarea n mod RX este ceva mai restrictiv dect blocarea n mod
RS.
Operaii permise: O blocare n mod RX permite acces (SELECT, INSERT, UPDATE, DELETE)
concurent la tabel i blocarea concurent a tabelului de ctre alt tranzacie n modurile RS i RX.
Operaii nepermise: O blocare n mod RX nu permite altor tranzacii concurente de a bloca tabelul
n modurile X, SRX i S.
Mod de blocare S la nivel de tabel
O blocare n mod S este obinut la executarea comenzii LOCK TABLE cu opiunea SHARE.
Operaii permise: O blocare n mod S permite altor tranzacii doar interogarea (SELECT) tabelului
i blocarea sa n modurile S i RS.
Operaii nepermise: O blocare n mod S nu permite altor tranzacii concurente de a efectua operaii
de INSERT, UPDATE sau DELETE i de a bloca tabelul n modurile SRX i X.
Mod de blocare SRX la nivel de tabel
Modul de blocare SRX este mai restrictiv dect cel S. O blocare n mod SRX este obinut la
executarea comenzii LOCK TABLE cu opiunea SHARE ROW EXCLUSIVE.
Operaii permise: O blocare n mod SRX permite altor tranzacii doar interogarea (SELECT)
tabelului i blocarea sa n modul RS. Asupra unui tabel nu poate deine simultan blocri n modul
SRX dect cel mult o singur tranzacie.
Operaii nepermise: O blocare n mod SRX nu permite altor tranzacii concurente de a efectua
operaii de INSERT, UPDATE sau DELETE i de a bloca tabelul n orice mod n afara de RS.
Mod de blocare X la nivel de tabel
Modul de blocare X este cel mai restrictiv mod de blocare. O blocare n mod X este obinut la
executarea comenzii LOCK TABLE cu opiunea EXCLUSIVE.
Operaii permise: O blocare n mod SRX permite interogarea altor tranzacii doar interogarea
(SELECT) tabelului. Asupra unui tabel nu poate deine simultan blocri n modul SRX dect cel
mult o singur tranzacie.
Operaii nepermise: O blocare n mod SRX nu permite altor tranzacii concurente de a efectua
operaii de INSERT, UPDATE sau DELETE i de a bloca tabelul n orice mod.
Urmtorul tabel rezum modul de blocare implicit precum i posibilitatea existenei simultane a mai
multor tipuri de blocare la nivel de tabel, n urma executrii comenzilor SQL corespunztoare:

165

Comanda SQL

Mod de
blocare
implicit
SELECT fr clauza FOR UPDATE
Nici unul
INSERT
RX
UPDATE
RX
DELETE
RX
SELECT cu clauza FOR UPDATE
RS
LOCK TABLE n ROW SHARE MODE
RS
LOCK TABLE n ROW EXCLUSIVE MODE
RX
LOCK TABLE n SHARE MODE
S
LOCK TABLE n ROW SHARE EXCLUSIVE SRX
MODE
LOCK TABLE n EXCLUSIVE MODE
X

Moduri de blocare permise


simultan
RS
RX S
SRX X
Da
Da
Da
Da
Da
Da
Da
Nu
Nu
Nu
Da* Da* Nu
Nu
Nu
Da* Da* Nu
Nu
Nu
Da* Da* Da* Da* Nu
Da
Da
Da
Da
Nu
Da
Da
Nu
Nu
Nu
Da
Nu
Da
Nu
Nu
Da
Nu
Nu
Nu
Nu
Nu

Nu

Nu

Nu

Nu

Da* = Da, dac nu exist alt tranzacie care deine blocri la nivel de rnd care intr n conflict cu blocarea la nivel de
rnd produs de aceast comand SQL; n caz contrar, tranzacia va atepta eliberarea acestor blocri la nivel de rnd.

n general, blocarea implicit la nivel de rnd este suficient n aplicaii. Totui, aa cum am
menionat mai devreme, blocarea se poate face i n mod implicit, folosind comanda SELECT cu
clauza FOR UPDATE (la nivel de rnd i tabel) i comanda LOCK TABLE (la nivel de tabel).
Acestea sunt prezentate n urmtoarele dou seciuni.
7.3.3. Comanda SELECT cu clauza FOR UPDATE
Folosirea clauzei FOR UPDATE ntr-o comand SELECT determin blocarea rndurilor selectate n
modul X i blocarea ntregului tabel sau tabelelor pe care se face interogarea n modul RS. Deci
comanda SELECT cu clauza FOR UPDATE nu modific rndurile selectate ci doar le blocheaz.
Aceast comand este foarte folositoare pentru aducerea unui rnd mai devreme ntr-o tranzacie,
nainte de a-l actualiza. La actualizarea rndurilor (prin comanda UPDATE) blocarea la nivel de
rnd rmne neschimbat n timp ce modul de blocare al tabelului devine RX.
Sintaxa acestei comenzi este urmtoarea:
SELECT lista_coloane
FROM tabel [,tabel] .
WHERE condiie
FOR UPDATE [OF coloana [,coloana] ] [NOWAIT]
Dac se specific NOWAIT i rndul sau rndurile selectate sunt deja blocate de alt tranzacie,
atunci utilizatorul este ntiinat de acest lucru, returnndu-i-se controlul. Dac NOWAIT nu este
specificat, atunci comanda ateapt pn cnd rndul este deblocat.
S lum de exemplu, tranzacia urmtoare:
SELECT salariu
FROM salariat
WHERE cod_salariat = 102
FOR UPDATE OF salariu NOWAIT;
UPDATE salariat
SET salariu = 3500
WHERE cod_salariat = 102;

166

COMMIT;
Atunci, la executarea primei comenzi, rndul cu cod_salariat = 2 este blocat n mod X n timp ce
tabelul salariat este blocat n mod RS. La executarea celei de-a doua comenzi, blocarea la nivel de
rnd se menine n timp ce blocarea la nivel de tabel este schimbat n modul RX. La executarea
instruciunii COMMIT, tranzacia este permanentizat i toate blocrile sunt eliberate.
7.3.4 Comanda LOCK TABLE
Unul sau mai multe tabele pot fi blocate n oricare din modurile prezentate mai sus folosind
comanda LOCK TABLE, avnd sintaxa:
LOCK TABLE nume_tabel [, nume_tabel]
IN mod_blocare MODE
[NOWAIT]
unde mod_blocare poate avea valorile ROW SHARE, ROW EXCLUSIVE, SHARE, ROW SHARE
EXCLUSIVE sau EXCLUSIVE. Folosirea lui NOWAIT este opional i are aceeai semnificaie ca
n cazul de mai sus.
n principal, blocarea manual a unui tabel folosind comanda LOCK TABLE poate fi preferat n
urmtoarele situaii:
Este necesar o vedere consistent asupra mai multor tabele. n acest caz, tabelele pot fi
blocate n modul S, mpiedicnd operaiile DML asupra acestuia.
Se dorete mpiedicarea altor utilizatori de a bloca tabelele asupra crora opereaz tranzacia
curent. Acest lucru se poate face blocnd tabelele n modul X
Se dorete ca o instruciune sa nu atepte pentru deblocarea unei resurse. n acest caz se poate
folosi opiunea NOWAIT.
Urmtorul tabel rezum tipurile de blocare la nivel de rnd i tabel obinute la executarea diverselor
comenzi SQL.
Comanda SQL
SELECT fr clauza FOR UPDATE
INSERT
UPDATE
DELETE
SELECT cu clauza FOR UPDATE
LOCK TABLE n ROW SHARE MODE
LOCK TABLE n ROW EXCLUSIVE MODE
LOCK TABLE n SHARE MODE
LOCK TABLE n ROW SHARE EXCLUSIVE MODE
LOCK TABLE n EXCLUSIVE MODE

Blocare la nivel
de rnd

Mod de blocare
La nivel de
tabel

X
X
X
X

RX
RX
RX
RS
RS
RX
S
RSX
X

7.3.5 Interblocarea
Datorit accesului concurent la date este posibil ca mai muli utilizatori s se blocheze reciproc.
Aceast situaie se numete interblocare (deadlock), pentru c fiecare dintre utilizatori ateapt ca
167

cellalt s elibereze resursa blocat. n cazul acesta problema nu se poate rezolva prin simpla
ateptare, una din tranzacii trebuind s fie derulat napoi.
S lum, de exemplu, urmtoarele dou tranzacii care se execut simultan:
Tranzacia A
UPDATE salariat
SET salariu = 3500
WHERE cod_salariat = 102;

Tranzacia B
UPDATE departament
SET nume_dept = Proiectare
WHERE cod_dept = 2
AND cod_tara = 40

UPDATE departament
SET localitate = Ploiesti
WHERE cod_dept = 2
AND cod_tara = 40

UPDATE salariat
SET manager = 101
WHERE cod_salariat = 102;

La executarea primelor instruciuni din fiecare tranzacie nu este nici o problem. Cnd ns
tranzaciile ncerc s obin blocri pentru instruciunile respective se va ajunge la interblocare
deoarece tranzacia A trebuie s atepte ca tranzacia B s deblocheze rndul din tabelul
departament n timp ce tranzacia B trebuie s atepte ca tranzacia A s deblocheze rndul din
tabelul salariat. n general o interblocare poate s fie cauzat de mai mult de dou tranzacii, de
exemplu tranzacia 2 ateapt dup tranzacia 1, tranzacia 3 dup tranzacia 2, etc., iar tranzacia 1
atept dup tranzacia n.
Detectarea interblocrii
Oracle detecteaz interblocrile n mod automat. n acest caz, Oracle semnaleaz o eroare uneia
dintre tranzaciile implicate i deruleaz napoi ultima instruciune din acesta tranzacie. Acest lucru
rezolv interblocarea, dei cealalt tranzacie poate nc s atepte pn la deblocarea resursei
pentru care ateapt. De obicei, tranzacia semnalat trebuie derulat napoi n mod explicit.
Evitarea interblocrii
Interblocrile pot fi de obicei evitate dac tranzaciile care acceseaz aceleai tabele blocheaz
aceste tabele n aceeai ordine, prin blocare implicit sau explicit. De exemplu, putem impune
regula ca, atunci cnd este accesat att un tabel master ct i un tabel detaliu, s fie blocat nti
tabelul master i dup aceea cel de detaliu. Dac astfel de reguli sunt bine alctuite i aplicate,
atunci probabilitatea de apariie a interblocrilor este foarte rar.

168

Capitolul 8: SQL
n acest capitol vor fi prezentate pe larg comanda de regsire a datelor SELECT, comenzile de
manipulare a datelor INSERT, UPDATE, DELETE, precum i comanda TRUNCATE. Exemplele din
acest capitol sunt realizate cu ajutorul utilitarului SQL*Plus.
8.1 Comanda SELECT
Regsirea datelor stocate n baza de date este considerat cea mai important facilitate a unui
SGBD. n SQL ea se realizeaz prin intermediul comenzii SELECT. Comanda SELECT este
folosit doar pentru regsirea datelor, ea neputndu-le modifica. Aa cum am vzut mai nainte,
comanda SELECT implementeaz toi operatorii algebrei relaionale.
O instruciune SELECT cuprinde n mod obligatoriu cuvntul cheie FROM. Cu alte cuvinte, sintaxa
minimal pentru comanda SELECT este:
SELECT atribute FROM tabel
Dup cuvntul cheie SELECT se specific lista atributelor ce urmeaz a fi returnate ca rezultat al
interogrii, iar dup cuvntul FROM se precizeaz obiectele (tabele, vederi, sinonime) din care se
vor selecta aceste atribute.
8.1.1 Atributele comenzii SELECT
n lista de atribute pot aprea:
toate coloanele din tabel sau vedere (n ordinea n care au fost definite n comanda CREATE
TABLE / CREATE VIEW) prin utilizarea semnului * :
SQL> SELECT * FROM profesor;
COD
----100
101
102
103
104
105
106

NUME
------GHEORGHIU
MARIN
GEORGESCU
IONESCU
ALBU
VOINEA
STANESCU

PRENUME DATA_NAST
-------------------------STEFAN
11-AUG-46
VLAD
19-APR-45
CRISTIANA 30-OCT-51
VERONICA
GHEORGHE
MIRCEA
15-NOV-65
MARIA
05-DEC-69

GRAD
------PROF
PROF
CONF
ASIST
LECT
ASIST
ASIST

SEF
---3000
100
100
102
100
100
103

SALARIU
----------3500
2500
2800
1500
2200
1200
1200

PRIMA
-------200
2500
150
600

COD_CATEDRA
-------------------10
20
30
10
20
10
20

numele coloanelor separate prin virgul. Acestea vor aprea n rezultatul interogrii n ordinea
n care sunt specificate:

SQL> SELECT nume, prenume, salariu FROM profesor;


NUME
---------------------GHEORGHIU
MARIN
GEORGESCU
IONESCU
ALBU
VOINEA

PRENUME
-------------------STEFAN
VLAD
CRISTIANA
VERONICA
GHEORGHE
MIRCEA

SALARIU
------------3000
2500
2800
1500
2200
1200
169

STANESCU

MARIA

1200

atribute rezultate din evaluarea unor expresii. Aceste expresii pot conine nume de coloane,
constante, operatori sau funcii.

8.1.2. Operatori aritmetici


Operatorii aritmetici pot fi folosii pentru a crea expresii avnd tipul de date numeric sau date
calendaristice. Operatorii aritmetici sunt: + (adunare), - (scdere ), * (nmulire), / (mprire).
Ordinea de preceden a operatorilor poate fi schimbat cu ajutorul parantezelor.
De exemplu dac n tabela PROFESOR ne intereseaz s calculm impozitul aferent salariilor,
tiind c acesta este de 38%, putem scrie urmtoarea interogare:
SQL> SELECT nume, salariu, salariu*0.38 FROM profesor;
NUMES
-------------------GHEORGHIU
MARIN
GEORGESCU
IONESCU
ALBU
VOINEA
STANESCU

SALARIU
-------------------3000
2500
2800
1500
2200
1200
1200

SALARIU*0.38
-------------------1140
950
1064
570
836
456
456

8.1.3. Aliasuri de coloane


Pentru exemplul anterior observm c n momentul afirii rezultatelor, SQL*Plus utilizeaz
numele coloanelor ca antet. Cnd acest lucru poate face dificil nelegerea rezultatelor, se poate
schimba antetul prin atribuirea altor nume coloanelor (numite alias-uri ale coloanei). Acest lucru
se realizeaz specificnd aliasul dup numele coloanei. n cazul n care aliasul conine spaii sau
caractere speciale cum ar fi + sau -, acesta se va specifica ntre ghilimele.
n exemplul de mai jos aliasul "DATA NASTERE" conine spaii deci este specificat ntre ghilimele
n timp ce aliasul IMPOZIT nu conine spaii sau caractere speciale deci nu trebuie specificat
obligatoriu ntre ghilimele.
SQL> SELECT nume, data_nast "DATA NASTERE", salariu, salariu*0.38 IMPOZIT FROM profesor;
NUME
-------------------GHEORGHIU
MARIN
GEORGESCU
IONESCU
ALBU
VOINEA
STANESCU

DATA NASTERE SALARIU


------------------------ --------------11-AUG-46
3000
19-APR-45
2500
30-OCT-51
2800
1500
2200
15-NOV-65
1200
05-DEC-69
1200

IMPOZIT
------------1140
950
1064
570
836
456
456

8.1.4. Operatorul de concatenare

170

Operatorul de concatenare, notat ||, permite legarea coloanelor cu alte coloane, expresii aritmetice
sau valori constante pentru a crea o expresie de tip ir de caractere. De exemplu, pentru a combina
codul, numele si prenumele unui profesor, separate printr-un spaiu, se folosete urmtoarea
interogare:
SQL> SELECT cod || ' ' || nume || ' ' || prenume detalii_profesor FROM profesor;
DETALII_PROFESOR
------------------------------------------100 GHEORGHIU STEFAN
101 MARIN VLAD
102 GEORGESCU CRISTIANA
103 IONESCU VERONICA
104 ALBU GHEORGHE
105 VOINEA MIRCEA
106 STANESCU MARIA
8.1.5 Convertirea valorilor Null cu ajutorul funciei NVL
Dac la o nregistrare pentru o anumit coloan valoarea este necunoscut sau neaplicabil, atunci
aceasta este Null. Aceast valoare nu trebuie confundat cu zero sau irul de caractere format dintrun spaiu. Aa cum am vzut n exemplele de pn acum, dac o anumit valoare este Null,
SQL*Plus nu va afia nimic. Pentru expresiile aritmetice, dac una dintre valorile componente este
Null, atunci i rezultatul expresiei este Null. De exemplu, pentru a calcula salariul total, ce
reprezint suma dintre coloanele salariu i prima putem folosi interogarea:
SQL> SELECT nume, salariu, prima, salariu+prima SALARIU TOTAL FROM profesor;
NUME
-------------------GHEORGHIU
MARIN
GEORGESCU
IONESCU
ALBU
VOINEA
STANESCU

SALARIU
--------------3000
2500
2800
1500
2200
1200
1200

PRIMA SALARIU TOTAL


----------- ----------------------3500
6500
200

3000

2500
150
600

4700
1350
1800

Observm c pentru acele nregistrri care au avut valoarea Null n cmpul prima expresia ce
calculeaz salariul total returneaz tot valoarea Null.
Pentru a obine un rezultat diferit de Null, valorile Null trebuiesc convertite ntr-un numr (n cazul
de fa 0) nainte de a aplica operatorul aritmetic. Aceast convertire se poate realizeaz prin
intermediul funciei NVL. Funcia NVL are dou argumente. Dac valoarea primului argument nu
este Null, atunci NVL ntoarce aceast valoare; dac nu, ea ntoarce valoarea celui de-al doilea
argument. Cele dou argumente pot avea orice tip de date. Dac tipurile de date ale celor dou
argumente difer, Oracle ncerc s converteasc al doilea argument la tipul de date al primului. De
exemplu, pentru a putea calcula salariul total al tuturor cadrelor didactice, trebuie s convertim
valoarea Null din coloana prima a tabelei PROFESOR n valoarea 0 folosind NVL(prima, 0):
SQL> SELECT nume, salariu, prima, salariu+nvl(prima,0) SALARIU TOTAL FROM profesor;

171

NUME
-----------------GHEORGHIU
MARIN
GEORGESCU
IONESCU
ALBU
VOINEA
STANESCU

SALARIU
------------3000
2500
2800
1500
2200
1200
1200

PRIMA SALARIU TOTAL


----------- ----------------------3500
6500
2500
200
3000
1500
2500
4700
150
1350
600
1800

8.1.6 Prevenirea selectrii nregistrrilor duplicat


O comanda SELECT care nu cuprinde cuvntul cheie DISTINCT va afia toate nregistrrile care
rezult din interogare, indiferent dac una sau mai multe dintre ele sunt identice. De exemplu,
interogarea de mai jos va returna urmtoarele rezultate:
SQL> SELECT grad FROM profesor;
GRAD
----PROF
PROF
CONF
ASIST
LECT
ASIST
ASIST
n cazul folosirii cuvntului cheie DISTINCT nregistrrile duplicat sunt eliminate, afindu-se
numai prima apariie a valorilor cmpurilor specificate n lista de atribute. De exemplu:
SQL> SELECT DISTINCT grad FROM profesor;
GRAD
----ASIST
CONF
LECT
PROF
Dac lista de atribute conine mai multe coloane, operatorul DISTINCT va afecta toate coloanele
selectate. Urmtorul exemplu va afia toate combinaiile de valori care sunt diferite pentru
coloanele grad i cod_catedra.
Exemplu:
SQL> SELECT DISTINCT grad, cod_catedra FROM profesor;
GRAD
--------ASIST
ASIST

COD_CATEDRA
---------------------10
20
172

CONF
LECT
PROF
PROF

30
20
10
20

8.1.7 Clauza ORDER BY


n mod normal, n urma interogrii nregistrrile rezultate apar n aceeai ordine n care au fost
introduse n baza de date. Pentru a modifica ordinea de afiare se utilizeaz clauza ORDER BY, care
sorteaz nregistrrile dup valorile din una sau mai multe coloane. Aceast clauz este urmat de
numele coloanelor dup care se va face sortarea. De asemenea, este posibil s se identifice coloana
dintr-o clauz ORDER BY folosind n locul numelui coloanei un numr ordinal ce reprezint poziia
coloanei n rezultat (de la stnga la dreapta). Aceast facilitate face posibil ordonarea rezultatului
interogrii n funcie de un atribut al clauzei SELECT care poate fi o expresie complex, fr a mai
rescrie acea expresie.
Nu exist nici o limit a numrului de coloane n funcie de care se poate face sortarea. Nu este
obligatoriu ca ordinea de sortare s se fac n funcie de o coloan care s fie afiat, dar n acest
caz nu se mai poate folosi numrul de ordine al coloanei n loc de numele acesteia. nregistrrile vor
fi sortate mai nti n funcie de primul cmp specificat dup clauza ORDER BY, apoi, nregistrrile
care au aceeai valoare n acest prim cmp sunt sortate n funcie de valoarea celui de-al doilea
cmp specificat dup clauza ORDER BY, .a.m.d.
De exemplu, pentru a sorta ascendent nregistrrile n funcie de impozitul pe salariu folosim
interogarea:
SQL> SELECT nume, salariu*0.38 FROM profesor ORDER BY salariu*0.38;
care este echivalenta cu:
SQL> SELECT nume, salariu*0.38 FROM profesor ORDER BY 2;
NUME
-------------------VOINEA
STANESCU
IONESCU
ALBU
MARIN
GEORGESCU
GHEORGHIU

SALARIU*0.38
------------------456
456
570
836
950
1064
1140

nregistrrile sunt sortate n mod implicit n ordine ascendent (opiunea ASC), afiarea n ordine
descendent fcndu-se prin utilizarea opiunii DESC. Observai c n momentul sortrii valoarea
Null este considerat cea mai mare, deci dac sortarea este ascendent este trecut pe ultima poziie
i dac sortarea este descendent este trecut pe prima poziie. De exemplu:
SQL> SELECT grad, prima FROM profesor ORDER BY grad, prima DESC;
GRAD
PRIMA
------------- ---------

173

ASIST
ASIST
ASIST
CONF
LECT
PROF
PROF

600
150
200
2500
3500

Se observ c n exemplul de mai sus nregistrrile au fost mai nti sortate ascendent (specificaie
implicit) n funcie de gradul didactic. nregistrrile cu acelai grad au fost apoi ordonate n funcie
de cel de-al doilea criteriu de sortare, adic n funcie de prima primit cu specificaia explicit de
sortare descendent.
8.1.8 Clauza WHERE
Clauza WHERE se folosete pentru a regsi nregistrri ce corespund unei anumite condiii evaluat
cu valoarea de adevr TRUE, adic pentru a realiza anumite restricii de selecie. Astfel, clauza
WHERE corespunde restriciilor operatorilor din algebra relaional. Cu alte cuvinte, dac o clauz
ORDER BY este o clauz de sortare, clauza WHERE este o clauz de filtrare. Dac nu se specific o
clauz WHERE, interogarea va ntoarce ca rezultat toate rndurile din tabel. mpreun cu clauza
SELECT i FROM care sunt obligatorii, WHERE este cea mai folosit clauz din SQL. Din punct de
vedere sintactic clauza WHERE este opional, dar atunci cnd este introdus urmeaz ntotdeauna
imediat dup clauza FROM:
SELECT nume coloan
FROM
tabel
WHERE
condiie
Datorit existenei valorii Null, n SQL o condiie poate lua att valorile TRUE i FALSE ct i
valoarea Necunoscut (despre acest lucru vom discuta mai n detaliu n seciunile urmtoare). O
comand SELECT cu clauza WHERE va returna toate nregistrrile pentru care condiia are
valoarea TRUE. Condiia clauzei WHERE poate cuprinde numele unor coloane, constante, operatori
de comparaie sau operatori logici (NOT, AND, OR). Operatorii de comparaie se pot mpari n
dou categorii: operatori relaionali i operatori SQL. Toi aceti operatori sunt trecui n revist n
continuare.
8.1.9 Operatori relaionali
Operatorii relaionali sunt:
=
egal
>
mai mare
>=
mai mare sau egal
<
mai mic
<=
mai mic sau egal
<> i !=
diferit
Cele dou valori care sunt comparate trebuie s aparin unor tipuri de date compatibile.
De exemplu, pentru a selecta toate cadrele didactice care nu aparin catedrei cu codul 10 folosim
urmtoarea interogare:
SQL> SELECT nume, prenume FROM profesor WHERE cod_catedra <>10;

174

NUME
---------------------MARIN
GEORGESCU
ALBU
STANESCU

PRENUME
--------------VLAD
CRISTIANA
GHEORGHE
MARIA

irurile de caractere i data calendaristic trebuiesc incluse ntre apostrofuri. De exemplu, pentru a
selecta numai acele cadre didactice care au gradul didactic de profesor vom utiliza urmtoarea
interogare:
SQL> SELECT nume, prenume FROM profesor WHERE grad ='PROF';
NUME
-------------------GHEORGHIU
MARIN

PRENUME
--------------STEFAN
VLAD

n cazul irurilor de caractere, literele mici sunt diferite de literele mari. De exemplu, urmtoarea
interogare nu va returna nici o nregistrare:
SQL> SELECT nume, prenume FROM profesor WHERE grad='prof';
Toi operatorii de comparaie pot fi folosii att pentru valori numerice ct i pentru iruri de
caractere sau date calendaristice. De exemplu, pentru a afla toate cadrele didactice care s-au nscut
nainte de 1 Ianuarie 1960 folosim interogarea:
SQL> SELECT nume, prenume, data_nast FROM profesor WHERE data_nast < '01-JAN-65';
NUME
PRENUME
------------------------ -----------------GHEORGHIU
STEFAN
MARIN
VLAD
GEORGESCU
CRISTIANA

DATA_NAST
-----------------11-AUG-46
19-APR-45
30-OCT-51

n cazul irurilor de caractere ordonarea se face dup codul ASCII al acestora. De exemplu, pentru a
afla toate cadrele didactice ale cror nume sunt n ordinea alfabetic dup litera M se poate folosi
interogarea.
SQL> SELECT nume, prenume FROM profesor WHERE nume >= 'M';
NUME
-------------------MARIN
VOINEA
STANESCU

PRENUME
--------------VLAD
MIRCEA
MARIA

Observai c interogarea de mai sus este corect numai n cazul n care numele angajailor ncepe cu
o liter mare, literele mici fiind n spatele celor mari.

175

Exist posibilitatea de a compara pentru o nregistrare valoarea unei coloane cu valoarea altei
coloane. De exemplu, dac dorim s selectm acele cadre didactice care au primit prim mai mare
dect salariul de baz vom avea:
SQL> SELECT nume, prenume, salariu, prima FROM profesor WHERE salariu<prima;
NUME
---------GHEORGHIU
ALBU

PRENUME
---------STEFAN
GHEORGHE

SALARIU
--------3000
2200

PRIMA
--------3500
2500

8.1.10 Operatori SQL


Exist patru tipuri de operatori SQL care pot opera cu toate tipurile de date:
1. BETWEEN...AND...
2. IN
3. LIKE
4. IS NULL
Operatorul BETWEEN...AND...
Operatorul BETWEEN...AND...permite specificarea unui domeniu mrginit de dou valori ntre care
trebuie s se afle valoarea testat. Domeniul de valori specificat este un interval nchis iar limita
inferioar trebuie specificat prima.
Astfel, dac dorim selectarea acelor cadre didactice care au salariul ntre 2000 i 3000 vom folosi
comanda:
SQL> SELECT nume, prenume, salariu FROM profesor WHERE salariu BETWEEN 2000 AND 3000;
NUME
---------GHEORGHIU
MARIN
GEORGESCU
ALBU

PRENUME
---------STEFAN
VLAD
CRISTIANA
GHEORGHE

SALARIU
--------3000
2500
2800
2200

Operatorul IN
Operatorul IN permite specificarea unei liste de valori, valoarea testat trebuind s se afle printre
valorile acestei liste.
De exemplu, dac dorim selectarea cadrelor didactice care au gradul de confereniar, lector sau
asistent vom utiliza comanda:
SQL> SELECT nume, prenume, grad FROM profesor WHERE grad IN ('CONF', 'LECT', 'ASIST');
NUME

PRENUME

GRAD
176

---------GEORGESCU
IONESCU
ALBU
VOINEA
STANESCU

---------CRISTIANA
VERONICA
GHEORGHE
MIRCEA
MARIA

----CONF
ASIST
LECT
ASIST
ASIST

Operatorul LIKE
Operatorul LIKE permite specificarea unui anumit model de ir de caractere cu care trebuie s se
potriveasc valoarea testat. Acest operator se folosete n mod special atunci cnd nu se tie exact
valoarea care trebuie cutat. Pentru a construi modelul dup care se face cutarea pot fi folosite
dou simboluri:
%
semnific orice secven de zero sau mai multe caractere
_
semnific orice caracter (care apare o singur dat)
De exemplu, urmtoarea comand SELECT va returna toate cadrele didactice al cror nume ncepe
cu litera G:
SQL> SELECT nume, prenume FROM profesor WHERE nume LIKE 'G%';
NUME
---------GHEORGHIU
GEORGESCU

PRENUME
---------STEFAN
CRISTIANA

Dac dorim selectarea acelor cadre didactice al cror nume are litera O pe a doua poziie,
indiferent de lungimea cuvntului, vom avea:
SQL> SELECT nume, prenume FROM profesor WHERE nume LIKE '_O%';
NUME
---------IONESCU
VOINEA

PRENUME
---------VERONICA
MIRCEA

O problem intervine atunci cnd irul conine caracterele % sau _ (de exemplu irul J_James)
deoarece aceste caractere au semnificaie predefinit. Pentru a schimba interpretarea acestor
caractere se folosete opiunea ESCAPE.
De exemplu, pentru a cuta toate titlurile de carte care ncep cu caracterele J_ se poate folosi
interogarea:
SQL> SELECT titlu FROM carte WHERE titlu LIKE 'J/_%' ESCAPE '/';
n exemplul de mai sus opiunea ESCAPE identific caracterul / ca fiind caracterul escape.
Deoarece n modelul folosit pentru LIKE acest caracter precede caracterul _ acesta din urm va fi
interpretat ca o simpl liter, fr alt semnificaie.
Avantajul unei viteze mari de regsire ca urmare a indexrii este pierdut n momentul n care se
caut un ir de caractere care ncepe cu _ sau % ntr-o coloan indexat.

177

Operatorul IS NULL
Operatorul IS NULL testeaz dac valorile sunt Null. Pentru a vedea utilitatea acestui operator s
considerm urmtoarele interogri:
SQL> SELECT nume, prenume FROM profesor WHERE prima = NULL;
SQL> SELECT nume, prenume FROM profesor WHERE prima <> NULL;
Amndou aceste interogri nu vor returna nici o nregistrare. Aceste lucru pare surprinztor la
prima vedere deoarece ne-am fi ateptat ca prima interogare s returneze toate cadrele didactice care
nu au primit prim, iar a doua toate cadrele didactice care au primit prim. n SQL ns, orice
condiie care este format dintr-un operator de comparaie care are unul dintre termeni valoarea
Null va avea ca rezultat valoarea Necunoscut, diferit de valoarea TRUE (pentru care se face
filtrarea). Pentru compararea cu Null se folosete operatorul special IS NULL.
Deci pentru a afla cadrele didactice care nu au primit prim se folosete interogarea:
SQL> SELECT nume, prenume FROM profesor WHERE prima IS NULL;
NUME
---------MARIN
IONESCU

PRENUME
---------VLAD
VERONICA

La fel, pentru a afla cadrele didactice ale cror dat de natere nu se cunoate vom folosi urmtoarea
interogare:
SQL> SELECT nume, prenume FROM profesor WHERE data_nast IS NULL;
NUME
---------IONESCU
ALBU

PRENUME
---------VERONICA
GHEORGHE

8.1.11. Operatorii logici


Negarea operatorilor
n unele cazuri sunt mai uor de cutat nregistrrile care nu ndeplinesc o anumit condiie. Acest
lucru se poate realiza folosind operatorul NOT. Operatorul NOT se poate folosi pentru negarea unei
expresii logice (de exemplu expresii de tipul NOT coloana = ....) sau pentru negarea operatorilor
SQL n modul urmtor:
NOT BETWEEN
NOT IN
NOT LIKE
IS NOT NULL.
De exemplu, pentru a selecta cadrelor didactice al cror nume nu ncepe cu litera G se folosete
interogarea:
SQL> SELECT nume, prenume FROM profesor WHERE nume NOT LIKE 'G%';
178

NUME
---------MARIN
IONESCU
ALBU
VOINEA
STANESCU

PRENUME
---------VLAD
VERONICA
GHEORGHE
MIRCEA
MARIA

Pentru a selecta cadrelor didactice care au primit prima se folosete interogarea:


SQL> SELECT nume, prenume FROM profesor WHERE prima IS NOT NULL;
NUME
---------GHEORGHIU
GEORGESCU
ALBU
VOINEA
STANESCU

PRENUME
---------STEFAN
CRISTIANA
GHEORGHE
MIRCEA
MARIA

Observaie: Negarea unei expresii logice care are valoarea Necunoscut va avea tot valoare
necunoscut. De exemplu, o expresie de genul NOT coloana = NULL va avea valoarea necunoscut,
urmtoarea interogare nereturnnd nici o nregistrare:
SQL> SELECT nume, prenume FROM profesor WHERE NOT prima = NULL;
Condiii multiple de interogare (operatorii AND i OR)
Operatorii AND i OR pot fi utilizai pentru a realiza interogri ce conin condiii multiple. Condiia
ce conine operatorul AND este adevrat atunci cnd ambele condiii sunt adevrate iar condiia ce
conine operatorul OR este adevrat atunci cnd cel puin una din condiii este adevrat. n aceeai
expresie logic se pot combina operatorii AND i OR dar operatorul AND are o preceden mai mare
dect operatorul OR deci este evaluat mai nti.
n momentul evalurii unei expresii, se calculeaz mai nti operatorii n ordinea precedenei, de la
cel cu precedena cea mai mare pn la cel cu precedena cea mai mic. Dac operatorii au
preceden egal atunci ei sunt calculai de la stnga la dreapta.
Precedena operatorilor, pornind de la cea mai mare la cea mai mic este urmtoarea:
toi operatorii de comparaie i operatorii SQL: >,<,<=,>=,=,<>, BETWEEN...AND..., IN, LIKE,
IS NULL;
operatorul NOT;
operatorul AND;
operatorul OR.
Pentru a schimba prioritatea operatorilor se folosesc parantezele.
n exemplele de mai jos se observ modul de evaluare al expresiei n funcie de precedena
operatorilor, precum i modul n care parantezele pot schimba acest lucru.

179

SQL> SELECT nume, prenume, salariu, cod_catedra FROM profesor WHERE salariu>2000 AND
cod_catedra=10 OR cod_catedra=20;
este echivalent cu:
SQL> SELECT nume, prenume, salariu, cod_catedra FROM profesor WHERE (salariu>2000 AND
cod_catedra=10) OR cod_catedra=20;
NUME
---------GHEORGHIU
MARIN
ALBU
STANESCU

PRENUME
---------STEFAN
VLAD
GHEORGHE
MARIA

SALARIU
--------3000
2500
2200
1200

COD_CATEDRA
----------10
20
20
20

SQL> SELECT nume, prenume, salariu, cod_catedra FROM profesor WHERE salariu>2000 AND
(cod_catedra=10 OR cod_catedra=20);
NUME
---------GHEORGHIU
MARIN
ALBU

PRENUME
---------STEFAN
VLAD
GHEORGHE

SALARIU
--------3000
2500
2200

COD_CATEDRA
----------10
20
20

8.1.12 Funcii
Funciile sunt o caracteristic important a SQL i sunt utilizate pentru a realiza calcule asupra
datelor, modifica date, manipula grupuri de nregistrri, schimba formatul datelor sau pentru a
converti diferite tipuri de date. Funciile se clasific n dou tipuri:
1. Funcii referitoare la o singur nregistrare:
- funcii caracter;
- funcii numerice;
- funcii pentru data calendaristic i or;
- funcii de conversie;
- funcii diverse.
2. Funcii referitoare la mai multe nregistrri:
- funcii totalizatoare sau funcii de grup.
Diferena dintre cele dou tipuri de funcii este numrul de nregistrri pe care acioneaz. Funciile
referitoare la o singur nregistrare returneaz un singur rezultat pentru fiecare rnd al tabelului, pe
cnd funciile referitoare la mai multe nregistrri returneaz un singur rezultat pentru fiecare grup
de nregistrri din tabel.
O observaie important este faptul c dac se apeleaz o funcie SQL ce are un argument egal cu
valoarea Null, atunci n mod automat rezultatul va avea valoarea Null. Singurele funcii care nu
respect aceast regul sunt: CONCAT, DECODE, DUMP, NVL i REPLACE.
n continuare vom exemplifica i prezenta la modul general cele mai importante funcii, pentru
sintax urmnd s consultai Anexa 6.
8.1.13 Funcii referitoare la o singur nregistrare

180

Sunt funcii utilizate pentru manipularea datelor individuale. Ele pot avea unul sau mai multe
argumente i returneaz o valoare pentru fiecare rnd rezultat n urma interogrii.
Funcii caracter
Aceste funcii au ca argumente date de tip caracter i returneaz date de tip VARCHAR2, CHAR sau
NUMBER.
Cele mai importante funcii caracter sunt:
- CONCAT- returneaz un ir de caractere format prin concatenarea a dou iruri;
- LOWER - modific toate caracterele n litere mici;
- UPPER - modific toate caracterele n litere mari;
- LENGTH - returneaz numrul de caractere dintr-un anumit cmp;
- REPLACE - caut ntr-un ir de caractere un subir iar dac l gsete l va nlocui cu un alt ir
de
caractere;
- SUBSTR - returneaz un subir de caractere avnd o anumit lungime ncepnd cu o anumit
poziie;
- TRANSLATE - caut ntr-un ir de caractere un caracter iar dac l gsete l va nlocui cu un alt
caracter;
Exemplu de utilizare a funciei LENGTH:
SQL> SELECT LENGTH (nume) FROM profesor;
LENGTH(NUME)
-----------9
5
9
7
4
6
8
Spre deosebire de alte funcii, funciile caracter pot fi imbricate pn la orice adncime. Dac
funciile sunt imbricate ele sunt evaluate din interior spre exterior. Pentru a determina, de exemplu,
de cte ori apare caracterul A n cmpul nume vom folosi interogarea:
SQL>SELECT nume, LENGTH (nume)-LENGTH (TRANSLATE (nume,DA,D)) A FROM
profesor;
NUME
---------GHEORGHIU
MARIN
GEORGESCU
IONESCU
ALBU
VOINEA
STANESCU

'A'
--------0
1
0
0
1
1
1

181

Observaie: n exemplul de mai sus, funcia TRANSLATE (nume,DA,D) va cuta n coloana nume
primul caracter (caracterul D) din cel de-al doilea argument al funciei (irul de caractere DA) i l va
nlocui cu primul caracter (adic tot cu caracterul D) din cel de-al treilea argument al funciei (irul de
caractere D), apoi va cuta cel de-al doilea caracter, adic caracterul A, i l va terge din cmpul
nume deoarece acesta nu are caracter corespondent n cel de-al treilea argument al funciei. Am folosit
acest artificiu deoarece irul de caractere vid este echivalent cu valoarea Null deci funcia TRANSLATE
(nume,A,) ar fi nlocuit toate valorile cmpului nume cu valoarea Null.
Funcii numerice sau aritmetice
Aceste funcii au ca argumente date numerice i returneaz tot valori numerice. Marea majoritate a
acestor funcii au o precizie de 38 de zecimale (COS, EXP, LN, LOG, SIN SQRT, TAN au ns o
precizie de 36 de zecimale).
Dintre cele mai importante funcii amintim:
- ROUND - rotunjete valorile la un anumit numr de poziii zecimale;
- TRUNC - trunchiaz valorile un anumit numr de poziii zecimale;
- CEIL - returneaz cel mai mic ntreg mai mare sau egal cu o anumit valoare;
- FLOOR - returneaz cel mai mare ntreg mai mic sau egal cu o anumit valoare;
- SIGN - returneaz valoarea -1 dac valoarea argumentului primit este mai mic dect 0, 1 dac
valoarea argumentului primit este mai mare dect 0 i 0 dac valoarea argumentului primit este
egal cu 0;
- SQRT - returneaz rdcina ptrat a argumentului primit;
- ABS - returneaz valoarea absolut a argumentului primit;
- POWER - returneaz valoarea unui numr ridicat la o anumit putere;
- MOD - returneaz restul mpririi a dou numere;
- alte funcii matematice cum ar fi: LOG, SIN, TAN, COS, EXP, LN.
Funcii pentru dat calendaristic i or
n Oracle datele de tip dat calendaristic sunt reprezentate sub un format numeric reprezentnd:
ziua, luna, anul, ora, minutul, secunda i secolul. Oracle poate manevra date calendaristice de la 1
ianuarie 4712 BC pn la 31 decembrie 4712 AD. Modul predefinit de afiare i introducere este
sub forma: DD-MON-YY (ex. 31-Dec-99). Aceasta categorie de funcii opereaz pe valori de tip
dat calendaristic, rezultatul returnat fiind tot de tip dat calendaristic, excepie fcnd funcia
MONTHS_BETWEEN care returneaz o valoare numeric.
Cele mai des ntlnite funcii sunt:
- ADD_MONTH - returneaz o dat calendaristic format prin adugarea la data calendaristica
specificata a unui anumit numr de luni;
- LAST_DAY - ntoarce ca rezultat ultima zi a unei luni specificate;
- MONTHS_BETWEEN - returneaz numrul de luni dintre dou date calendaristice specificate;
- NEXT_DAY - returneaz o dat ulterioar datei calendaristice specificate;
- SYSDATE ntoarce ca rezultat data calendaristic a sistemului.
Asupra datelor calendaristice se pot realiza operaii aritmetice, cum ar fi scderea sau adunarea,
modul lor de funcionare fiind ilustrat n tabelul de mai jos:
Tip operand
Operaie
Tip operand
Tip Rezultat
Descriere
data
+/Numr
Data
Adaug/scade un numr de zile la o
dat calendaristic
data
+/numr/24
Data
Adaug/scade un numr de ore la o
dat calendaristic

182

data

+/-

numr/1440

Data

data

+/-

numr/86400

Data

data

Data

Numr zile

Adaug/scade un numr de minute la


o dat calendaristic
Adaug/scade un numr de secunde la
o dat calendaristic
Scade dou date calendaristice
rezultnd diferena n numr de zile.
Dac al doilea operand este mai mare
dect primul numrul de zile rezultat
este reprezentat de o valoare negativ.

De asemenea mai exist funciile ROUND i TRUNC care rotunjesc, respectiv trunchiaz data
calendaristic. Aceste funcii sunt foarte folositoare atunci cnd se dorete compararea datelor
calendaristice care au ora diferit. Exemplul urmtor rotunjete data de natere a cadrelor didactice
n funcie de an:
SQL> SELECT ROUND (data_nast,'YEAR') DATA FROM profesor;
DATA
--------01-JAN-47
01-JAN-45
01-JAN-52
01-JAN-66
01-JAN-70
Funcii de conversie
n general expresiile nu pot conine valori aparinnd unor tipuri de date diferite. De exemplu, nu se
poate nmuli 3 cu 7 i apoi aduna ION. Prin urmare se realizeaz anumite conversii care pot fi
implicite sau explicite. Conversiile implicite se realizeaz n urmtoarele cazuri:
- atribuiri de valori unei coloane (folosind comenzile INSERT sau UPDATE) sau atribuirilor de
valori unor argumente ale unei funcii;
- evaluri de expresii.
Pentru atribuiri, programul Oracle efectueaz n mod implicit urmtoarele conversii de tip:
- VARCHAR2 sau CHAR la NUMBER
- VARCHAR2 sau CHAR la DATE
- VARCHAR2 sau CHAR la ROWID
- NUMBER, DATE sau ROWID la VARCHAR2
Conversia la atribuire reuete n cazul n care Oracle poate converti tipul valorii atribuite la tipul
destinaiei atribuirii.
Pentru evaluarea expresiilor, se realizeaz n mod implicit urmtoarele conversii de tip:
- VARCHAR2 sau CHAR la NUMBER
- VARCHAR2 sau CHAR la DATE
- VARCHAR2 sau CHAR la ROWID
De exemplu, pentru urmtoarea interogare se realizeaz conversia n mod implicit a constantei de
tip CHAR 10 la tipul NUMBER.
SQL> SELECT salariu + '10' FROM profesor;

183

SALARIU+'10'
-----------3010
2510
2810
1510
2210
1210
1210
Pentru conversiile explicite de tip, SQL pune la dispoziie mai multe funcii de conversie, de la un
anumit tip de dat la altul, dup cum este artat n tabelul de mai jos.
CHAR
CHAR
NUMBER TO_CHAR
DATE
TO_CHAR
RAW
RAWTOHEX
RAWID
RAWIDTOCHA
R

NUMBER
TO_NUMBER
TO_DATE(dat,J)

DATE
TO_DATE
TO_DATE(nr,J)
-

RAW
HEXTORAW

ROWID
CHARTOROWID

Cele mai uzuale funcii sunt:


- TO_CHAR - convertete un numr sau o dat calendaristic ntr-un ir de caractere;
- TO_NUMBER - convertete un ir de caractere alctuit din cifre la o valoare numeric;
- TO_DATE - convertete un ir de caractere sau un numr ce reprezint o dat calendaristic la o
valoare de tip dat calendaristic. De asemenea poate converti o dat calendaristic la un numr
ce reprezint data calendaristic Iulian.
Pentru a realiza conversia aceste funcii folosesc anumite mti de format. Pentru mai multe
amnunte vezi Anexa 6.
Urmtorul exemplu va prelua data i ora curent a sistemului din funcia SYSDATE i o va formata
ntr-o dat scris pe litere ce va conine i ora n minute i secunde:
SQL> SELECT TO_CHAR(SYSDATE,'DD MONTH YYYY HH24:MI:SS') Data FROM dual;
DATA
-------------------------17 MAY
2000 17:03:38
Funcii diverse
Acestea sunt n general funcii care accept ca argumente orice tip de dat.
Cele mai utilizate sunt:
- DECODE - Aceasta este una dintre cele mai puternice funcii SQL. Ea practic faciliteaz
interogrile condiionate, acionnd ca o comanda if-then-else sau case dintr-un limbaj
procedural. Pentru fiecare nregistrare se va evalua valoarea din coloana testat i se va compara
pe rnd cu fiecare valoare declarat n cadrul funciei. Dac se gsesc valori egale, atunci
funcia va returna o valoare aferent acestei egaliti, declarat tot n cadrul funciei. Se poate
specifica ca, n cazul n care nu se gsesc valori egale, funcia s ntoarc o anumit valoare.
Dac acest lucru nu se specific funcia va ntoarce valoarea Null.

184

GREATEST - returneaz cea mai mare valoare dintr-o list de valori;


LEAST - returneaz cea mai mic valoare dintr-o list de valori;
VSIZE - returneaz numrul de bytes pe care este reprezentat intern o anumit coloan;
USER - returneaz numele utilizatorului curent al bazei de date;
DUMP - returneaz o valoare ce conine codul tipului de dat, lungimea n bytes, precum i
reprezentarea intern a unei expresii.

Exemplul urmtor utilizeaz funcia DECODE pentru a returna o cretere a salariului cadrelor
didactice cu grad de profesor, confereniar i lector, restul salariilor rmnnd nemodificate:
SQL> SELECT nume, grad, salariu, DECODE (grad, PROF,salariu*1.2, CONF , salariu*1.15,
LECT, salariu*1.1, salariu) Salariu modificat FROM profesor;
NUME
---------GHEORGHIU
MARIN
GEORGESCU
IONESCU
ALBU
VOINEA
STANESCU

GRAD
----PROF
PROF
CONF
ASIST
LECT
ASIST
ASIST

SALARIU
--------3000
2500
2800
1500
2200
1200
1200

Salariu modificat
----------------3600
3000
3220
1500
2420
1200
1200

8.14. Funcii referitoare la mai multe nregistrri


Aceste funii se mai numesc i funcii totalizatoare sau funcii de grup. Spre deosebire de funciile
referitoare la o singur nregistrare, funciile de grup opereaz pe un set de mai multe nregistrri i
returneaz un singur rezultat pentru fiecare grup. Dac nu este utilizat clauza GROUP BY, ce
grupeaz nregistrrile dup un anumit criteriu, tabela este considerat ca un singur grup i se va
returna un singur rezultat.
- COUNT - determin numrul de nregistrri care ndeplinesc o anumit condiie;
- MAX - determin cea mai mare valoare dintr-o coloan;
- MIN - determin cea mai mic valoare dintr-o coloan;
- SUM - returneaz suma tuturor valorilor dintr-o coloan;
- AVG - calculeaz valoarea medie a unei coloane;
- STDDEV - determin abaterea sau deviaia standard a unei coloane numerice;
- VARIANCE - returneaz dispersia, adic ptratul unei deviaii standard pentru o coloan
numeric.
Exemplu:
SQL> SELECT MIN(salariu), MAX(salariu), AVG(salariu), COUNT(*) FROM profesor;
Toate funciile de mai sus, cu excepia funciei COUNT, opereaz asupra unei coloane sau unei
expresii, care este specificat ca parametru al funciei. n cazul funciei COUNT, argumentul
acesteia nu conteaz, de obicei utilizndu-se ca argument simbolul *.
MIN(SALARIU) MAX(SALARIU)
----------------------1200
3000

AVG(SALARIU)
-----------2057.1429

185

COUNT(*)
--------7

Observaie: Toate funciile de mai sus ignor valorile Null, excepie fcnd funcia COUNT. Pentru
a include n calcule i nregistrrile cu valoarea Null se poate folosi funcia NVL.
Dac nu este utilizat clauza GROUP BY, n lista de SELECT nu pot apare funcii de grup alturi de
nume de coloane sau alte expresii care iau valori pentru fiecare nregistrare n parte. De exemplu,
urmtoarea interogare va genera o eroare:
SQL> SELECT nume, MIN(salariu) FROM profesor;
ERROR at line 1:
ORA-00937: not a single-group group function
8.1.15 Pseudo-coloana ROWNUM
ROWNUM este o pseudo-coloan care numeroteaz rndurile selectate de o interogare. Astfel, pentru
primul rnd selectat pseudo-coloana ROWNUM are valoarea 1, pentru al doilea rnd are valoarea 2,
.a.m.d. De exemplu, pentru a limita rndurile selectate de o interogare la maxim 5, se folosete
urmtoarea comand:
SELECT *
FROM profesor
WHERE ROWNUM < 6;
Deoarece pseudo-coloana ROWNUM numeroteaz rndurile selectate, valorile sale vor trebui s
nceap tot timpul cu 1. Deci dac n exemplul de mai sus condiia ar fi ROWNUM > 6 sau ROWNUM =
6 interogarea nu ar selecta nici un rnd deoarece n acest caz condiia ar fi ntotdeauna fals. Pentru
primul rnd accesat de interogare ROWNUM va avea valoarea 1, condiia nu este ndeplinit i deci
rndul nu va fi selectat. Pentru al doilea rnd accesat de interogare ROWNUM va avea din nou
valoarea 1, condiia nu este ndeplinit nici n acest caz i deci nici acest rnd nu va fi selectat. Prin
urmare nici unul din rndurile accesate nu vor satisface condiia coninut de interogare.
Pseudo-coloana ROWNUM se poate folosi att n condiia unor comenzi UPDATE sau DELETE ct i
pentru a atribui valori unice unei coloane, ca n exemplul de mai jos:
UPDATE vanzari
SET cod = ROWNUM;
Valoarea pseudo-coloanei ROWNUM este atribuit unui rnd nainte ca acesta s fie sortat datorit
unei clauze ORDER BY, de aceea valorile pseudo-coloanei nu reprezint ordinea de sortare. De
exemplu
SQL> SELECT nume, prenume, ROWNUM FROM profesor ORDER BY salariu;
NUME
---------VOINEA
STANESCU
IONESCU
ALBU
MARIN
GEORGESCU
GHEORGHIU

PRENUME
---------MIRCEA
MARIA
VERONICA
GHEORGHE
VLAD
CRISTIANA
STEFAN

ROWNUM
--------6
7
4
5
2
3
1
186

8.1.16 Clauza GROUP BY


Clauza GROUP BY este utilizat pentru a mpri din punct de vedere logic un tabel n grupuri de
nregistrri. Fiecare grup este format din toate nregistrrile care au aceeai valoare n cmpul sau
grupul de cmpuri specificate n clauza GROUP BY. Unele nregistrri pot fi excluse folosind clauza
WHERE nainte ca tabelul s fie mprit n grupuri.
Clauza GROUP BY se folosete de obicei mpreun cu funciile de grup, acestea returnnd valoarea
calculat pentru fiecare grup n parte. n cazul folosirii clauzei GROUP BY, toate expresiile care
apar n lista de SELECT trebuie s aib o valoare unic pentru fiecare grup, de aceea orice coloan
sau expresie din aceast list care nu este o funcie de grup trebuie s apar n clauza GROUP BY.
Prezentm n continuare cteva exemple:
SQL> SELECT grad, AVG (salariu) FROM profesor GROUP BY grad;
GRAD
----ASIST
CONF
LECT
PROF

AVG(SALARIU)
-----------1300
2800
2200
2750

SQL> SELECT grad, MAX(salariu) FROM profesor WHERE prima is not NULL GROUP BY grad;
GRAD
----ASIST
CONF
LECT
PROF

MAX(SALARIU)
-----------1200
2800
2200
3000

Urmtoarea interogare va genera o eroare deoarece n lista de SELECT exist o coloan (nume)
care nu apare n clauza GROUP BY:
SQL> SELECT nume, MIN(salariu) FROM profesor GROUP BY grad;
ERROR at line 1:
ORA-00979: not a GROUP BY expression
Comanda de mai sus este invalid deoarece coloana nume are valori individuale pentru fiecare
nregistrare, n timp ce MIN(salariu) are o singur valoare pentru un grup.
Clauza GROUP BY permite apelarea unei funcii de grup n alt funcie de grup. n exemplul
urmtor, funcia AVG returneaz salariul mediu pentru fiecare grad didactic, iar funcia MAX
returneaz maximul dintre aceste salarii medii.
SQL> SELECT MAX(AVG(salariu)) from profesor
GROUP BY grad;

187

MAX(AVG(SALARIU))
----------------2800
8.1.17 Clauza HAVING
Clauza HAVING este tot o clauz de filtrare ca i clauza WHERE. Totui, n timp ce clauza WHERE
determin ce nregistrri vor fi selecionate dintr-un tabel, clauza HAVING determin care dintre
grupurile rezultate vor fi afiate dup ce nregistrrile din tabel au fost grupate cu clauza GROUP
BY. Cu alte cuvinte, pentru a exclude grupuri de nregistrri se folosete clauza HAVING iar pentru
a exclude nregistrri individuale se folosete clauza WHERE.
Clauza HAVING este folosit numai dac este folosit i clauza GROUP BY. Expresiile folosite ntro clauz HAVING trebuie s aib o singur valoare pe grup.
Atunci cnd se folosete clauza GROUP BY, clauza WHERE se utilizeaz pentru eliminarea
nregistrrilor ce nu se doresc a fi grupate. Astfel, urmtoarea interogare este invalid deoarece
clauza WHERE ncearc s exclud grupuri de nregistrri i nu anumite nregistrri:
SQL> SELECT grad, AVG(salariu) FROM profesor WHERE AVG(salariu)>2000 GROUP BY grad;
ERROR:
ORA-00934: group function is not allowed here
Pentru a exclude gradul didactic pentru care media de salariu nu este mai mare dect 2000 se
folosete urmtoarea comand SELECT cu clauza HAVING:
SQL> SELECT grad, AVG(salariu) FROM profesor GROUP BY grad HAVING AVG(salariu)>2000;
GRAD
----CONF
LECT
PROF

AVG(SALARIU)
-----------2800
2200
2750

Urmtoarea interogare exclude nti cadrele didactice care nu au salariu mai mare dect 2000 dup
care exclude gradul didactic pentru care media de salariu nu este mai mare dect 2500.
SQL> SELECT grad, AVG(salariu) FROM profesor WHERE salariu > 2000 GROUP BY grad
HAVING AVG(salariu) > 2500;
GRAD
----PROF

AVG(SALARIU)
-----------CONF 2800
2750

8.1.18 Regsirea datelor din dou sau mai multe tabele


O jonciune este o interogare care regsete nregistrri din dou sau mai multe tabele. Capacitatea
de a realiza o jonciune ntre dou sau mai multe tabele reprezint una dintre cele mai puternice
faciliti ale unui sistem relaional. Legtura dintre nregistrrile tabelelor se realizeaz prin

188

existena unor cmpuri comune caracterizate prin domenii de definiie compatibile (chei primare
sau strine). Pentru realizarea unei jonciuni se folosete clauza SELECT, preciznd n clauza FROM
numele tabelelor utilizate, iar n clauza WHERE criteriul de compunere.
Produsul a dou sau mai multe tabele.
n cazul n care n interogare se specific mai multe tabele i nu este inclus o clauz WHERE,
interogarea va genera produsul cartezian al tabelelor. Acesta va conine toate combinaiile posibile
de nregistrri din tabelele componente. Astfel, produsul cartezian a dou tabele care conin 100,
respectiv 50 de nregistrri va avea dimensiunea de 5.000 de nregistrri.
De exemplu, s considerm tabela CATEDRA cu urmtoarele 4 nregistrri:
COD_CATEDRA
----------10
20
30
40

NUME
----------INFORMATICA
ELECTRONICA
AUTOMATICA
FINANTE

PROFIL
--------TEHNIC
TENHIC
TENHIC
ECONOMIC

Atunci urmtoarea interogare va genera produsul cartezian al tabelelor, adic va avea ca rezultat 7 x
4 = 28 de rnduri ce vor conine toate combinaiile posibile de nregistrri din cele dou tabele:
SQL> SELECT * FROM profesor, catedra;
Dac n lista de SELECT sunt specificate coloanele selectate, atunci numele acestora trebuie s fie
unic n cadrul tuturor tabelelor. Dac exist un nume de coloan care apare n mai mult de un tabel,
atunci, pentru evitarea ambiguitii, trebuie specificat i tabelul din care face parte coloana n cauz.
De exemplu, n urmtoarea interogare pentru coloanele cod_catedra i nume trebuie specificate
tabelele din care fac parte:
SQL> SELECT profesor.nume, prenume, catedra.cod_catedra, catedra.nume FROM profesor,
catedra;
NUME
---------GHEORGHIU
MARIN
GEORGESCU
IONESCU
ALBU
VOINEA
STANESCU
GHEORGHIU
MARIN
GEORGESCU
IONESCU
ALBU
VOINEA
STANESCU
GHEORGHIU
MARIN

PRENUME
---------STEFAN
VLAD
CRISTIANA
VERONICA
GHEORGHE
MIRCEA
MARIA
STEFAN
VLAD
CRISTIANA
VERONICA
GHEORGHE
MIRCEA
MARIA
STEFAN
VLAD

COD_CATEDRA
----------10
10
10
10
10
10
10
20
20
20
20
20
20
20
30
30
189

NUME
----------INFORMATICA
INFORMATICA
INFORMATICA
INFORMATICA
INFORMATICA
INFORMATICA
INFORMATICA
ELECTRONICA
ELECTRONICA
ELECTRONICA
ELECTRONICA
ELECTRONICA
ELECTRONICA
ELECTRONICA
AUTOMATICA
AUTOMATICA

GEORGESCU
IONESCU
ALBU
VOINEA
STANESCU
GHEORGHIU
MARIN
GEORGESCU
IONESCU
ALBU
VOINEA
STANESCU

CRISTIANA
VERONICA
GHEORGHE
MIRCEA
MARIA
STEFAN
VLAD
CRISTIANA
VERONICA
GHEORGHE
MIRCEA
MARIA

30
30
30
30
30
40
40
40
40
40
40
40

AUTOMATICA
AUTOMATICA
AUTOMATICA
AUTOMATICA
AUTOMATICA
FINANTE
FINANTE
FINANTE
FINANTE
FINANTE
FINANTE
FINANTE

n general, pentru a scurta textul comenzii, n astfel de cazuri se folosesc de obicei aliasuri pentru
numele tabelelor, care pot fi folosite n interogare. Astfel interogarea de mai sus se mai poate scrie:
SQL> SELECT p.nume, prenume, c.cod_catedra, c.nume FROM profesor p, catedra c;
n general, produsul cartezian este rar folosit, avnd o utilitate practic redus.
Jonciuni
Pentru a realiza o jonciune ntre dou sau mai multe tabele se utilizeaz clauza WHERE a
interogrilor pe aceste tabele. n funcie de criteriul de compunere, se disting mai multe tipuri de
jonciuni:
1. jonciuni echivalente (EQUI -JOIN) sau jonciuni interne (INNER JOIN)
2. jonciuni neechivalente
3. jonciuni externe (OUTER JOIN)
4. auto-jonciuni
1. Jonciunile echivalente
O echi-jonciune conine operatorul egalitate (=) n clauza WHERE, combinnd nregistrrile din
tabele care au valori egale pentru coloanele specificate.
De exemplu, pentru a afia cadrele didactice i numele catedrei din care fac parte se combin
nregistrrile din cele dou tabele pentru care codul catedrei este acelai.
SQL> SELECT p.nume, p.prenume,
p.cod_catedra=c.cod_catedra;
NUME
---------GHEORGHIU
IONESCU
VOINEA
MARIN
STANESCU
ALBU
GEORGESCU

PRENUME
---------STEFAN
VERONICA
MIRCEA
VLAD
MARIA
GHEORGHE
CRISTIANA

c.nume

NUME
----------INFORMATICA
INFORMATICA
INFORMATICA
ELECTRONICA
ELECTRONICA
ELECTRONICA
AUTOMATICA

2. Jonciuni neechivalente
190

FROM

profesor

p,

catedra

WHERE

Jonciunile neechivalente sunt acelea care nu folosesc n clauza WHERE operatorul egal. Operatorii
cei mai utilizai n cazul jonciunilor neechivalente sunt: <, >, <=, >= ,<>, BETWEENAND.
Pentru a exemplifica un astfel de tip de jonciune considerm tabela GRADSAL ce conine pragul
minim i pragul maxim al salariului dintr-un anumit grad de salarizare:
GRAD_SALARIZARE
--------------1
2
3
4
5

PRAG_MIN
--------500
1501
2001
2501
3501

PRAG_MAX
--------1500
2000
2500
3500
10000

Evident, ntre tabelele PROFESOR i GRADSAL nu are sens definirea unei jonciuni echivalente
deoarece nu exist o coloan din tabela PROFESOR creia s-i corespund o coloan din tabela
GRADSAL. Exemplul urmtor ilustreaz definirea unei jonciuni neechivalente care evalueaz
gradul de salarizare a cadrelor didactice, prin ncadrarea salariului acestora ntr-un interval stabilit
de pragul minim i pragul maxim:
SQL> SELECT p.nume, p.grad, p.salariu, g.grad_salarizare FROM profesor p, gradsal g WHERE
p.salariu BETWEEN g.prag_min AND g.prag_max;
NUME
---------IONESCU
VOINEA
STANESCU
MARIN
ALBU
GHEORGHIU
GEORGESCU

GRAD
----ASIST
ASIST
ASIST
PROF
LECT
PROF
CONF

SALARIU
--------1500
1200
1200
2500
2200
3000
2800

GRAD_SALARIZARE
--------------1
1
1
3
3
4
4

3. Jonciuni externe
Dac ntr-o jonciune de tipul celor prezentate pn acum una sau mai multe nregistrri nu satisfac
condiia de compunere specificat n clauza WHERE, atunci ele nu vor aprea n rezultatul
interogrii. Aceste nregistrri pot apare ns dac se folosete jonciunea extern. Jonciunea
extern returneaz toate nregistrrile care satisfac condiia de jonciune plus acele nregistrri dintrun tabel ale cror valori din coloanele dup care se face legtura nu se regsesc n coloanele
corespunztoare ale nici unei nregistrri din celalalt tabel.
Pentru a realiza o jonciune extern ntre tabelele A i B ce returneaz toate nregistrrile din tabela
A se utilizeaz semnul (+) n dreapta tabelului B. Pentru fiecare nregistrare din tabela A care nu
satisface condiia de compunere pentru nici o nregistrare din tabela B se va crea n tabela B o
nregistrare nul care va fi compus cu nregistrarea din tabela A. Invers, pentru a realiza o
jonciune extern ntre tabelele A i B ce returneaz toate nregistrrile din tabela B, se utilizeaz
semnul (+) n dreapta tabelului A.

191

n interogarea utilizat pentru a exemplifica jonciunea echivalent, se observ c au fost selectate


numai catedrele n care exist cadre didactice. Pentru a afia toate catedrele, indiferent dac ele
cuprind sau nu cadre didactice, se folosete urmtoarea interogare:
SQL> SELECT p.nume, p.prenume,
p.cod_catedra(+)=c.cod_catedra;
NUME
---------GHEORGHIU
IONESCU
VOINEA
MARIN
STANESCU
ALBU
GEORGESCU

PRENUME
---------STEFAN
VERONICA
MIRCEA
VLAD
MARIA
GHEORGHE
CRISTIANA

c.nume

FROM

profesor

p,

catedra

WHERE

NUME
----------INFORMATICA
INFORMATICA
INFORMATICA
ELECTRONICA
ELECTRONICA
ELECTRONICA
AUTOMATICA
FINANTE

Se observ c ultima nregistrare (ce corespunde catedrei de finane care nu are n componen nici
un cadru didactic) va avea coloanele corespunztoare primului tabel completate cu Null.
Folosirea operatorului de jonciune extern are urmtoarele restricii:
1. Operatorul (+) poate fi plasat n oricare parte a condiiei din clauza WHERE, ns nu n ambele
pri. Tabelul de partea cruia este amplasat acest operator va crea nregistrri nule care vor fi
compuse cu nregistrrile din cellalt tabel care nu satisfac condiia de compunere.
2. Daca tabelele A i B au condiii multiple de jonciune, atunci operatorul (+) trebuie utilizat n
toate aceste condiii;
3. ntr-o singur interogare nu se poate realiza o jonciune extern a unui tabel cu mai multe tabele.
4. O condiie care conine operatorul (+) nu poate fi combinat cu o alt condiie ce utilizeaz
operatorul IN.
5. O condiie care conine operatorul (+) nu poate fi combinat cu o alt condiie prin operatorul
OR.
4. Auto-jonciuni
Auto-jonciunea reprezint jonciunea unui tabel cu el nsui. Pentru ca rndurile dintr-un tabel s
poat fi compuse cu rnduri din acelai tabel, n clauza FROM a interogrii numele tabelului va
apare de mai multe ori, urmat de fiecare dat de un alias.
De exemplu, pentru a selecta toate cardele didactice care au un ef direct i numele acestui ef se
folosete urmtoarea auto-jonciune:
SQL> SELECT p.nume, p.prenume, s.nume, s.prenume FROM profesor p, profesor s WHERE
p.sef=s.cod;
NUME
---------MARIN
GEORGESCU
ALBU
VOINEA
IONESCU

PRENUME
---------VLAD
CRISTIANA
GHEORGHE
MIRCEA
VERONICA

NUME
---------GHEORGHIU
GHEORGHIU
GHEORGHIU
GHEORGHIU
GEORGESCU

PRENUME
---------STEFAN
STEFAN
STEFAN
STEFAN
CRISTIANA
192

STANESCU

MARIA

IONESCU

VERONICA

Auto-jonciunea poate fi folosit i pentru verificarea corectitudinii interne a datelor. De exemplu,


este puin probabil s existe dou cadre didactice care au cod diferit dar n schimb au acelai nume,
prenume i dat de natere. Pentru a verifica dac exist astfel de nregistrri se folosete
interogarea:
SQL> SELECT a.nume, a.prenume FROM profesor a, profesor b WHERE
a.nume=b.nume AND a.prenume=b.prenume AND
a.data_nast=b.data_nast AND a.cod<>b.cod;
8.1.19. Operatorii pentru mulimi
Operatorii de mulimi combin dou sau mai multe interogri, efectund operaii specifice
mulimilor: reuniune, intersecie, diferen. Aceti operatori se mai numesc i operatori verticali
deoarece combinarea celor dou interogri se face coloan cu coloan. Din acest motiv, numrul
total de coloane i tipurile de date ale coloanelor corespondente din cele dou interogri trebuie s
coincid.
Exist urmtorii operatori pentru mulimi:
1. UNION Returneaz rezultatele a dou sau mai multe interogri eliminnd toate nregistrrile
duplicat;
2. UNION ALL Returneaz rezultatele a dou sau mai multe interogri incluznd nregistrrile
duplicat;
3. INTERSECT Returneaz toate nregistrrile distincte gsite n ambele interogri;
4. MINUS Returneaz toate nregistrrile distincte care se gsesc n prima interogare dar nu i n
a doua interogare.
S considerm de exemplu urmtoarele interogri:
SQL> SELECT grad, salariu FROM profesor WHERE cod_catedra = 10;
GRAD
----PROF
ASIST
ASIST

SALARIU
--------3000
1500
1200

SQL> SELECT grad, salariu FROM profesor WHERE cod_catedra = 20;


GRAD
----PROF
LECT
ASIST

SALARIU
--------2500
2200
1200

n continuare exemplificm fiecare dintre operatorii pentru mulimi aplicai acestor interogri:
SQL> SELECT grad, salariu FROM profesor WHERE cod_catedra = 10
UNION
SELECT grad, salariu FROM profesor WHERE cod_catedra = 20;

193

GRAD
----ASIST
ASIST
LECT
PROF
PROF

SALARIU
--------1200
1500
2200
2500
3000

SQL> SELECT grad, salariu FROM profesor WHERE cod_catedra = 10


UNION ALL
SELECT grad, salariu FROM profesor WHERE cod_catedra = 20;
GRAD
----PROF
ASIST
ASIST
PROF
LECT
ASIST

SALARIU
--------3000
1500
1200
2500
2200
1200

SQL> SELECT grad, salariu FROM profesor WHERE cod_catedra = 10


INTERSECT
SELECT grad, salariu FROM profesor WHERE cod_catedra = 20;
GRAD
----ASIST

SALARIU
--------1200

SQL> SELECT grad, salariu FROM profesor WHERE cod_catedra = 10


MINUS
SELECT grad, salariu FROM profesor WHERE cod_catedra = 20;
GRAD
----ASIST
PROF

SALARIU
--------1500
3000

Exist urmtoarele reguli de folosire a operatorilor pentru mulimi:


interogrile trebuie s conin acelai numr de coloane;
coloanele corespondente trebuie s aib acelai tip de dat;
n rezultat vor aprea numele coloanelor din prima interogare, nu cele din a doua interogare
chiar dac aceasta folosete alias-uri; de exemplu:
SQL> SELECT cod FROM profesor
MINUS
SELECT sef FROM profesor;
COD
--------101
104
194

105
106

clauza ORDER BY poate fi folosit o singur dat ntr-o interogare care folosete operatori de
mulimi; atunci cnd se folosete, ea trebuie poziionat la sfritul comenzii; de exemplu:

SQL> SELECT grad, salariu FROM profesor WHERE cod_catedra = 10


UNION
SELECT grad, salariu FROM profesor WHERE cod_catedra = 20
ORDER BY 2;
GRAD
----ASIST
ASIST
LECT
PROF
PROF

SALARIU
--------1200
1500
2200
2500
3000

operatorii pentru mulimi pot fi utilizai n subinterogri;


pentru a modifica ordinea de execuie este posibil utilizarea parantezelor; de exemplu:

SQL> SELECT grad FROM profesor WHERE cod_catedra = 10


INTERSECT
SELECT grad FROM profesor WHERE cod_catedra = 20
UNION
SELECT grad FROM profesor WHERE cod_catedra = 30;
GRAD
----ASIST
CONF
PROF
SQL> SELECT grad FROM profesor WHERE cod_catedra = 10
INTERSECT
(SELECT grad FROM profesor WHERE cod_catedra = 20
UNION
SELECT grad FROM profesor WHERE cod_catedra = 30);
GRAD
----ASIST
PROF
8.1.20. Subinterogri i operatorii ANY, ALL, EXISTS

195

O subinterogare este o comand SELECT inclus n alt comand SELECT. Rezultatele


subinterogrii sunt transmise celeilalte interogri i pot aprea n cadrul clauzelor WHERE, HAVING
sau FROM. Subinterogrile sunt utile pentru a scrie interogri bazate pe o condiie n care valoarea
de comparaie este necunoscut. Aceast valoare poate fi aflat folosind o subinterogare. De
exemplu:
SELECT coloane
FROM tabel
WHERE coloana = (SELECT coloane
FROM tabel
WHERE condiie)
Subinterogarea, denumit i interogare interioar (inner query), genereaz valorile pentru condiia
de cutare a instruciunii SELECT care o conine, denumit interogare exterioar (outer query).
Instruciunea SELECT exterioar depinde de valorile generate de ctre interogarea interioar. n
general, interogarea interioar se execut prima i rezultatul acesteia este utilizat n interogarea
exterioar. Rezultatul interogrii exterioare depinde de numrul valorilor returnate de ctre
interogarea interioar. n acest sens, putem distinge:
1. Subinterogri care returneaz un singur rnd;
2. Subinterogri care returneaz mai multe rnduri.
Din punct de vedere al ordinii de evaluare a interogrilor putem clasifica subinterogrile n:
1. Subinterogri simple n care interogarea interioar este evaluat prima, independent de
interogarea exterioar (interogarea interioar se execut o singur dat);
2. Subinterogri corelate n care valorile returnate de interogarea interioar depind de valorile
returnate de interogarea exterioar (interogarea interioar este evaluat pentru fiecare nregistrare a
interogrii exterioare).
Subinterogrile sunt ndeosebi utilizate atunci cnd se dorete ca o interogare s regseasc
nregistrri dintr-o tabel care ndeplinesc o condiie ce depinde la rndul ei de valori din aceeai
tabel.
Observaie: Clauza ORDER BY nu poate fi utilizat ntr-o subinterogare. Regula este c poate exista
doar o singur clauz ORDER BY pentru o declaraie SELECT i, dac este specificat, trebuie s fie
ultima clauz din comanda SELECT. Prin urmare, clauza ORDER BY nu poate fi specificat dect n
interogarea cea mai din exterior.
Subinterogri care returneaz un singur rnd
n acest caz condiia, din clauza WHERE sau HAVING a interogrii exterioare utilizeaz operatorii:
=, <, <=, >, >=, <> care opereaz asupra unei subinterogri ce returneaz o singur valoare.
Interogarea interioar poate conine condiii complexe formate prin utilizarea condiiilor multiple de
interogare cu ajutorul operatorilor AND i OR sau prin utilizarea funciilor agregat.
Urmtoarea interogare selecteaz cadrele didactice care salariul minim. Salariul minim este
determinat de o subinterogare ce returneaz o singur valoare.
SQL> SELECT nume, prenume, salariu FROM profesor
WHERE salariu = (SELECT MIN(salariu) FROM profesor);

196

NUME
---------VOINEA
STANESCU

PRENUME
---------MIRCEA
MARIA

SALARIU
--------1200
1200

Procesul de evaluare al acestei interogri se desfoar astfel:


se evalueaz n primul rnd interogarea interioar:
Valoarea obinut este MIN(salariu)=1200
rezultatul evalurii interogrii interioare devine condiie de cutare pentru interogarea exterioar
i anume: SELECT nume, prenume, salariu FROM profesor WHERE salariu =1200;
n cazul n care interogarea interioar nu ntoarce nici o nregistrare, interogarea exterioar nu va
selecta la rndul ei nici o nregistrare.
Observaie: Dac care se utilizeaz operatorii: =, <, <=, >, >=, <> n condiia interogrii exterioare,
atunci interogarea interioar trebuie n mod obligatoriu s returneze o singur valoare. n caz
contrar va aprea un mesaj de eroare, ca n exemplul urmtor:
SQL> SELECT nume, prenume, salariu FROM profesor
WHERE salariu = (SELECT MIN (salariu) FROM profesor GROUP BY grad);
ERROR:
ORA-01427: single-row subquery returns more than one row
Subinterogrile pot fi folosite nu numai n clauza WHERE a interogrii exterioare, ci i n clauza
HAVING. Urmtoarea interogare afieaz toate gradele didactice pentru care salariul minim este
mai mare dect salariul mediu al tuturor cadrelor didactice.
SQL> SELECT grad FROM profesor GROUP BY grad HAVING min(salariu) > (SELECT
avg(salariu) FROM profesor);
GRAD
----CONF
LECT
PROF
Subinterogri care returneaz mai multe rnduri
n cazul cnd interogarea ntoarce mai multe rnduri nu mai este posibil folosirea operatorilor de
comparaie. n locul acestora se folosete operatorul IN, care ateapt o list de valori i nu doar
una.
Urmtoarea interogare selecteaz pentru fiecare grad didactic acele persoane care au salariul minim.
Salariul minim pentru fiecare grad didactic este aflat printr-o subinterogare, care, evident, va
ntoarce mai multe rnduri:
SQL> SELECT nume, salariu, grad FROM profesor
WHERE (salariu, grad) IN
(SELECT MIN (salariu), grad FROM profesor GROUP BY grad)
ORDER BY salariu;

197

NUME
---------VOINEA
STANESCU
ALBU
MARIN
GEORGESCU

SALARIU
--------1200
1200
2200
2500
2800

GRAD
----ASIST
ASIST
LECT
PROF
CONF

Observaie: Spre deosebire de celelalte interogri de pn acum, interogarea de mai sus compar
perechi de coloane. n acest caz trebuiesc respectate urmtoarele reguli:
coloanele din dreapta condiiei de cutare sunt n paranteze i fiecare coloan este separat prin
virgul;
coloanele returnate de interogarea interioar trebuie s se potriveasc ca numr i tip cu
coloanele cu care sunt comparate n interogarea exterioar; n plus, ele trebuie s fie n aceeai
ordine cu coloanele cu care sunt comparate.
Alturi de operatorul IN, o subinterogare care returneaz mai multe rnduri poate folosi operatorii
ANY, ALL sau EXISTS. Operatorii ANY i ALL sunt prezentai n continuare, iar operatorul
EXISTS va fi prezentat n seciunea Subinterogri corelate.
Operatorii ANY i ALL sunt folosii n mod obligatoriu n combinaie cu operatorii relaionali =, !=,
<, >, <=, >=; operatorii IN i EXISTS nu pot fi folosii n combinaie cu operatorii relaionali, dar
pot fi utilizai cu operatorul NOT, pentru negarea expresiei.
Operatorul ANY
Operatorul ANY (sau sinonimul su SOME) este folosit pentru a compara o valoare cu oricare dintre
valorile returnate de o subinterogare. Pentru a nelege modul de folosire a acestui operator s
considerm urmtorul exemplu ce afieaz cadrele didactice ce ctig mai mult dect profesorii
care au cel mai mic salariu:
SQL> SELECT nume, salariu, grad FROM profesor
WHERE salariu > ANY
(SELECT DISTINCT salariu FROM profesor WHERE grad=PROF);
NUME
---------GHEORGHIU
GEORGESCU

SALARIU
--------3000
2800

GRAD
---PROF
CONF

Interogarea de mai sus este evaluat astfel: dac salariul unui cadru didactic este mai mare dect cel
puin unul din salariile returnate de interogarea interioar, acea nregistrare este inclus n rezultat.
Cu alte cuvinte, >ANY nsemn mai mare dect minimul dintre valorile returnate de interogarea
interioar, <ANY nseamn mai mic ca maximul, iar =ANY este echivalent cu operatorul IN.
Observaie: opiunea DISTINCT este folosit frecvent atunci cnd se folosete operatorul ANY
pentru a preveni selectarea de mai multe ori a unor nregistrri.
Operatorul ALL

198

Operatorul ALL este folosit pentru a compara o valoare cu toate valorile returnate de o
subinterogare. Considerm urmtorul exemplu ce afieaz cadrele didactice care ctig mai mult
dect asistenii cu salariul cel mai mare:
SQL> SELECT nume, salariu, grad FROM profesor
WHERE salariu > ALL
(SELECT DISTINCT salariu FROM profesor WHERE grad=ASIST);
NUME
---------GHEORGHIU
MARIN
GEORGESCU
ALBU

SALARIU
--------3000
2500
2800
2200

GRAD
----PROF
PROF
CONF
LECT

Interogarea de mai sus este evaluat astfel: dac salariul unui cadru didactic este mai mare dect
toate valorile returnate de interogarea interioar, acea nregistrare este inclus n rezultat. Cu alte
cuvinte, >ALL nseamn mai mare ca maximul dintre valorile returnate de interogarea interioar iar
<ALL nseamn mai mic ca minimul dintre acestea.
Observaie: operatorul ALL nu poate fi utilizat cu operatorul = deoarece interogarea nu va ntoarce
nici un rezultat cu excepia cazului n care toate valorile sunt egale, situaie care nu ar avea sens.
Subinterogrile pot fi imbricate (utilizate cu alte subinterogri) pn la 255 de nivele, indiferent de
numrul de valori returnate de fiecare subinterogare. Pentru a selecta cadrele didactice care au
salariul mai mare dect cel mai mare salariu al cadrelor didactice care aparin catedrei de
Electronic, vom folosi urmtoarea interogare:
SQL> SELECT nume, prenume, salariu FROM profesor
WHERE salariu > (SELECT MAX(salariu) FROM profesor
WHERE cod_catedra = (SELECT cod_catedra FROM catedra
nume='ELECTRONIC'));
NUME
---------GHEORGHIU
GEORGESCU

PRENUME
---------STEFAN
CRISTIANA

WHERE

SALARIU
--------3000
2800

Subinterogri corelate
n exemplele considerate pn acum interogarea interioar era evaluat prima, dup care valoarea
sau valorile rezultate erau utilizate de ctre interogarea exterioar. Subinterogrile de acest tip sunt
numite subinterogri simple. O alt form de subinterogare o reprezint interogarea corelat, caz n
care interogarea exterioar transmite repetat cte o nregistrare pentru interogarea interioar.
Interogarea interioar este evaluat de fiecare dat cnd este transmis o nregistrare din interogarea
exterioar, care se mai numete i nregistrare candidat. Subinterogarea corelat poate fi
identificat prin faptul c interogarea interioar nu se poate executa independent ci depinde de
valoarea transmis de ctre interogarea exterioar. Dac ambele interogri acceseaz aceeai tabel,
trebuiesc asigurate alias-uri pentru fiecare referire la tabela respectiv.
Subinterogrile corelate reprezint o cale de a accesa fiecare nregistrare din tabel i de a compara
anumite valori ale acesteia cu valori ce depind tot de ea.
199

Evaluarea unei subinterogri corelate se execut n urmtorii pai:


1. Interogarea exterioar trimite o nregistrare candidat ctre interogarea interioar;
2. Interogarea interioar se execut n funcie de valorile nregistrrii candidate;
3. Valorile rezultate din interogarea interioar sunt utilizate pentru a determina dac nregistrarea
candidat va fi sau nu inclus n rezultat;
4. Se repet procedeul ncepnd cu pasul 1 pn cnd nu mai exist nregistrri candidate.
De exemplu pentru a regsi cadrele didactice care ctig mai mult dect salariul mediu din propria
catedr, putem folosi urmtoarea interogare corelat:
SQL> SELECT nume, prenume, salariu FROM profesor p
WHERE salariu > (SELECT AVG(salariu) FROM profesor
WHERE cod_catedra = p.cod_catedra);
NUME
----------------GHEORGHIU
MARIN
ALBU

PRENUME
--------------STEFAN
VLAD
GHEORGHE

SALARIU
-----------3000
2500
2200

n exemplul de mai sus coloana interogrii exterioare care se folosete n interogarea interioar este
p.cod_catedra. Deoarece p.cod_catedra poate avea valoare diferit pentru fiecare
nregistrare, interogarea interioar se execut pentru fiecare nregistrare candidat transmis de
interogarea exterioar.
Atunci cnd folosim subinterogri corelate mpreun cu clauza HAVING, coloanele utilizate n
aceast clauz trebuie s se regseasc n clauza GROUP BY. n caz contrar, va fi generat un mesaj
de eroare datorat faptului c nu se poate face comparaie dect cu o expresie de grup. De exemplu,
urmtoarea interogare este corect, ea selectnd gradele didactice pentru care media salariului este
mai mare dect maximul primei pentru acelai grad:
SQL> SELECT grad FROM profesor p
GROUP BY grad
HAVING AVG(salariu) > (SELECT MAX(prima) FROM profesor
WHERE grad = p.grad);
Operatorul EXISTS
Operatorul EXISTS verific dac, pentru fiecare nregistrare transmis de interogarea exterioar,
exist sau nu nregistrri care satisfac condiia interogrii interioare, returnnd interogrii exterioare
valoarea TRUE sau FALSE. Cu alte cuvinte, operatorul EXISTS cere n mod obligatoriu corelarea
interogrii interioare cu interogarea exterioar. Datorit faptului c operatorul EXISTS verific
doar existena rndurilor selectate i nu ia n considerare numrul sau valorile atributelor selectate,
n subinterogare pot fi specificate orice numr de atribute; n particular, poate fi folosit o constant
i chiar simbolul * (dei acest lucru nu este recomandabil din punct de vedere al eficienei). De
altfel EXISTS este singurul operator care permite acest lucru.
Urmtoarea interogare selecteaz toate cadrele didactice care au mcar un subordonat:
SQL> SELECT cod, nume, prenume, grad FROM profesor p

200

WHERE EXISTS
(SELECT '1' FROM profesor
WHERE profesor.sef = p.cod)
ORDER BY cod;
COD
---100
102
103

NUME
---------GHEORGHIU
GEORGESCU
IONESCU

PRENUME
---------STEFAN
CRISTIANA
VERONICA

GRAD
----PROF
CONF
ASIST

La fel ca i operatorul IN, operatorul exists poate fi negat, lund forma NOT EXISTS. Totui, o
remarc foarte important este faptul c pentru subinterogri NOT IN nu este la fel de eficient ca
NOT EXISTS. Astfel dac n lista de valori transmis operatorului NOT IN exist una sau mai
multe valori Null, atunci condiia va lua valoarea de adevr FALSE, indiferent de celelalte valori
din list.
De exemplu, urmtoarea interogare ncearc s returneze toate cadrele didactice care nu au nici un
subaltern:
SQL> SELECT nume, grad FROM profesor
WHERE cod NOT IN (SELECT sef FROM profesor);
Aceast interogri nu va ntoarce nici o nregistrare deoarece coloana sef conine i valoarea Null.
Pentru a obine rezultatul corect trebuie s folosim urmtoarea interogare:
SQL> SELECT nume, grad FROM profesor p
WHERE NOT EXISTS (SELECT sef FROM profesor WHERE sef=p.cod);
NUME
---------MARIN
ALBU
VOINEA
STANESCU

GRAD
----PROF
LECT
ASIST
ASIST

n general, operatorul EXISTS se folosete n cazul subinterogrilor corelate i este cteodat cel
mai eficient mod de a realiza anumite interogri. Performana interogrilor depinde de folosirea
indecilor, de numrul rndurilor returnate, de dimensiunea tabelei i de necesitatea crerii tabelelor
temporare pentru evaluarea rezultatelor intermediare. Tabelele temporare generate de Oracle nu
sunt indexate, iar acest lucru poate degrada performana subinterogrilor dac se folosesc operatorii
IN, ANY sau ALL.
Subinterogrile mai pot aprea i n alte comenzi SQL cum ar fi: UPDATE, DELETE, INSERT i
CREATE TABLE.
Aa cum am vzut, exist n principal dou moduri de realizare a interogrilor ce folosesc date din
mai multe tabele: jonciuni i subinterogri. Jonciunile reprezint forma de interogare relaional
(n care sarcina gsirii drumului de acces la informaie revine SGBD-ului) iar subinterogrile forma
procedural (n care trebuie indicat drumul de acces la informaie). Fiecare dintre aceste forme are
avantajele sale, depinznd de cazul specific n care se aplic.

201

8.1.21 Operaii pe tabele ce conin informaii de structur arborescent


O baz de date relaional nu poate stoca nregistrri n mod ierarhic, dar la nivelul nregistrrii pot
exista informaii care determin o relaie ierarhic ntre nregistrri. SQL permite afiarea rndurilor
dintr-o tabel innd cont de relaiile ierarhice care apar ntre rndurile tabelei. Parcurgerea n mod
ierarhic a informaiilor se poate face doar la nivelul unei singure tabele. Operaia se realizeaz cu
ajutorul clauzelor START WITH i CONNECT BY din comanda SELECT.
De exemplu, n tabela PROFESOR exist o relaie ierarhic ntre nregistrri datorat valorilor din
coloanele cod i sef. Fiecare nregistrare aferent unui cadru didactic conine n coloana sef
codul persoanei creia i este direct subordonat. Pentru a obine o situaie ce conine nivelele
ierarhice, vom folosi urmtoarea interogare:
SQL> SELECT LEVEL, nume, prenume, grad FROM profesor
CONNECT BY PRIOR cod=sef
START WITH sef IS NULL;
LEVEL
--------1
2
2
3
4
2
2

NUME
---------GHEORGHIU
MARIN
GEORGESCU
IONESCU
STANESCU
ALBU
VOINEA

PRENUME
---------STEFAN
VLAD
CRISTIANA
VERONICA
MARIA
GHEORGHE
MIRCEA

GRAD
----PROF
PROF
CONF
ASIST
ASIST
LECT
ASIST

Explicarea sintaxei i a regulilor de funcionare pentru exemplul de mai sus:


Clauza standard SELECT poate conine pseudo-coloana LEVEL ce indic nivelul nregistrrii n
arbore (ct de departe este de nodul rdcin). Astfel, nodul rdcin are nivelul 1, fiii acestuia
au nivelul 2, .a.m.d.;
n clauza FROM nu se poate specifica dect o tabel;
Clauza WHERE poate aprea n interogare pentru a restriciona vizitarea nodurilor
(nregistrrilor) din cadrul arborelui;
Clauza CONNECT BY specific coloanele prin care se realizeaz relaia ierarhic; acesta este
clauza cea mai important pentru parcurgerea arborelui i este obligatorie;
Operatorul PRIOR stabilete direcia n care este parcurs arborele. Dac clauza apare nainte de
atributul cod arborele este parcurs de sus n jos, iar dac apare nainte de atributul sef arborele
este parcurs de jos n sus;
Clauza START WITH specific nodul (nregistrarea) de nceput al arborelui. Ca punct de start nu
se poate specifica un anumit nivel (LEVEL), ci trebuie specificat valoarea; aceast clauz este
opional, dac ea lipsete, pentru fiecare nregistrare se va parcurge arborele care are ca
rdcin aceast nregistrare.
n sintaxa interogrii de mai sus, pentru a ordona nregistrrile returnate, poate aprea clauza
ORDER BY, dar este recomandabil s nu o folosim deoarece ordinea implicit de parcurgere a
arborelui va fi distrus.

202

Pentru a elimina doar un anumit nod din arbore putem folosi clauza WHERE, iar pentru a elimina o
ntreag ramur dintr-un arbore (o anumit nregistrare mpreun cu fii acesteia) folosim o condiie
compus n clauza CONNECT BY.
Urmtorul exemplu elimin doar nregistrarea cu numele GEORGESCU, dar nu i copii acesteia:
SQL> SELECT LEVEL, nume, prenume, grad FROM profesor
WHERE nume != 'GEORGESCU'
CONNECT BY PRIOR cod=sef
START WITH sef IS NULL;
LEVEL
-----1
2
3
4
2
2

NUME
---------GHEORGHIU
MARIN
IONESCU
STANESCU
ALBU
VOINEA

PRENUME
---------STEFAN
VLAD
VERONICA
MARIA
GHEORGHE
MIRCEA

GRAD
----PROF
PROF
ASIST
ASIST
LECT
ASIST

Pentru a elimina toat ramura care conine nregistrarea cu numele GEORGESCU i nregistrrile
pentru subordonaii acesteia se folosete urmtoarea interogare:
SQL> SELECT LEVEL, nume, prenume, grad FROM profesor
CONNECT BY PRIOR cod=sef AND nume != 'GEORGESCU'
START WITH sef IS NULL;
LEVEL
----1
2
2
2

NUME
---------GHEORGHIU
MARIN
ALBU
VOINEA

PRENUME
---------STEFAN
VLAD
GHEORGHE
MIRCEA

GRAD
----PROF
PROF
LECT
ASIST

8.2 Comanda INSERT


Aceast comand este utilizat pentru adugarea unor rnduri noi ntr-o tabel creat anterior sau n
tabelele de baz ale unei vederi. Comanda INSERT poate fi utilizat n dou moduri:
1. Pentru introducerea datelor ntr-un tabel, cte o nregistrare la un moment dat. n acest caz
sintaxa este urmtoarea:
INSERT INTO tabela [(coloana1, coloana 2, .)]
VALUES (valoare1, valoare2, );
n momentul inserrii datelor, trebuie respectate urmtoarele reguli:
coloanele pot fi specificate n orice ordine, ns trebuie asigurat corespondena ntre coloane i
valorile furnizate (coloanei 1 i corespunde valoarea 1, coloanei 2 i corespunde valoarea 2,
.a.m.d.) iar coloanelor nespecificate le va fi ataat valoarea Null;
n cazul n care coloanele nu sunt specificate explicit, se impune ca ordinea n care apar valorile
n comanda INSERT s coincid cu cea n care coloanele au fost definite la crearea tabelei

203

(dac nu se cunoate ordinea de declarare a coloanelor se poate folosi comanda DESCRIBE


nume_tabela care va afia lista coloanelor definite pentru tabela respectiv, tipul, lungimea
i restriciile de integritate);
valorile trebuie s aib acelai tip de dat ca i cmpurile n care sunt adugate;
dimensiunea valorilor introduse trebuie s fie mai mic sau cel mult egal cu dimensiunea
coloanei (un ir de 20 de caractere nu poate fi adugat ntr-o coloan cu dimensiunea de 15
caractere);
valorile introduse trebuie s respecte restriciile de integritate definite la crearea tabelei (de
exemplu, cmpuri definite ca NOT NULL sau UNIQUE).

Atunci cnd se insereaz valori de tip dat calendaristic n format predefinit (DD-MON-YY),
sistemul presupune n mod automat secolul 20, ora 00:00:00 (miezul nopii)
Urmtoarea instruciune exemplific introducerea unei noi nregistrri n tabela profesor:
SQL> INSERT INTO profesor (cod, nume, prenume, data_nast, sef,
salariu, cod_catedra)
VALUES (107,
'POPESCU', 'SERGIU', '09-DEC-71', 100, 1200,
20);
Se poate observa c valorile coloanelor grad i prim, care nu au fost specificate, vor fi Null.
n cazul n care nu se specific implicit numele coloanelor, valorile trebuie introduse n ordinea n
care au fost definite i nu se poate omite valoarea nici unei coloane. Urmtoarea instruciune va
produce acelai efect ca cea de mai sus:
SQL> INSERT INTO profesor
VALUES (107,
'POPESCU', 'SERGIU', '09-DEC-71', NULL, 100,
1200,
NULL, 20);
2. Pentru introducerea datelor ntr-un tabel, prin copierea mai multor nregistrri dintr-un alt tabel
sau grup de tabele; aceste nregistrri sunt rezultatul unei comenzi SELECT. n acest caz sintaxa
este urmtoarea:
INSERT INTO tabela [(coloana1, coloana 2, .)]
comanda_select;
i n acest caz trebuie respectate regulile de inserare, singura diferen fiind faptul c valorile noi
introduse sunt extrase cu ajutorul unei interogri, acest lucru crend posibilitatea de inserare a mai
multor nregistrri n funcie de anumite condiii.
De exemplu, pentru a insera n tabela nou_profesor, avnd coloanele cod, nume, prenume
i data_nastere, nregistrrile din tabela profesor care au gradul didactic de asistent se
poate folosi urmtoarea instruciune:
SQL> INSERT INTO nou_profesor (cod, nume, prenume, data_nastere)
SELECT cod, nume, prenume, data_nast FROM profesor
WHERE grad=ASIST;
8.3 Comanda UPDATE

204

Comanda UPDATE este folosit pentru a modifica valorile datelor existente ntr-un tabel sau n
tabelele de baz ale unei vederi i are urmtoarea sintax general:
UPDATE tabela [alias]
SET atribuire_coloane, [atribuire_coloane, ]
[WHERE condiie];
unde atribuire_coloane poate avea una dintre urmtoarele forme:
coloana = {expresie | (subinterogare)}
sau
(coloana [,coloana] ...) = (subinterogare)
Se observ c exist dou posibiliti de modificare:
furnizarea n mod explicit a fiecrei valori sau expresii pentru cmpurile ce trebuiesc
modificate;
obinerea valorilor cu ajutorul unei subinterogri.
Comanda UPDATE modific valorile nregistrrilor n funcie de condiia clauzei WHERE. n lipsa
clauzei WHERE, vor fi actualizate toate nregistrrile din tabelul dat.
Expresia furnizat ca nou valoare a unei coloane poate cuprinde valorile curente ale cmpurilor din
nregistrarea care este actualizat. De exemplu, pentru a mri salariul cu 20% i prima cu 100 pentru
cadrele didactice ce au gradul de asistent, se va folosi urmtoarea comand:
SQL> UPDATE profesor
SET salariu=salariu*1.2,
prima=prima+100
WHERE grad=ASIST;
Pentru a exemplifica actualizarea datelor utiliznd subinterogri presupunem c mai avem o tabel
numit PRIMA ce conine sumele de bani primite suplimentar de unele cadre didactice:
COD
--------102
103
102

PRIMA
------------100
200
50

Pentru a modifica datele din tabela PROFESOR pe baza datelor din tabela PRIMA se poate folosi
urmtoarea comand care conine o subinterogare corelat i o subinterogare imbricat:
SQL> UPDATE profesor
SET prima=(SELECT SUM(prima)
FROM prima a
WHERE a.cod=profesor.cod)
WHERE cod IN (SELECT cod FROM prima);
O alt posibilitate este ca sumele suplimentare coninute n tabela PRIMA s fie adugate la prima
existent n tabela PROFESOR:

205

SQL> UPDATE profesor


SET prima=(SELECT SUM (prima) + profesor.prima
FROM prima a
WHERE a.cod=profesor.cod)
WHERE cod IN (SELECT cod FROM prima);
S presupunem acum c toi asistenii sunt transferai la catedra din care face parte cadrul didactic
cu codul 104 i vor primi acelai salariu cu acesta:
SQL> UPDATE profesor
SET (cod_catedra, salariu) = (SELECT cod_catedra, salariu
FROM profesor
WHERE cod= 104)
WHERE grad = ASIST;
8.4 Comanda DELETE
Comanda DELETE realizeaz tergerea nregistrrilor dintr-o tabel sau din tabelele de baz ale
unei vederi n funcie de o anumit condiie i are urmtoarea sintax general:
DELETE FROM tabela
[WHERE condiie];
Similar comenzii UPDATE, comanda DELETE terge anumite nregistrri n funcie de condiia din
clauza WHERE. n lipsa clauzei WHERE vor fi terse toate nregistrrile din tabelul dat. n aceast
clauz pot fi incluse i subinterogri.
De exemplu urmtoarea comand terge toate nregistrrile pentru care gradul didactic este asistent
SQL> DELETE FROM profesor
WHERE grad=ASIST;
Observaii: Comanda DELETE nu poate fi folosit pentru tergerea valorii unui cmp individual
(pentru aceasta folosii comanda UPDATE) ci terge nregistrri complete dintr-un singur tabel. n
plus, comanda DELETE terge numai nregistrri din tabel nu i tabelul. Pentru a terge un tabel se
folosete comanda DROP TABLE.
Un alt aspect important este faptul c, similar comenzilor INSERT i UPDATE, tergerea
nregistrrilor dintr-un tabel poate determina apariia unor probleme legate de integritatea
referenial. Pentru a evita aceste probleme se pot defini constrngeri de integritate care mpiedic
operaiile de inserare, actualizare sau tergere care ar distruge integritatea referenial a datelor.
8.5 Comanda TRUNCATE
Pentru a terge n mod rapid toate nregistrrile dintr-o tabel dau dintr-un cluster se poate folosi
comanda TRUNCATE. Comanda TRUNCATE este mult mai rapid dect comanda DELETE din
urmtoarele motive:
Comanda TRUNCATE este o comand DDL, prin urmare se execut dintr-o singur tranzacie i
deci nu folosete segmentul de revenire. Comanda trebuie folosit cu precauie deoarece nu mai
poate fi derulat napoi.

206

Comanda TRUNCATE nu declaneaz triggerul DELETE (vezi seciunea 9.16).

Comanda are urmtoarea sintax general:


TRUNCATE {TABLE tabel | CLUSTER cluster}
[ {DROP | REUSE} STORAGE]
unde:
Clauza TABLE specific numele unei tabele iar clauza CLUSTER specific numele unui cluster.
Dup cum se observ din sintax, aceste dou opiuni sunt alternative, deci nu se poate specifica
ntr-o comand TRUNCATE tergerea rndurilor dintr-o tabel i dintr-un cluster n acelai timp.
n cazul n care se specific clauza TABLE, tabela la care se refer aceast clauz nu poate face
parte dintr-un cluster. Comanda TRUNCATE se poate executa i asupra tabelelor organizate pe
index. La truncherea unei tabele, Oracle terge automat datele din indecii tabelei. n cazul n
care se specific clauza CLUSTER, clusterul la care se refer aceast clauz nu poate fi un
cluster hash ci numai un cluster de index. De asemenea, la truncherea unui cluster, Oracle terge
automat datele din indecii tabelelor clusterului.
Clauza DROP STORAGE elibereaz spaiul alocat nregistrrilor terse din tabel sau cluster.
Clauza REUSE STORAGE pstreaz spaiul alocat nregistrrilor terse din tabel sau cluster.
Acest spaiu care nu a fost dealocat poate fi reutilizat doar la operaii de inserare sau modificare
asupra tabelei sau clusterului. Aceste dou opiuni nu modific efectul pe care l are comanda
TRUNCATE asupra spaiului eliberat de datele terse din indecii asociai. Opiunea implicit
este DROP STORAGE.
tergerea nregistrrilor cu ajutorul comenzii TRUNCATE este mult mai avantajoas dect
eliminarea tabelului i recrearea lui ulterioar deoarece:
Eliminarea tabelului face ca obiectele dependente de acesta s devin invalide, pe cnd n cazul
folosirii comenzii TRUNCATE nu se ntmpl acest lucru;
Comanda TRUNCATE nu necesit reacordarea de drepturi asupra tabelului aa cum se ntmpl
dac acesta a fost eliminat i apoi recreat;
Eliminarea tabelului necesit recrearea indecilor, constrngerilor de integritate,
declanatoarelor, precum i specificarea parametrilor de stocare.
De exemplu, dac un utilizator execut comanda SELECT COUNT (*) FROM nume_tabel,
iar aceast interogare returneaz dup un interval destul de ndelungat valoarea zero, se recomand
trunchierea tabelului.

207

Capitolul 9: PL/SQL
PL/SQL (Procedural Language/ Structured Query Language) este o extensie a limbajului Oracle
SQL. PL/SQL permite ca instruciunile SQL de interogare i manipulare a datelor s fie incluse n
blocuri sau uniti procedurale de cod, cu alte cuvinte, PL/SQL este un limbaj cu structur de bloc.
Prin urmare programatorii pot realiza proceduri, funcii i blocuri ce combin instruciunile SQL cu
instruciunile procedurale (aa cum sugereaz i numele PL/SQL).
PL/SQL prezint urmtoarele caracteristici:
1. Structur de bloc
Acest lucru permite ca programele s fie mprite n blocuri logice bine definite i uor de
gestionat. De asemenea programatorul poate declara variabile locale blocului i poate manipula
rutinele pentru tratarea erorilor (numite excepii) specifice blocului apelat.
2. Structuri de control
PL/SQL utilizeaz structuri de control ce permit controlarea cursului logic de executare a
instruciunilor dintr-un bloc PL/SQL dnd o flexibilitate mare n programare. Limbajul PL/SQL
include structuri de control fundamentale (structura condiional, iterativ i secvenial). Aceast
caracteristic PL/SQL permite gruparea comenzilor i executarea acestora n mod controlat. Acest
lucru nu se poate realiza n SQL deoarece acesta nu este un limbaj procedural.
3. Portabilitatea
Codul PL/SQL este compatibil cu orice sistem de operare sau platform pe care ruleaz sistemul
Oracle. Astfel programele se pot muta pe orice mediu gazd care suport Oracle i PL/SQL.
4. Integrarea
PL/SQL ocup un rol central pentru Oracle Server i instrumentele Oracle. Variabilele i tipurile de
date PL/SQL sunt compatibile cu cele SQL (adic tipuri de date ce corespund coloanelor din
tabelele bazei de date Oracle). PL/SQL face legtura ntre accesul la tehnologia bazei de date i
necesitatea programrii procedurale.
5. Performana
Utilizarea PL/SQL pot mbunti performanele unei aplicaii. Performanele difer n funcie de
mediul n care PL/SQL este utilizat.
9.1 Blocuri PL/SQL
Orice unitate PL/SQL cuprinde unul sau mai multe blocuri. Aceste blocuri pot fi complet separate
sau imbricate, deci un bloc poate reprezenta doar o mic parte din alt bloc care la rndul lui poate fi
doar o parte din unitatea de cod. n general un bloc este sau un bloc anonim sau un subprogram.
Blocurile anonime
Sunt acele blocuri care nu au nume. Deoarece un bloc anonim nu are nume, acesta nu poate fi apelat
din alte programe. Blocurile anonime sunt declarate ntr-un punct al aplicaiei de unde sunt lansate
n execuie, moment n care controlul este transferat motorului PL/SQL. nainte de fiecare execuie
blocurile anonime PL/SQL trebuiesc compilate. Ele se pot regsi n programe precompilate n
SQL*Plus sau Server Manager. Declanatoarele din Oracle*Forms sunt alctuite din astfel de
blocuri.
Subprogramele
208

Sunt acele blocuri PL/SQL declarate sub form de proceduri sau funcii. Deoarece aceste blocuri
PL/SQL au asociat un nume ele pot fi apelate din alte subprograme. n cazul n care sunt declarate
sub form de funcii, la momentul apelrii blocurile ntorc n mod explicit un parametru. Dac
blocurile sunt declarate sub form de proceduri, la momentul execuiei nu se returneaz n mod
explicit nici un parametru. Oracle*Forms permite declararea procedurilor i funciilor i apelarea lor
dintr-un declanator sau dintr-o alt procedur sau funcie.
Structura blocurilor PL/SQL
Aa cum este artat n figura 9.1 un bloc PL/SQL este compus din trei pri:
- o parte declarativ;
- o parte executabil;
- o parte de tratare a excepiilor (n PL/SQL apariia unei erori este numit excepie).
Un bloc PL/SQL conine n mod obligatoriu elementele BEGIN i END n care sunt incluse
aciunile ce urmeaz a fi executate. Dup elementul END trebuie pus obligatoriu ;.
Bloc anonim

Procedur

Funcie

[EXCEPTION]
[Instruciuni]

PROCEDURE nume [list argumente]


IS
[declarare variabile locale]
BEGIN
Instruciuni
[EXCEPTION]
[Instruciuni]

END;

END;

FUNCTION nume [list argumente]


RETURN tipul_dat_returnat
IS
[declarare variabile locale]
BEGIN
Instruciuni;
RETURN rezultat;
[EXCEPTION]
[Instruciuni;
RETURN rezultat;]
END;

[DECLARE]
BEGIN
Instruciuni

Figura 9.1 Structura blocurilor PL/SQL


Dintre cele trei seciuni numai partea executabil este n mod obligatoriu necesar. Ordinea celor
trei pri este logic. Prima parte este cea de declaraie, seciune n care se definesc obiectele
PL/SQL, cum ar fi variabilele, ce urmeaz a fi referite n blocul PL/SQL. Seciunea de declaraie
este opional. Odat declarate, obiectele pot fi manipulate n partea executabil a blocului PL/SQL.
Excepiile aprute n timpul execuiei pot fi plasate n seciunea de tratare a excepiilor. n aceast
seciune se definesc aciuni ce vor fi executate atunci cnd condiiile de apariie a unei erori sunt
ndeplinite. Seciunea de tratare a erorilor este opional i trebuie plasat nainte de END.
Sub-blocurile se pot imbrica n seciunea executabil sau n seciunea de tratare a erorilor unui bloc
PL/SQL, dar nu se poate realiza imbricarea n seciunea declarativ. n schimb n seciunea
declarativ se pot defini subprograme locale ce pot fi apelate n blocul n care sunt definite.
9.2 Arhitectura PL/SQL
PL/SQL nu este un produs Oracle de sine stttor, ci o tehnologie asemntoare cu un motor ce
execut blocuri sau subprograme PL/SQL. Acest motor poate fi instalat n:
Serverul bazei de date (Oracle Server)
Instrumente Oracle (cum ar fi Oracle Forms sau Oracle Reports)

209

Cele dou medii de programare sunt independente. Astfel, PL/SQL poate fi disponibil n serverul
bazei de date dar nu i n instrumentele Oracle, sau invers. Figura 9.2 prezint modul n care
motorul PL/SQL proceseaz un bloc anonim.

Motorul PL/SQL

BLOC
PL/SQL

BLOC
PL/SQL

Comenzi procedurale

Executorul
de comenzi
procedurale

Comenzi
SQL

de comenzi SQL
Figura Executorul
*
Oracle Server
Figura 9.2 Procesarea unui bloc anonim
Motorul execut comenzile procedurale dar comenzile SQL sunt trimise spre execuie ctre
executorul de comenzi SQL (SQL Statement Executor) din Oracle Server.
n cazul n care instrumentele Oracle nu conin un motor PL/SQL local trebuie s trimit spre
procesare comenzile procedurale ctre Oracle Server. Acesta nseamn c este nevoie de un singur
transfer pentru a trimite blocul din aplicaie ctre Server ducnd la mbuntirea performanei n
special ntr-o reea client-server.
n cellalt caz, atunci cnd motorul este instalat n instrumentele Oracle, comenzile procedurale sunt
executate local, ceea ce nseamn reducerea cantitii de prelucrat pentru Oracle Server precum i a
numrului de cursoare de memorie necesare. Cu alte cuvinte, cea mai mare cantitate de prelucrat
este executat de ctre aplicaia Oracle, mai mult, dac blocul nu conine comenzi SQL atunci este
executat local n ntregime. Acest lucru este foarte util atunci cnd aplicaia folosete controlul
condiional sau iterativ. Oracle Forms utilizeaz n mod frecvent comenzi SQL doar pentru a testa
valorile atribuite unor cmpuri sau pentru a realiza calcule simple. Prin utilizarea PL/SQL se poate
evita apelarea Oracle Server, i mai mult dect att, se pot utiliza funcii PL/SQL pentru a manipula
cmpurile introduse.
Din punct de vedere al compatibilitii PL/SQL cu limbajul SQL exist urmtoarele reguli:
- PL/SQL suport toate comenzile limbajului de manipulare a datelor (DML) ale limbajului SQL,
comanda de interogare SELECT (cu clauza INTO), comenzile pentru controlul tranzaciilor,
precum i funciile, pseudo-coloanele i operatorilor SQL;
- Limbajul PL/SQL nu suport comenzi de definire a datelor.
9.3 Sintaxa de baz a PL/SQL
Deoarece PL/SQL reprezint extensia procedural a limbajului SQL, n general regulile de sintax
210

care se aplic n SQL sunt aplicabile i n PL/SQL:


- comenzile pot fi scrise pe mai multe rnduri ns cuvintele cheie nu;
- unitile lexicale (identificatori, nume de operatori, literali) sunt desprite prin unul sau mai
multe spaii, sau prin delimitatori ce nu pot fi confundai cu uniti lexicale;
- nu se pot utiliza cuvinte rezervate ca identificatori, dect dac sunt introduse ntre ghilimele (de
exemplu UPDATE);
- identificatorii pot conine maxim 30 de caractere i trebuie s nceap cu un caracter alfabetic;
- literalii de tip caracter sau dat calendaristic trebuiesc inclui ntre apostrofuri;
- literalii de tip numeric se reprezint prin valori simple (de exemplu -13.7) sau notaie tiinific
(3E4, ceea ce nseamn 3x104);
- comentariile pe mai multe linii se includ ntre simbolurile /* i */, iar comentariile mono-linie
ncep cu semnul dubl cratim -- i se termin la sfritul liniei respective. Comentariile nu pot
fi imbricate i nici nu se pot folosi comentarii mono-linie dac blocul este procesat de un
program de precompilare.
9.4 Referirea obiectelor
Regiunea unui program n care se poate referi un obiect pentru a delimita durata de via a acestuia
se numete domeniul de vizibilitate al obiectului. Acest lucru se refer la toate obiectele declarate n
seciunea DECLARE, incluznd variabile, cursoare, excepii definite de utilizator i constante.
Blocul ce conine un obiect declarat mpreun cu sub-blocurile imbricate n acesta reprezint
domeniul de vizibilitate al obiectului, deoarece obiectul poate fi accesat i din interiorul subblocurilor coninute n blocul unde acesta a fost declarat. Obiectele declarate n sub-blocuri sunt
accesibile pn n momentul cnd sub-blocul s-a terminat. n acest sens este recomandabil
definirea variabilelor ct mai local cu putin. Cu alte cuvinte, dac o variabil este folosit numai
n blocul cel mai din interior aceasta trebuie declarat n acel bloc.
Se pot defini obiecte care au acelai nume dar numai dac acestea se gsesc n blocuri diferite. n
acest context numai obiectul declarat n blocul curent se poate folosi. Acest lucru nu nseamn c
obiectul cu acelai nume aflat n alt bloc dect cel curent nu mai exist, ci faptul c obiectul nu are
vizibilitate n blocul curent.
9.5 Variabile i constante
Instruciunile SQL i instruciunile procedurale pot folosi variabile i constante. Deoarece nu sunt
permise referine anticipate variabilele i constantele trebuiesc declarate nainte ca acestea s fie
referite n instruciuni. Aa cum am mai spus, variabilele i constantele se declar n seciunea de
declaraie a unui bloc PL/SQL.
Orice constant sau variabil are un anumit tip de dat ce specific un anumit format, constrngeri
sau un anumit interval n care datele pot lua valori. PL/SQL dispune de o varietate de date
predefinite printre care toate tipurile de date ce se regsesc i n limbajul SQL (adic tipuri de date
ce corespund coloanelor din tabelele bazei de date Oracle). n plus fa de SQL, PL/SQL prevede
cteva tipuri de date proprii cum ar fi: boolean, binary_integer, record, table.
Tipurile de date se mpart n mai multe categorii:
- tipuri de date scalare sunt acele tipuri de date ce nu au componente interne, adic conin
valori atomice. Majoritatea tipurile de date scalare din PL/SQL sunt similare tipurilor de date
Oracle SQL, dar exist i tipuri de date suplimentare (de exemplu BOOLEAN,
BINARY_INTEGER, etc.)
- tipuri de date compuse sunt acele tipuri de date ce au componente interne care pot fi
manipulate n mod individual;
211

tipuri de date referin sunt acele tipuri de date ale cror valori, numite pointeri, fac referin
ctre elemente ale altor programe;
- tipuri de date LOB - sunt acele tipuri de date ale cror valori, numite locatori (locators),
specific locaia unor obiecte de dimensiuni mari stocate n afara bazei de date (de exemplu
imagini grafice).
Consultai anexa 3 pentru o descriere complet a tipurilor de date PL/SQL.
Identificatorul unei variabile sau constante trebuie s ndeplineasc urmtoarele condiii:
- s fie compuse din litere, semnul dolar, liniua de subliniere (underscore) i cifre;
- primul caracter s fie o liter;
- lungimea trebuie s fie de maxim 30 de caractere;
- nu se face distincie ntre litere mari i litere mici (nu este CASE SENSITIVE).
Declararea constantelor
n cazul unei constante este obligatorie iniializarea acesteia cu o anumit valoare n momentul
declarrii. Aceast valoare nu poate fi modificat mai apoi n interiorul blocului. Sintaxa pentru
declararea constantelor este urmtoarea:
identificator CONSTANT tip_data :=expresie;
Exemplu:
pi
CONSTANT
titlu CONSTANT

NUMBER (9,5):=3.14159;
CHAR (5):=Titlu;

Declararea variabilelor
n momentul declarrii se poate iniializa n mod opional o variabil cu o anumit valoare. Acest
valoare poate fi schimbat apoi prin atribuiri fcute variabilei n interiorul blocului. Sintaxa pentru
declararea i iniializarea variabilelor este urmtoarea:
identificator tip_data [NOT NULL] [{:=|DEFAULT} expresie];
unde:
Dac la declararea variabilei se folosete constrngerea NOT NULL, atunci n mod obligatoriu
trebuie atribuit o valoare variabilei n momentul declarrii acesteia. Ca urmare a folosirii
acestei constrngeri, variabila nu va putea avea valoarea Null.
Pentru iniializarea variabilelor se poate folosi ori operatorul de atribuire, ori cuvntul cheie
DEFAULT. Dac nu se iniializeaz n momentul declarrii, variabila va avea valoarea Null pn
n momentul cnd acesteia i se atribuie o valoare explicit. n momentul declarrii unei variabile
ce are tipul NATURALN sau POZITIVEN, trebuie specificat i o valoarea iniial a acesteia. n
caz contrar va aprea o eroare de compilare.
O observaie foarte important este faptul c o variabil nu trebuie s aib acelai nume
(identificator) cu numele unei coloane dintr-un tabel deoarece atunci cnd o comand SQL folosete
o variabil PL/SQL ce are acelai nume cu numele unei coloane, sistemul Oracle recunoate
variabila drept nume de coloan. O soluie pentru rezolvarea conflictelor de nume este adoptarea
unei convenii ce va utiliza prefixul v_ pentru reprezentarea variabilelor.
Exemplu de declarare a variabilelor:
v_salariu NUMBER (10,2);
v_gasit
BOOLEAN DEFAULT FALSE;
212

v_nume
v_data
v_total

VARCHAR (25):=ION;
DATE DEFAULT SYSDATE;
NUMBER NOT NULL :=0;

Atribuirea variabilelor
Variabilelor PL/SQL li se pot atribui valori n interiorul blocului cu ajutorul instruciunii de
atribuire. n acest caz trebuie specificat numele variabilei ce va lua o nou valoare, n stnga
operatorului de atribuire :=. O alt metod de atribuire a variabilelor este folosirea clauzei INTO a
comenzii SELECT sau utilizarea cursoarelor, aa cum vom vedea mai trziu n cuprinsul acestui
capitol.
Exemplu de atribuire a variabilelor n interiorul blocului:
v_nume:=DANIEL;
v_salariu:=salariu*12;
-- unde salariu este o variabil existent
v_data:=12-Nov-99;
Dei, n momentul atribuirii variabilelor, PL/SQL realizeaz conversii implicite pentru tipurile de
date, trebuie avut n vedere compatibilitatea variabilelor cu expresiile care le sunt atribuite. n acest
sens se pot folosi funciile TO_CHAR, TO_DATE, TO_NUMBER.
Folosirea variabilelor PL/SQL pentru stocarea valorilor nregistrrilor dintr-un tabel
Atributul %TYPE
n momentul declarrii variabilelor PL/SQL cu scopul de a stoca valorile unei coloane trebuie s
avem grij ca variabila s aib acelai tip de dat cu coloana tabelului. Dac nu se ndeplinete
aceast condiie va fi semnalat o eroare n momentul execuiei. Utiliznd atributul %TYPE putem
atribui unei variabile tipul i mrimea coloanei aa cum este definit n dicionarul de date. PL/SQL
determin tipul i mrimea variabilei n momentul cnd blocul este compilat astfel nct aceasta va
fi mereu compatibil cu coloana respectiv. Sintaxa pentru definirea acestor variabile este:
identificator nume_tabel.nume_coloana%TYPE;
Exemplu:
DECLARE
v_nume
angajati.nume%TYPE;
v_salariu angajati.salariu%TYPE;
BEGIN
SELECT nume, salariu
INTO v_nume, v_salariu
FROM angajati;
-- alte aciuni
END;
Atributul %ROWTYPE
O variabil de tip nregistrare PL/SQL conine o colecie de cmpuri diferite, fiecare cmp putnd fi
adresat n mod individual. Cmpurile dintr-o variabil de tip nregistrare pot avea tipuri de dat i
mrimi diferite, asemntor coloanelor dintr-un tabel. Variabila de tip nregistrare este foarte
folositoare atunci cnd se dorete extragerea unui rnd dintr-un tabel n vederea procesrii lui ntr213

un program PL/SQL (n special n cursoare). Pentru a declara o variabil de tip nregistrare ce se


bazeaz pe o colecie de cmpuri dintr-o tabel sau vedere se folosete atributul %ROWTYPE.
Cmpurile din variabila de tip nregistrare vor avea acelai nume ca i coloanele tabelului sau
vederii.
Sintaxa pentru definirea acestor variabile este:
identificator referinta%ROWTYPE;
Identificator reprezint numele ales pentru variabil iar referinta reprezint numele
tabelului sau vederii pe care se bazeaz variabila. n momentul declarrii variabilei trebuie verificat
dac referina este valid, adic verificarea existenei tabelului sau vederii pe care se bazeaz
variabila.
Exemplu:
DECLARE
angajat_inreg
angajati%ROWTYPE;
Pentru a popula o variabil de tip nregistrare PL/SQL cu un rnd al unui tabel, trebuie folosit o
comand SELECT ce conine n clauza INTO numele variabilei:
BEGIN
SELECT * INTO angajat_inreg
FROM angajati WHERE cod=101;
-- alte aciuni;
END;
Putem de asemenea s atribuim unei variabile de tip nregistrare valorile unei alte variabile de tip
nregistrare cu condiia ca tabelele pe care se bazeaz aceste variabile s aib aceeai structur sau
s se bazeze pe acelai tabel:
DECLARE
inreg1
angajati%ROWTYPE;
inreg2
angajati%ROWTYPE;
BEGIN
inreg1:=inreg2;
--alte aciuni
END;
Att n instruciunile procedurale ct i n SQL cmpurile dintr-o variabil de tip nregistrare se pot
referi n mod individual:
angajati_inreg.bonus:=angajati_inreg.salariu/12;
n cazul instruciunii INSERT nu se poate specifica doar numele variabilei de tip nregistrare n
lista valorilor ci va trebui specificat fiecare cmp individual din variabila de tip nregistrare. Prin
urmare urmtoarea instruciune este ilegal:
INSERT INTO angajati (cod, nume, prenume, salariu, bonus)
VALUES (inreg1);
Pentru a putea insera o nregistrare n mod corect vom folosi:
INSERT INTO angajati (cod, nume, prenume, salariu, bonus)
214

VALUES (inreg1.cod,
inreg1.bonus);

inreg1.nume,

inreg1.prenume,

inreg1.salariu,

Referirea variabilelor non-PL/SQL


Pentru a putea referi variabilele non-PL/SQL (variabile declarate n programe de precompilare,
cmpuri din aplicaii Forms, variabile de legtur SQL*Plus) trebuie folosit naintea numelui
variabilelor semnul :, cu scopul de a le distinge de variabilele PL/SQL la nivel de compilator.
Exemplu:
:global.var1:=Yes;
Variabilele non-PL/SQL se mai numesc i variabilele programului gazd i sunt folosite pentru a
transfera valori n ambele sensuri ntre programul surs i PL/SQL.
9.6 Operatori PL/SQL
Operatorii logici, aritmetici i de concatenare utilizai de PL/SQL sunt aceeai ca cei utilizai de
SQL. n plus, n PL/SQL exist un operator exponenial (**).Ordinea de execuie a operatorilor este
prezentat n tabelul din figura 9.3. Ca i n SQL ordinea de execuie a operaiilor este controlat cu
ajutorul parantezelor.
Operator
Operaia
**, NOT
Ridicare la putere, negare logic
+, Identitate, negare (operatori unari)
*, /
nmulire, mprire
+, -, ||
Adunare, scdere, concatenare
=, !=, <, >, <=, >=,
Comparare
IS NULL, LIKE, BETWEEN, IN
AND
AND logic
OR
OR logic
Figura 9.3 - Ordinea de execuie a operatorilor
9.7 Comenzile SQL i PL/SQL
Aa cum am mai spus pn acum n PL/SQL sunt implementate comenzile SQL, singura excepie
fcnd comanda SELECT care trebuie s conin o clauz suplimentar, clauza INTO care nu exist
n SQL, i s ndeplineasc anumite condiii. n SQL pot exista ns numai referine ale variabilelor
PL/SQL.
Referine PL/SQL n comenzi SQL
Comenzile SQL pot folosi variabile PL/SQL cu condiia ca acestea s nu aib acelai nume cu
numele coloanelor unui tabel, ns n cadrul comenzilor SQL nu se pot folosi funcii sau atribute
specifice PL/SQL (de exemplu funcia SQLCODE sau SQLERRM)
Comenzi de manipulare a datelor
n PL/SQL se pot utiliza fr nici o restricie comenzile SQL de manipulare a datelor (INSERT,
UPDATE, DELETE).
Comanda SELECT n PL/SQL
215

Comanda SELECT ntr-un bloc PL/SQL este denumit de ctre ANSI ca SQL ncapsulat i
asupra ei se aplic urmtoarea regul:
O comand SELECT trebuie s returneze o singur nregistrare. Returnarea mai multor
nregistrri sau a nici uneia va genera o eroare.
Totui, PL/SQL gestioneaz aceste erori n seciunea de excepii a blocului i, aa cum vom vedea
n continuare exist posibilitatea folosirii acestor erori pentru a testa dac o comand SELECT
returneaz zero, una sau mai multe nregistrri. Clauza INTO este obligatorie i trebuie plasat ntre
clauza SELECT i FROM. Aceast clauz este utilizat pentru a specifica numele variabilelor ce vor
stoca valorile returnate de interogare. Pentru fiecare element selectat trebuie s existe o variabil iar
ordinea din clauza INTO trebuie s corespund cu ordinea elementelor selectate. Variabilele din
clauza INTO pot fi variabile PL/SQL (declarate n seciunea DECLARE), variabile ale programului
gazd (variabile precedate de caracterul :, numite i variabile de legtur) i variabile de
substituie (precedate de caracterul &). Deoarece comanda SELECT trebuie s returneze o singur
valoare clauzele GROUP BY i ORDER BY nu pot fi folosite.
Exemple referitoare la comanda SELECT..INTO au fost folosite n seciunea anterioar pentru
prezentarea atributelor %TYPE i %ROWTYPE.
9.8 Funcii predefinite n PL/SQL
Majoritatea funciilor SQL referitoare la o singur nregistrare sunt disponibile i n PL/SQL: funcii
numerice, funcii caracter, funcii pentru conversii de tip, funcii pentru data calendaristica, funcii
diverse. n plus PL/SQL prevede dou funcii pentru raportarea erorilor, SQLCODE i SQLERRM,
despre care vom discuta mai trziu n acest capitol.
Exist i funcii care nu sunt disponibile n instruciuni procedurale:
- GREATEST, LEAST i DECODE.
- funcii de grup: AVG, MIN, MAX, COUNT, SUM, STDDEV i VARIANCE.
Funciile de grup se aplic numai grupurilor de nregistrri din tabele deci din acest motiv ele sunt
disponibile numai n instruciunile SQL dintr-un bloc PL/SQL, i nu n cadrul instruciunilor
procedurale. n cadrul instruciunii SELECT...INTO, funciile de grup trebuiesc folosite cu atenie
deoarece, aa cum am mai menionat, aceast instruciune nu poate conine clauza GROUP BY.
9.9 Cursoare implicite
De fiecare dat cnd se execut o comand SQL, serverul bazei de date deschide o arie de memorie
n care comanda este analizat i executat. Aceast arie este denumit cursor. n momentul cnd n
partea executabil a unui bloc se ntlnete o comanda SQL, PL/SQL gestioneaz n mod automat
acest cursor implicit.
Pentru a evalua ce s-a ntmplat n momentul cnd cursorul implicit a fost utilizat, PL/SQL ofer
programatorului cteva atribute: SQL%ISOPEN, SQL%ROWCOUNT, SQL%FOUND i
SQL%NOTFOUND. Aceste atribute se folosesc n seciunea de tratare a excepiilor a unui bloc
pentru a evalua rezultatul comenzilor de manipulare a datelor. Valoarea atributelor cursorului se
refer ntotdeauna la cea mai recent executat instruciune SQL. Atunci cnd comenzile INSERT,
UPDATE i DELETE nu afecteaz nici o nregistrare, PL/SQL nu semnaleaz nici o eroare.
Semnificaia atributelor cursoarelor implicite este descris n tabelul de mai jos.
216

Atribut

Tip dat

%ROWCOUNT

ntreg

%FOUND

Boolean

%NOTFOUND

Boolean

%ISOPEN

Boolean

Descriere
Returneaz numrul de linii afectate de o instruciune INSERT,
UPDATE sau DELETE. Atributul %ROWCOUNT returneaz zero
dac instruciunea SQL nu afecteaz nici o valoare.
Are valoarea True dac o instruciune INSERT, UPDATE sau
DELETE afecteaz una sau mai multe linii sau dac instruciunea
SELECT INTO returneaz o linie sau mai multe linii.
Are valoarea True dac o instruciune INSERT, UPDATE sau
DELETE nu afecteaz nici o linie sau n cazul n care instruciunea
SELECT INTO nu returneaz nici o linie. Atributul %NOTFOUND
are o valoare logic contar atributului %FOUND.
Acest atribut are valoarea False deoarece programul nchide n mod
automat cursorul implicit imediat dup executarea instruciunii SQL
asociate iar atributele sunt folosite pentru a evalua ce s-a ntmplat
dup ce cursorul implicit a fost utilizat.

9.10 Controlul tranzaciilor


Tranzaciile pentru manipularea datelor ncep cu prima comand ce urmeaz instruciunea COMMIT
sau ROLLBACK i se termin n momentul cnd urmtoarea instruciune COMMIT sau ROLLBACK
este executat cu succes. Comenzile pentru controlul tranzaciilor (COMMIT, ROLLBACK) sunt
disponibile i n PL/SQL dei mediul gazd poate impune unele restricii n utilizarea lor. ntr-un
bloc PL/SQL se pot include de asemenea i comenzi explicite de blocare (LOCK TABLE i
SELECT...FOR UPDATE).
9.11 Structuri de control n PL/SQL
Fluxul secvenial de execuie a instruciunilor unui program PL/SQL poate fi modificat cu ajutorul
structurilor de control. Limbajul PL/SQL suport patru structuri de control fundamentale: structura
secvenial, condiional, iterativ i de salt necondiionat. Pe lng aceste structuri de control,
PL/SQL mai suport i instruciunea vid.
Controlul secvenial
n mod prestabilit, blocurile PL/SQL sunt executate secvenial, de sus n jos. Procesarea ncepe cu
instruciunea BEGIN i se termin cu instruciunea END. Prin introducerea structurilor de control
condiionale, iterative sau sau de salt necondiionat se poate schimba cursul prestabilit de procesare
al instruciunilor.
Controlul condiional
Pentru controlul condiional, adic pentru a efectua aciuni alternative n funcie de o anumit
condiie, este folosita instruciunea IF. Instruciunea IF este similar cu comenzile de control
condiional din alte limbaje procedurale. Sintaxa instruciunii IF este urmtoarea:
IF condiie
THEN
aciuni
[ELSIF condiie
THEN
217

aciuni]
[ELSE aciuni]
END IF;
In funcie de modul de utilizare al instruciunii IF aceasta se poate clasifica n mai multe tipuri.
Instruciunea IF simpl
PL/SQL execut aciunile ce urmeaz dup instruciunea condiional numai dac condiia este
ndeplinit (are valoarea True). Condiia poate fi o comparaie sau o variabil boolean. n cazul n
care condiia are valoarea False sau Null, instruciunile nu sunt procesate, controlul fiind transferat
urmtoarei instruciuni ce urmeaz dup delimitatorul de sfrit al instruciunii condiionale (END
IF).
Exemplu:
IF v_nume = Ionescu
THEN
v_bonus:=500000;
END IF;
Rezultatul unei comparaii poate avea valoarea Null dac una din valorile comparate conine
valoarea Null. De exemplu, n urmtorul bloc PL/SQL, ambele valori x1 i x2 sunt iniializate cu
valoarea Null. Chiar dac cele dou variabile au aceai valoare, condiia nu va fi ndeplinit
deoarece valorile comparate au valoarea Null, i prin urmare instruciunea x:=x+1 nu va fi
procesat.
DECLARE
x
NUMBER:=null;
y
NUMBER:=null;
BEGIN
IF x=y
THEN
x:=x+1;
END IF;
END;
Instruciunea IF-THEN-ELSE
Dac condiia are valoarea False sau Null, atunci se execut aciunile din clauza ELSE. Acest lucru
asigur execuia selectiv a unuia dintre cele dou seturi de aciuni indiferent dac este ndeplinit
condiia sau nu. Fiecare instruciune IF-THEN poate s aib o singur instruciune ELSE i trebuie
s se ncheie cu o instruciune END IF.
Exemplu:
IF v_nume = Ionescu
THEN
v_bonus:=500000;
ELSE
v_bonus:=0;
END IF;
Cele dou seturi de aciuni ale unei instruciuni condiionale pot conine la rndul lor alte
218

instruciuni condiionale. Fiecare instruciune IF imbricat trebuie s se termine cu clauza END


IF.
Instruciunea IF-THEN-ELSIF
Clauza ELSIF reprezint o alternativa n utilizarea instruciunilor IF imbricate. Astfel, dac
aciunea din clauza ELSE este o alt instruciune IF, este mult mai convenabil s se utilizeze clauza
ELSIF.
Exemplu:
IF titlu = dna
THEN
statut:=casatorit;
ELSIF titlu = dra
THEN
statut:=necasatorita;
ELSE
statut:=necunoscut;
END IF;
Instruciunea de mai sus este echivalent cu urmtoarele instruciuni IF imbricate:
IF titlu = dna
THEN
statut:=casatorit;
ELSE
IF titlu = dra
THEN
statut:=necasatorita;
ELSE
statut:=necunoscut;
END IF;
END IF;
Controlul iterativ
Pentru a executa de mai multe ori o secven de instruciuni se folosete controlul iterativ. Exist
mai multe instruciuni care sunt folosite n acest sens.
Instruciunea LOOP
Instruciunea LOOP reprezint cel mai simplu ciclu iterativ i const dintr-un grup de instruciuni
care se repet, incluse ntre delimitatorii LOOP i END LOOP. De fiecare dat cnd se ajunge la
delimitatorul END LOOP controlul revine n punctul unde se afl delimitatorul LOOP. Acest ciclu
iterativ se poate executa la infinit dac n interiorul lui nu exist nici o instruciune de control care
s opreasc acest lucru. Pentru a opri acest ciclu trebuie plasat n interiorul ciclului instruciunea
EXIT, instruciune ce transfer controlul instruciunii imediat urmtoare delimitatorului END LOOP.
Instruciunea EXIT are urmtoarea sintax:
EXIT [eticheta][WHEN condiie];
n interiorul ciclului instruciunea EXIT se poate folosi n dou moduri:
219

ca aciune ntr-o instruciune condiional;

Exemplu:
LOOP
i:=i+1;
-- alte aciuni
IF i>=10
THEN
COMMIT;
EXIT;
END IF;
END LOOP;
ca instruciune de sine stttoare, cu obligativitatea folosirii clauzei WHEN.
Exemplu:
LOOP
i:=i+1;
-- alte aciuni
EXIT WHEN i>=10;
END LOOP;
Instruciunea FOR-LOOP
Instruciunea FOR-LOOP permite parcurgerea unui ciclu de un numr specificat de ori. Sintaxa este
urmtoarea:
FOR contor IN [REVERSE] limita_inf..limita_sup
LOOP
--actiuni
END LOOP;
Variabila contor este o variabil de tip ntreg a crei valoare va fi incrementat sau decrementat la
fiecare iteraie a ciclului. De asemenea, variabila contor este declarat implicit (nu trebuie declarat
de utilizator). Valorile limita_inf i limita_sup pot fi constante, variabile sau expresii,
ns n urma evalurii trebuie s ia valori ntregi. Ele reprezint valoarea minim, respectiv valoarea
maxim pe care o poate lua contorul. Dac la intrarea n ciclu n urma evalurii limita superioar
este mai mica dect limita inferioar, instruciunile nu sunt executate.
n general variabila contor este iniializat la intrarea n ciclu cu valoarea minim i este
incrementat cu 1 pn ajunge la valoarea maxim:
FOR i IN 1..100
LOOP
-- contorul i ia valoarea 1 la prima iteraie i 100 la ultima
END LOOP;
Instruciunea FOR LOOP poate fi folosit cu opiunea REVERSE, caz n care variabila contor este
iniializat cu valoarea maxim i decrementat cu 1 pn ajunge la valoarea minim:
FOR n IN REVERSE 50..100
LOOP
-- contorul n ia valoarea 100 la prima iteraie i 50 la ultima
END LOOP;

220

Instruciunea WHILE
Structura WHILE-LOOP repet un grup de instruciuni pn n momentul n care o condiie devine
fals. Spre deosebire de instruciunea FOR-LOOP, n cazul instruciunii WHILE numrul de iteraii
ce urmeaz s fie efectuate de un ciclu este necunoscut pn n momentul ncheierii ciclului
deoarece numrul de iteraii depinde de valoarea pe care o ia condiia. n cazul n care condiia are
valoarea True instruciunile sunt executate. n caz contrar, ciclul iterativ ia sfrit iar controlul este
transferat instruciunii imediat urmtoare delimitatorului END LOOP. Deoarece condiia este
evaluat la nceputul ciclului, este posibil ca instruciunile din interiorul ciclului s nu fie executate
nici mcar o data. Sintaxa instruciunii WHILE este urmtoarea:
WHILE condiie
Exemplu:
WHILE variabila_boolean
LOOP
-- aciuni
END LOOP;
Condiia unei instruciuni WHILE poate fi o condiie compus.
Exemplu:
WHILE nume LIKE F% AND salariu > 1000000
LOOP
--aciuni
END LOOP;
Dac variabilele implicate n condiie nu se schimb n interiorul ciclului atunci condiia va avea
valoarea True mereu i deci ciclul se va executa de un numr infinit de ori.
Instruciunea EXIT poate fi folosit i n cadrul instruciunii FOR sau WHILE pentru a permite
prsirea ciclului.
Salt necondiionat
Instruciunea GOTO execut un salt necondiionat la o etichet, transfernd controlul instruciunii
sau blocului etichetat. Este recomandabil ca instruciunea GOTO s fie utilizat ct mai puin
deoarece se poate ntmpla ca un program s devin prost structurat datorit folosirii acestei
instruciuni. Instruciunea GOTO face obiectul urmtoarelor restricii:
- nu se poate utiliza pentru a transfera controlul unei instruciuni din interiorul unei structuri IF
sau LOOP sau al unui sub-bloc;
- nu se poate utiliza pentru a transfera controlul n exteriorul unui subprogram;
- nu se poate utiliza pentru a transfera controlul din seciunea de tratare a excepiilor n blocul
curent.
Sintaxa instruciunii GOTO este urmtoarea:
GOTO nume_eticheta;
Instruciunea vid (NULL)
Instruciunea NULL specific n mod explicit faptul c nu va fi executat nici o aciune iar controlul
este transferat instruciunii imediat urmtoare.

221

9.12 Excepiile
Excepia reprezint o eroare sau un avertisment care este generat fie de severul Oracle, fie de
aplicaia utilizatorului. n cele mai multe limbaje de programare, mai puin n cazul n care se
dezactiveaz opiunea de control al erorilor, o eroare de execuie, provocat de exemplu de o
ncercare de mprire la zero, oprete procesarea normal a datelor i transfer controlul sistemului
de operare. n PL/SQL mecanismul numit tratarea erorilor permite programului s i continue
execuia i n prezena anumitor erori.
Un bloc se termin ntotdeauna cnd apare o excepie dar se pot executa aciuni ulterioare apariiei
excepiei ntr-o seciune special de tratare a excepiilor. Astfel, dac exist aciuni n seciunea de
tratare a excepiilor, excepia (eroarea) nu se va propaga n bloc sau n mediul de execuie. Dei nu
se pot anticipa toate erorile posibile, utilizatorul poate trata o parte din acestea n blocurile PL/SQL.
Exist dou tipuri de excepii:
1. Predefinite - sunt acele excepii predefinite de sistemul Oracle i sunt asociate unui cod specific
de eroare. Aceste erori pot avea drept cauz cderi ale echipamentelor sau ale reelei, erori de
programare, erori legate de integritatea datelor i multe alte cauze. Dei fiecare eroare Oracle are
asociat un cod specific, excepiile trebuiesc referite numai prin nume. Despre modul n care
aceste excepii pot fi tratate vom vorbi n continuare n acest capitol. n tabelul de mai jos sunt
prezentate numele celor mai importante erori Oracle precum i codul de eroare asociat acestora:
Nume excepie

Eroarea
Oracle

Cod
eroare

ACCES_INTO_NULL

ORA-06530

-6530

COLLECTION_IS_NULL

ORA-06531

-6531

CURSOR_ALREADY_OPEN

ORA-06511

-6511

DUP_VAL_ON_INDEX

ORA-00001

-1

INVALID_CURSOR

ORA-01001

-1001

INVALID_NUMBER

ORA-01722

-1722

LOGIN_DENIED

ORA-01017

-1017

NO_DATA_FOUND

ORA-01403

-1403

NOT_LOGGED_ON

ORA-01012

-1012

222

Descriere
Atribuire de valori atributelor
unui
obiect
neiniializat.
(iniializarea unui obiect se
face prin folosirea n atribuire a
constructorului sau a unui alt
obiect, vezi capitolul 10)
Aplicarea unei metode diferite
de EXISTS unui tabel imbricat
sau VARRAY neiniializat
(vezi capitolul 10).
ncercare de deschidere a unui
cursor deja deschis.
Detectarea
unei
valori
duplicate ntr-o coloan cu
index unic.
Efectuarea unei operaii ilegale
asupra unui cursor.
Conversia unui ir de caractere
ntr-un numr a euat.
Conectarea la serverul Oracle a
euat datorit unui nume de
utilizator invalid sau a unei
parole invalide.
Comanda SELECT...INTO nu
returneaz nici o nregistrare.
A fost efectuat un apel al bazei
de date fr conectarea
prealabil la serverul Oracle.

PROGRAM_ERROR

ORA-06501

ROWTYPE_MISMATCH

ORA-06504

STORAGE_ERROR

ORA-06500

SUBSCRIPT_BEYOND_COUNT

ORA-06533

SUBSCRIPT_OUTSIDE_LIMIT

ORA-06532

TIMEOUT_ON_RESOURCE

ORA-00051

TOO_MANY_ROWS

ORA-01422

VALUE_ERROR

ORA-06502

ZERO_DIVIDE

ORA-01476

Este generat atunci cnd


-6501 PL/SQL ntlnete o problem
intern.
n cazul deschiderii unui cursor
cu parametri, trebuiesc fcute
asocieri ntre parametrii actuali
i cei formali innd cont de
-6504 poziia acestora n sintaxa de
definire a cursorului. Dac
parametrii actuali nu au acelai
tip ca i parametrii formali, se
va declana aceast eroare.
Este generat atunci cnd
PL/SQL nu are la dispoziie
-6500 suficient memorie sau exist
anumite probleme legate de
aceasta.
Este generat atunci cnd este
referit un element dintr-un
-6533 tabel imbricat sau VARRAY a
crui poziie este mai mare
dect numrul de elemente al
coleciei (vezi capitolul 10).
Este generat atunci cnd este
referit un element dintr-un
-6532 tabel imbricat sau VARRAY a
crui poziie este n afara
domeniului (vezi capitolul 10).
Pauz survenit n timp ce
-51
programul Oracle atepta o
resurs.
O
instruciune
SELECT
-1422 ...INTO a returnat mai mult de
o singur linie.
A
survenit
o
eroare
-6502 matematic, de conversie, de
trunchiere sau referitoare la o
constrngere.
-1476 ncercare de mprire la zero.

2. Definite de utilizator - sunt acele excepii declarate n bloc de ctre utilizator. n mod uzual,
PL/SQL va genera o excepie definit de utilizator dac acest lucru este cerut n mod deliberat n
interiorul blocului, putndu-se face o asociere ntre codul erorilor i excepie. Un exemplu de
excepie definit de utilizator poate aprea, n cazul unei bnci, n momentul cnd un client
dorete retragerea unei sume ce depete valoarea deinut n cont.
Pentru a exemplifica cele expuse mai sus vom considera urmtorul bloc:
BEGIN
INSERT INTO angajati (cod, nume)
VALUES (20,GEORGE);
INSERT INTO angajati (cod, nume)
VALUES (20,DUMITRU);
223

END;
Blocul din exemplul de mai sus se sfrete fr a trata excepiile i va produce urmtoarea eroare
datorat ncercrii de a introduce o valoare duplicat ntr-un cmp ce este cheie primar a relaiei:
ora - 00001: unique constraint violated
Aa cum am mai spus, pentru a evita astfel de evenimente i pentru a preveni propagarea excepiilor
n mediul de execuie trebuiesc definite aciuni referitoare la acestea n seciunea de tratare a
excepiilor. Aciunile pot consta din una sau mai multe instruciuni procedurale sau SQL. Tratarea
unei excepii ncepe cu cuvntul cheie WHEN i se termin n momentul nceperii tratrii altei
excepii (apariia altui cuvnt WHEN) sau n momentul terminrii blocului (apariia cuvntului END).
Sintaxa pentru tratarea excepiilor este urmtoarea:
WHEN nume_excepie THEN aciuni
Exemplu:
DECLARE
v_nume
angajati.nume%TYPE;
v_salariu angajati.salariu%TYPE;
BEGIN
SELECT nume, salariu INTO v_nume, v_salariu FROM angajati
WHERE data_nastere BETWEEN 01-JAN-74 AND 31-DEC-74;
EXCEPTION
WHEN no_data_found THEN
INSERT INTO tabel_erori
VALUES (Nimeni nscut n 74);
WHEN too_many_rows THEN
INSERT INTO tabel_erori
VALUES (Mai mult dect o persoan n 74);
END;
n exemplul de mai sus se trateaz dou excepii datorate faptului c o comand SELECT n
PL/SQL trebuie s returneze o singur nregistrare. Astfel, n cazul n care nici o nregistrare nu
ndeplinete criteriul de selecie n tabela tabel_erori va fi inserat o nregistrare ce va conine
irul de caractere Nimeni nscut n 74 iar n cazul n care mai multe nregistrri vor ndeplini
criteriul de selecie va fi inserat o nregistrare ce va conine irul de caractere Mai mult dect o
persoan n 74.
Excepiile pot fi activate explicit cu ajutorul comenzii RAISE nume_exceptie. Blocul PL/SQL
de mai jos verific dac n tabela angajati mai exist persoane cu numele IONESCU i
prenumele HORIA. nregistrarea va fi inserat numai dac nu mai exist nici o persoan cu acest
nume i prenume, n caz contrar eroarea este nregistrat ntr-un tabel de erori.
DECLARE
dummy
VARCHAR2(1);
BEGIN
SELECT 'x' INTO dummy
FROM angajati
WHERE nume='IONESCU' AND prenume='HORIA';
RAISE too_many_rows;
EXCEPTION
224

END;

WHEN no_data_found THEN


INSERT INTO angajati VALUES (101,IONESCU,HORIA);
WHEN too_many_rows THEN
INSERT INTO tabel_erori
VALUES (Mai exista persoane cu acest nume si prenume);

n cazul n care comanda SELECT nu va returna nici o nregistrare atunci controlul programului va
fi transferat instruciunii WHEN no_data_found din seciunea EXCEPTION. n mod similar,
dac sunt returnate mai multe nregistrri atunci controlul programului va fi transferat instruciunii
WHEN too_many_rows din seciunea EXCEPTION. Dac ns exact o nregistrare este selectat,
se va continua execuia programului cu urmtoarea instruciune. Aceasta va activa n mod explicit
excepia too_many_rows, astfel nct i n acest caz atunci controlul programului va fi tranferat
instruciunii WHEN too_many_rows.
Comanda SELECT i excepiile
Principalele excepii posibile a se ntlni ca urmare a rezultatului unei comenzi SELECT sunt
no_data_found (nici o nregistrare returnat) i too_many_rows (mai mult dect o
nregistrare returnat). Exemplul anterior ilustreaz modul de funcionare al acestor excepii. Se pot
defini mai multe excepii, fiecare cu propriul set de aciuni. De fiecare dat cnd apare o excepie,
PL/SQL va procesa numai seciunea de tratare a excepiilor aferenta acesteia.
Observaie: PL/SQL nu va declana nici o eroare de tip no_data_found sau too_many_rows
pentru comenzile de manipulare INSERT, UPDATE i DELETE.
Tratarea excepiilor cu WHEN OTHERS
Seciunea de tratare a excepiilor execut aciunile aferente fiecrei excepii specificate. Pentru a
evita tratarea fiecrei excepii n parte, se folosete seciunea de tratare WHEN OTHERS care va
cuprinde aciuni pentru orice excepie care nu a fost tratat, adic pentru capturarea excepiilor
neprevzute sau necunoscute.
Exemplu:
DECLARE
nr_cod INTEGER:=100;
BEGIN
SAVEPOINT aici;
INSERT INTO angajati (cod, nume, prenume)
VALUES (nr_cod, GEORGESCU, RADU);
EXCEPTION
WHEN dup_val_on_index THEN
nr_cod:=nr_cod+1;
ROLLBACK TO aici;
WHEN OTHERS THEN
INSERT INTO tabel_erori
VALUES (Eroare n timpul execuiei blocului);
END;
Blocul PL/SQL anterior creeaz mai nti un punct de salvare numit aici, dup care ncearc s
insereze n tabela angajai o nregistrare. Dac tabela conine deja o nregistrare ce are valoarea
din cmpul cod egal cu valoarea care se ncearc a fi introdus, atunci va fi declanat excepia
dup_val_on_index. Aceast excepie este activat numai dac coloana cod din tabelul
225

angajati are definit un index unic, situaie presupus n acest exemplu. n cadrul acestei
excepii se incrementeaz valoarea ce va fi introdus n cmpul cod, dup care tranzacia este
reluat prin derularea napoi pn la punctul de salvare aici. n cazul n care se declaneaz o alt
excepie diferit de excepia dup_val_on_index, atunci n tabela TABEL_ERORI va fi inserat
o nregistrare ce va conine irul de caractere Eroare n timpul execuiei blocului.
Seciunea de tratare a excepiilor WHEN OTHERS trebuie utilizat cu foarte mare atenie deoarece
poate masca erori critice sau poate mpiedica aplicaia s rspund n mod corespunztor. Este
recomandabil ca aceast seciune de tratare a erorilor s fie folosit ct mai puin cu putin fiind de
preferat referirea n mod explicit a fiecrei excepii n parte. n cazul n care seciunea WHEN
OTHERS este utilizat este recomandabil folosirea acesteia, dac este posibil, n blocul cel mai din
interior. Un exemplu de folosire abuziv a excepiei WHEN OTHERS este urmtorul:
EXCEPTION
WHEN OTHERS THEN
NULL;
END;
Practic seciunea de tratare WHEN OTHERS execut instruciunea NULL (instruciunea vid). Prin
executarea acestei excepii sunt ascunse toate erorile logice ale aplicaiei.
Funcii de gestionare a erorilor
La apariia unei excepii, cteodat este necesar s se cunoasc codul de eroare asociat sau mesajul
de eroare. Acest lucru este foarte important pentru tratarea excepiilor cu WHEN OTHERS, atunci
cnd este necesar alegerea unui anumit set de aciuni n funcie de eroare.
n acest sens PL/SQL conine dou funcii:
- SQLCODE - returneaz codul erorii asociat excepiei declanate;
- SQLERRM - returneaz un mesaj de eroare asociat excepiei declanate incluznd i numrul erorii.
Funciile SQLCODE i SQLERRM sunt folosite pentru a obine informaii referitoare la cea mai
recent excepie.
Exemplul urmtor preia codul de eroare i mesajul excepiei n cauz i le stocheaz n tabela
erori ce conine cmpurile cod i mesaj:
DECLARE
mesaj_eroare
VARCHAR2(60);
cod_mesaj NUMBER;
BEGIN
.....
EXCEPTION
WHEN OTHERS THEN
cod_mesaj:=SQLCODE;
mesaj_eroare:=SUBSTR(SQLERRM,1,60);
INSERT INTO erori (cod, mesaj)
VALUES (cod_mesaj, mesaj_eroare);
END;
Observaie: Funciile SQLERRM i SQLCODE nu se pot utiliza direct ca parte a unei instruciuni
INSERT sau SELECT. Aa cum este exemplificat mai sus, valorile funciilor trebuiesc atribuite
unor variabile locale, funcia SQLERRM unei variabile de tip caracter (irul de caractere se
trunchiaz la lungimea variabilei) iar funcia SQLCODE unei variabile de tip numeric.
226

Propagarea excepiilor
Atunci cnd este ntlnit o eroare, PL/SQL caut n sub-blocul curent rutina de tratare a erorii,
execut aciunile din aceast seciune, iar controlul este transferat celui mai apropiat bloc ce
urmeaz dup sfritul sub-blocului. Dac PL/SQL ntlnete o excepie ce nu este tratat n blocul
curent, atunci excepia se propag. Acesta nseamn c excepia se transmite i blocului cruia i
este transferat controlul, acest lucru realizndu-se pn n momentul cnd ntlnete un bloc ce
conine o seciune de tratare a excepiei respective. Dac nu exist nici un bloc ce conine o seciune
de manipulare a excepiei respective atunci n mediul programului gazd va aprea o eroare datorat
unei excepii netratate. n acest caz pe ecranul utilizatorului va fi afiat codul i mesajul de eroare.
De exemplu, n Forms va aparea mesajul FRM-40735 unhandled exception in.
Aceast trecere de la seciunea de tratare a excepiilor a unui bloc interior la seciunea de tratare a
excepiilor a unui bloc exterior ocolete executarea instruciunilor rmase n aceste blocuri, cu alte
cuvinte PL/SQL nu proceseaz aciunile dintre sfritul unui sub-bloc i cuvntul EXCEPTION al
blocului cruia i se transfer controlul.
Avantajul acestui comportament este faptul c tratarea erorilor proprii unor instruciuni se poate
face n blocul unde sunt apelate instruciunile, n timp ce tratarea excepiilor generale aferente
acestora se poate face n blocuri exterioare. Se recomand tratarea excepiilor proprii unor
instruciuni n blocul unde acestea au fost apelate pentru a preveni situaia cnd o excepie este
interceptat i tratat de o seciune de tratare a excepiilor necorespunztoare. De asemenea, trebuie
avut n vedere situaia cnd aciunile ce trateaz o anumit excepie pot genera o alt excepie.
Exemplu:
DECLARE
mesaj_eroare
VARCHAR2(60);
cod_mesaj NUMBER;
BEGIN
DECLARE
v1
NUMBER(4);
BEGIN
SELECT cod INTO v1 FROM angajati
WHERE functia=PRESEDINTE;
EXCEPTION
WHEN too_many_rows THEN
INSERT INTO mesaje
VALUES (Exista mai multi presedinti);
END;
DECLARE
v1
NUMBER(4);
BEGIN
SELECT cod INTO v1 FROM angajati
WHERE functia=MANAGER;
EXCEPTION
WHEN too_many_rows THEN
INSERT INTO mesaje
VALUES (Exista mai multi manageri);
END;
EXCEPTION
WHEN OTHERS THEN
cod_mesaj:=SQLCODE;
227

END;

mesaj_eroare:=SUBSTR (SQLERRM,1,60);
INSERT INTO erori (cod, mesaj)
VALUES (cod_mesaj, mesaj_eroare);

Exemplul anterior const dintr-un bloc PL/SQL ce conine la rndul lui dou sub-blocuri. Cele dou
sub-blocuri ncearc s selecteze din tabela angajai o nregistrare care are valoarea cmpului
funcie egal cu PRESEDINTE, respectiv MANAGER. Fiecare sub-bloc are propria seciune
de tratare a erorii too_many_rows n urma creia se insereaz n tabela mesaje irul de
caractere Exista mai multi presedinti, respectiv Exista mai multi manageri. La apariia ntr-un
sub-bloc a unei alte erori diferit de eroarea too_many_rows, eroarea respectiv se propag n
blocul exterior unde este tratat cu ajutorul seciuni WHEN OTHERS. n aceast seciune se preia
codul de eroare i mesajul excepiei n cauz i se stocheaz n tabela erori ce conine cmpurile
cod i mesaj.
Excepiile pot fi generate i n partea declarativ a unui bloc prin iniializarea incorect a unei
expresii. De exemplu, urmtoarea declaraie genereaz o excepie deoarece constanta limita nu
poate stoca numere mai mari dect 999:
DECLARE
limita CONSTANT NUMBER(3) := 5000; -- genereaz o excepie
BEGIN
...
EXCEPTION
WHEN OTHERS THEN
-- nu poate trata excepia aprut n partea de declaraie
n exemplul de mai sus blocul curent nu poate trata excepia aprut n partea de declaraie deoarece
aceasta se propag direct n blocul exterior.
Activarea excepiilor
Excepiile se pot activa n dou moduri:
Prin apariia unei erori Oracle, asociat cu o excepie, fapt care duce la activarea excepiei
respective n mod automat. De exemplu, dac la inserarea unei nregistrri n baza de date apare
eroarea ORA-0001 atunci PL/SQL activeaz excepia DUP_VAL_ON_INDEX;
Prin activarea excepiei explicit, utiliznd comanda RAISE n interiorul blocului. Cu aceast
comand se pot activa excepii predefinite sau definite de utilizator. Unele instrumente Oracle,
de exemplu Forms, au propriile excepii predefinite care pot fi activate cu comanda RAISE
pentru a fora producerea anumitor evenimente. Exemplificarea comenzii RAISE va fi fcut n
continuare n seciunea ce trateaz excepiile definite de utilizator.
Excepii definite de utilizator
Sunt acele excepii declarate n seciunea de declaraie a blocului. Excepiile definite de utilizator
sunt folosite n situaiile cnd nu se mai dorete procesarea aciunilor blocului i sunt activate atunci
cnd se ntlnesc anumite condiii definite de utilizator. Sintaxa pentru declararea excepiilor de
acest gen este urmtoarea:
nume_excepie EXCEPTION;

228

Pentru ca o excepie definit de utilizator s fie interceptat i tratat trebuiesc parcurse urmtoarele
etape:
- generarea excepiei n mod explicit n poriunea executabil a blocului, folosind comanda:
RAISE nume_exceptie;
- tratarea excepiei n seciunea de tratare a erorilor:
WHEN nume_exceptie THEN
Exemplu:
DECLARE
stoc_lips
EXCEPTION;
stoc
NUMBER(4);
BEGIN
SELECT cantitate INTO stoc FROM produse WHERE cod=101;
IF stoc < 10 THEN
RAISE stoc_lipsa;
END IF;
EXCEPTION
WHEN stoc_lipsa THEN
INSERT INTO alerta (cod_produs, cant)
VALUES (101, stoc);
END;
n exemplul de mai sus se definete excepia stoc_lipsa, dup care se selecteaz n variabila
stoc valoarea cmpului cantitate din tabela produse pentru nregistrarea ce are codul 101.
Dac stocul acestui produs este mai mic dect 10 atunci se genereaz excepia stoc_lipsa
folosind comanda RAISE. n seciunea de tratare a excepiei generate explicit se insereaz n tabela
alerta valoarea codului i a cantitii care este sub limita admis de politica companiei.
Asocierea unui cod de eroare Oracle cu un nume
Pentru a trata o eroare intern Oracle nenominalizat am putut vedea anterior cum se folosete
clauza WHEN OTHERS drept detector universal de excepii. O alt metod de a trata o eroare
nenominalizat este cu ajutorul directivei de compilare exception_init. PL/SQL conine nume
predefinite pentru o parte din codurile interne ale excepiilor, dar nu toate excepiile au nume
predefinite. Pentru a putea asocia un nume unui anumit cod intern de eroare se folosete directiva de
compilare exception_init. Acest lucru permite referirea oricrei excepii interne prin nume i
scrierea unei rutine specifice pentru tratarea ei.
Aceast directiv de compilare trebuie s apar n poriunea declarativ a unui bloc, pachet sau
subprogram i are urmtoarea sintax:
PRAGMA EXCEPTION_INIT (nume_exceptie, numar_cod_eroare);
Numele excepiei este numele unei excepii declarate anterior. Deci aceast directiv de compilare
trebuie s apar dup ce a fost declarat o excepie creia i se asociaz numele cu codul de eroare,
aa cum este ilustrat n exemplul urmtor.
DECLARE
detectare_deadlock EXCEPTION;
PRAGMA EXCEPTION_INIT (detectare_deadlock, -60);
BEGIN
...
EXCEPTION
229

END;

WHEN detectare_deadlock THEN


-- aciuni specifice de tratare a excepiei
...

Executarea aceluiai set de aciuni pentru excepii nominalizate explicit


Pentru a executa acelai set de aciuni n cazul mai multor excepii nominalizate explicit, n
seciunea de manipulare a excepiilor se poate utiliza clauza OR:
WHEN invalid_number OR value_error
THEN INSERT INTO tabel_erori
VALUES (....);
9.13 Utilizarea explicit a cursoarelor
Aa cum am mai spus, de fiecare dat cnd se execut o comanda SQL, serverul bazei de date
deschide o arie de memorie n care comanda este analizat i executat. Un cursor este o construcie
PL/SQL ce permite denumirea acestor arii de memorie i accesarea informaiilor referitoare la
acesta. n sistemul Oracle exist dou tipuri de cursoare:
- cursoare implicite sunt acele cursoare declarate n mod implicit de ctre PL/SQL pentru
fiecare din instruciunile INSERT, UPDATE, DELETE i SELECT. Acest lucru survine
indiferent dac interogarea returneaz una sau mai multe linii
- cursoare explicite sunt acele cursoare declarate de utilizator i folosite pentru procesarea
rezultatelor comenzilor SELECT care returneaz linii multiple.
n lipsa cursoarelor explicite, proiectantul de aplicaii Oracle ar trebui s preia i s gestioneze n
mod explicit fiecare linie selectat de interogare. Liniile multiple returnate de o interogare poart
numele de setul activ de nregistrri. Dimensiunea setului activ reprezint numrul de linii care au
rezultat n urma interogrii.
Pentru a controla un cursor explicit trebuiesc parcurse urmtoarele etape:
1. Declararea cursorului
2. Deschiderea cursorului
3. Preluarea datelor n cursor
4. nchiderea cursorului
Numrul maxim de cursoare ce pot fi deschise simultan este stabilit de parametrul de iniializare
OPEN_CURSOR. Nu exist o limit a valorii pe care o poate avea acest parametru, singura limitare
fiind dat de memoria disponibil pentru gestionarea acestora.
Declararea cursoarelor
Declararea unui cursor const n denumirea cursorului i asocierea unei interogri cursorului
declarat. Interogarea asociat este analizat (sunt validate coloanele i tabelele) dar nu este
executat. Numele care este atribuit unui cursor nu este o variabil PL/SQL ci un identificator
nedeclarat ce este folosit pentru a face referire la interogare. Numele unui cursor nu se poate folosi
n expresii i nici nu se pot atribui valori numelui unui cursor. Sintaxa pentru declararea unui cursor
explicit este urmtoarea:
CURSOR nume_cursor IS interogare;

230

Interogarea asociat cursorului este o comand SELECT ce nu include clauza INTO.


Exemplul1:
DECLARE
CURSOR c1 IS
SELECT nume, prenume, salariu
FROM angajati
WHERE salariu > 1000000;
Exemplul2:
DECLARE
CURSOR c2 (v_sal NUMBER, v_functie VARCHAR2) IS
SELECT nume, prenume, salariu
FROM angajati
WHERE salariu > v_sal AND functie = v_functie;
Deschiderea cursoarelor
Deschiderea cursoarelor explicite se realizeaz cu comanda OPEN i duce la executarea interogrii
i identificarea setului activ de nregistrri. Sintaxa este urmtoarea:
OPEN nume_cursor[(lista_argumente)];
Exemplu:
OPEN c1;
n cazul deschiderii unui cursor cu parametrii, trebuiesc fcute asocieri ntre parametrii actuali i cei
formali innd cont de poziia acestora n sintaxa de definire a cursorului. Astfel pentru cursorul c2
definit anterior putem folosi urmtoarea comanda de deschidere a cursorului:
OPEN c2 (1000000, ANALIST);
Parametrii actuali dint-un cursor sunt n general constante dar pot fi i variabile PL/SQL sau
variabile ale programului gazda:
OPEN c2 (v_salariu, ANALIST);
-- unde v_salariu este o variabil PL/SQL
Atunci cnd este executat comanda OPEN cursorul identific acele linii care satisfac interogarea,
adic liniile nu sunt citite pn cnd nu se deschide cursorul. Dup deschidere cursorul este
iniializat pe prima linie a setului activ.
n cazul n care cursorul este declarat cu clauza FOR UPDATE aceasta nu i va pierde semnificaia,
adic n momentul deschiderii cursorului sistemul Oracle va bloca liniile care ndeplinesc criteriile
de cutare ale interogrii.
Preluarea datelor n cursor
Preluarea datelor n cursor este realizat cu comanda FETCH, comand care preia liniile din setul
activ de nregistrri una cte una i le introduce n variabile PL/SQL sau variabile ale programului
gazd. Trebuiesc specificate variabile pentru fiecare coloan din interogarea asociat cursorului sau
se poate folosi o singur variabil de tip nregistrare. Aceste variabile trebuiesc declarate nainte de
a utiliza comanda FETCH. Sintaxa comenzii FETCH este urmtoarea:
FETCH nume_cursor INTO variabile;
Exemplul 1:
231

DECLARE
CURSOR c1 IS
SELECT nume, prenume, salariu
FROM angajati
WHERE salariu > 1000000;
.........
BEGIN
OPEN c1;
FETCH c1 INTO v_nume, v_prenume, v_salariu;
.........
END
Exemplul 2:
DECLARE
CURSOR c1 IS
SELECT nume, prenume, salariu
FROM angajati
WHERE salariu > 1000000;
inreg c1%ROWTYPE;

BEGIN
OPEN c1;
FETCH c1 INTO inreg;

END;
De fiecare dat cnd este utilizat o comand FETCH cursorul avanseaz la linia urmtoare a setului
activ. Mai mult, singura cale de a parcurge setul activ este prin intermediul acestei comenzi. Dac
se dorete consultarea unei linii deja prelucrat anterior, trebuie s nchidei i s redeschidei
cursorul, dup care s preluai liniile una cte una pn se ajunge la linia dorit. Dac setul activ a
fost parcurs, urmtoarea comand FETCH va ntoarce valori nule n variabile. Acest lucru nu va
cauza o eroare. n schimb, dac se mai ncearc executarea unei comenzi FETCH se va genera o
eroare.
ntr-o comand SQL ce este folosit n interiorul unui bloc se poate folosi clauza WHERE CURRENT
OF dac se dorete o referire la linia curent din setul activ al cursorului. Acest lucru permite
modificri sau tergeri ale liniei adresate, fr a se mai utiliza n mod explicit o referin folosind
ROWID. Pentru ca rndurile accesate de cursor s fie blocate n vederea modificrii sau tergerii lor,
trebuie folosit clauza FOR UPDATE n interogarea aferent cursorului.
Exemplu:
DECLARE
CURSOR c1 IS
SELECT nume, prenume, salariu
FROM angajati
WHERE salariu > 1000000
FOR UPDATE OF salariu;
inreg c1%ROWTYPE;
BEGIN
OPEN c1;
FETCH c1 INTO inreg;
IF inreg.nume = ION THEN
DELETE FROM angajati WHERE CURRENT OF c1;
232

END IF;
-- alte aciuni
END;
nchiderea cursoarelor
nchiderea cursoarelor se realizeaz cu comanda CLOSE. Aceast comanda nchide explicit cursorul
fcnd posibil redeschiderea lui. Comanda CLOSE are urmtoarea sintax:
CLOSE nume_cursor;
Exemplu:
CLOSE c1;
Atunci cnd utilizatorul nchide legtura cu serverul, cursorul se nchide n mod implicit.
Atributele cursoarelor
Pentru a evalua ce s-a ntmplat n momentul cnd un cursor a fost utilizat, PL/SQL ofer
programatorului patru atribute: %ISOPEN, %ROWCOUNT, %FOUND i %NOTFOUND. Aceste
atribute se folosesc att pentru cursoarele explicite ct i pentru cursoarele implicite (despre care am
vorbit la nceputul acestui capitol). n cazul folosirii atributelor unui cursor implicit, acestea sunt
precedate de numele implicit al cursorului, adic SQL (exemplu: SQL%ISOPEN,
SQL%ROWCOUNT, SQL%FOUND i SQL%NOTFOUND). Dac se dorete folosirea atributelor unui
cursor explicit, acestea trebuiesc precedate la rndul lor de numele cursorului explicit (exemplu:
c1%ISOPEN, c1%ROWCOUNT, c1%FOUND i c1%NOTFOUND). Semnificaia fiecrui atribut al
unui cursor explicit este descris n tabelul de mai jos.
Atribut
%ROWCOUNT

Tip dat
ntreg

%FOUND

Boolean

%NOTFOUND

Boolean

%ISOPEN

Boolean

Descriere
Conine numrul total de linii preluate pn la un anumit moment de
comanda FETCH. n momentul deschiderii cursorului acest atribut
are valoarea zero, dup prima preluare cu comanda FETCH are
valoarea 1, .a.m.d.
Acest atribut are valoarea True dac cea mai recent comand
FETCH a preluat o linie din setul activ. Dup deschiderea cursorului
i naintea prelurii cu comanda FETCH acest atribut are valoarea
Null. Dup prima preluare, acest atribut va avea valoarea True pn
n momentul n care comanda FETCH nu mai returneaz nici o linie.
Acest atribut are valoarea True n cazul n care cea mai recent
comand FETCH nu a mai returnat nici o linie. Acest atribut este
opusul logic al atributului %FOUND i este folosit pentru a prsi
ciclul atunci cnd nu mai este nici o linie de preluat din setul activ.
Acest atribut are valoarea True n cazul n care cursorul este deja
deschis.

Exemplu de utilizare a atributului %ISOPEN:


IF c1%ISOPEN THEN
FETCH c1 INTO v_nume, v_prenume, v_salariu;
ELSE
OPEN c1;
END IF;

233

n mod uzual atunci cnd se dorete procesarea liniilor dintr-un cursor explicit se folosete un ciclu
iterativ n care este executat o instruciune FETCH. Eventual acest ciclu poate procesa toate
rndurile din setul activ pn cnd instruciunea FETCH seteaz atributul %NOTFOUND pe valoarea
True, adic setul activ a fost parcurs. n momentul n care se seteaz atributul %NOTFOUND pe
valoarea True, comanda FETCH va ntoarce valori nule n variabile. Dac n continuare se execut o
alt comand FETCH, atunci Oracle va genera eroarea ORA-1002: Fetch out of
sequence, eroare care va duce, n general, la terminarea execuiei blocului datorit unei excepii
netratate. Este deci foarte important ca de fiecare dat cnd se preiau date din cursor s se testeze
rezultatul acestei prelucrri nainte de a mai face referiri ulterioare la cursorul respectiv.
Exemplu:
OPEN c1;
LOOP
FETCH c1 INTO v_nume, v_prenume, v_salariu;
EXIT WHEN c1%NOTFOUND;
END LOOP;
CLOSE c1;
Ciclul iterativ destinat unui cursor (CURSOR FOR LOOP)
PL/SQL ofer programatorilor un tip special de ciclu iterativ aferent unui cursor explicit (CURSOR
FOR LOOP). Sintaxa pentru un astfel de ciclu este urmtoarea:
FOR nume_inregistrare IN nume_cursor[{parametrii}]LOOP

END LOOP;
Un astfel de ciclu simplific codificarea prin efectuarea automat a urmtoarelor operaii:
- deschiderea cursorului la iniializarea ciclului;
- executarea unei instruciuni FETCH la fiecare parcurgere a ciclului;
- prsirea ciclului atunci cnd toate liniile din setul activ au fost procesate;
- nchiderea cursorului la prsirea ciclului.
Un alt aspect foarte important este faptul c variabila nume_inregistrare nu trebuie declarat
deoarece este intern ciclului i scopul ei dureaz atta timp ct ciclul este executat. n interiorul
unui astfel de ciclu pot fi testate atribute ale cursorului.
Exemplu:
DECLARE
CURSOR c1 IS
SELECT nume, prenume, salariu FROM angajai;
...
BEGIN
FOR angajat_inreg IN c1 LOOP
...
salariu_total := salariu_total + angajat_inreg.salariu;
END LOOP;
END;
O alt metod eficient de a simplifica codul este folosirea unui ciclu ce proceseaz liniile returnate
de o interogare definit chiar la nceputul ciclului. Practic, este definit un cursor chiar la intrarea n
ciclu:

234

FOR angajat_inreg IN
(SELECT nume FROM angajati WHERE salariu >1000000) LOOP
IF angajat_inreg.nume = ION THEN
END LOOP;
Deoarece cursorul creat este intern ciclului, acesta nu trebuie declarat. n acest caz nu se pot testa
atributele cursorului deoarece acesta nu are nume.
Cursoare cu parametri
n interogarea asociat cursorului se pot face referiri la variabile cu condiia ca acestea s fie
declarate naintea declarrii cursorului. Pe lng variabile se pot folosi i parametri. Parametri sunt
folosii pentru a transfera cursorului diverse valori n momentul cnd acesta este deschis. Valorile
transferate pot fi utilizate de interogare la momentul execuiei acesteia. Acest lucru nseamn c
programatorul poate deschide un cursor explicit de mai multe ori pe parcursul unui bloc, de fiecare
dat rezultnd un alt set activ. Sintaxa pentru definirea unui cursor explicit cu parametri este
urmtoarea:
CURSOR nume_cursor (nume_parametru tip_data)
IS interogare;
Tipurile de date ale parametrilor sunt aceleai ca cele ale variabilelor scalare, cu deosebirea c
pentru parametri nu pot aplica constrngeri asupra tipului de dat.
Exemplul urmtor ilustreaz declararea cursorului c2 ce are parametri param1 i param2. Aceti
parametri permit transferarea valorii salariului precum i a funciei salariatului necesare n clauza
WHERE. Cursorul poate fi deschis de mai multe ori dar cu valori diferite ale parametrilor, de
exemplu OPEN c2 (90000, FUNCTIONAR) sau OPEN c2 (250000, MANAGER),
rezultnd seturi active diferite.
DECLARE
CURSOR c2 (param1
NUMBER, param2 VARCHAR2)
IS
SELECT nume, prenume, salariu, functie
FROM angajati
WHERE salariu > param1
AND functie = param2;
9.14 Proceduri i funcii
Dup cum am vzut la nceputul capitolului, n PL/SQL se pot defini subprograme, acestea fiind
blocuri PL/SQL crora li se pot transmite parametrii i care pot fi apelate din alte programe. Exist
dou feluri de subprograme PL/SQL: proceduri i funcii. O funcie este un bloc PL/SQL care
accept orice numr de parametrii de intrare sau ieire i returneaz o valoare. Din acest motiv o
funcie nu poate fi apelat dect ca parte a unei atribuiri. O procedur este un bloc PL/SQL care
accept orice numr de parametrii de intrare sau ieire dar nu returneaz n mod explicit nici o
valoare.
O procedur sau funcie are dou pri: specificaia i corpul. Specificaia unei proceduri ncepe de
la cuvntul cheie PROCEDURE i se sfrete cu numele procedurii sau cu lista de parametrii. n
cazul unei funcii specificaia ncepe de la cuvntul cheie FUNCTION i se sfrete cu clauza
RETURN, clauz care specific tipul de dat al valorii returnate.

235

Corpul unei proceduri sau funcii ncepe cu cuvntul cheie IS i se termin cu cuvntul cheie END
urmat n mod opional de numele acesteia. Corpul unei proceduri sau funcii are trei pri: partea
declarativ, partea executabil i partea de tratare a excepiilor.
Partea declarativ conine declaraii de tipuri, cursoare, constante, variabile, excepii i subprograme
interne. Aceste obiecte sunt locale i exist doar atta timp ct subprogramul este n execuie.
Cuvntul cheie DECLARE, care introduce partea de declaraii pentru un bloc anonim nu este utilizat
n acest caz.
Partea executabil conine instruciuni de atribuire, de control i de manipulare a structurilor Oracle
i este localizat ntre cuvntul cheie BEGIN i cuvntul EXCEPTION (sau END). n cazul unei
proceduri trebuie s existe cel puin o instruciune n aceast seciune. Dac se dorete ca procedura
s nu fac nimic se poate utiliza instruciunea NULL. n cazul unei funcii aceast seciune trebuie s
conin cel puin o instruciune RETURN (a nu se confunda instruciunea RETURN cu clauza
RETURN din partea de specificaie a unei funcii)
Partea de manipulare a excepiilor trateaz excepiile generate n timpul execuiei subprogramului i
este situat ntre cuvntul cheie EXCEPTION i END. Sintaxa unei funcii i sintaxa unei proceduri
n PL/SQL sunt prezentate explicit mai jos:
Funcie

Procedur
PROCEDURE nume_procedur [list
parametrii]
IS
[declaraii locale]
BEGIN
partea executabil
[EXCEPTION
partea de manipulare a excepiilor]
END[nume_procedur];

FUNCTION nume_funcie [list parametrii]


RETURN tipul_datei
IS
[declaraii locale]
BEGIN
partea executabil
[EXCEPTION
partea de manipulare a excepiilor]
END[nume_funcie];

Dup cum se poate observa mai sus, declaraiile locale ct i partea de tratare a excepiilor sunt
opionale, ns partea executabil este n mod obligatoriu necesar.
Funciile i procedurile pot fi declarate n orice bloc, subprogram sau pachet PL/SQL. Funciile i
procedurile trebuiesc ns declarate la sfritul seciunii declarative, dup toate celelalte elemente
ale programului. Astfel, urmtoarea declaraie este incorect deoarece procedura calcul trebuie
s se gseasc pe ultima poziie, nainte de declararea variabilei suma i a cursorului c1.
DECLARE
PROCEDURE calcul (...) IS
BEGIN
...
END;
suma NUMBER;
CURSOR c1 IS SELECT * FROM angajati;
Vom exemplifica n continuare procedura crestere_salariu, procedur care mrete salariul
unui angajat ce are un anumit cod cu o anumit valoare:
PROCEDURE crestere_salariu (cod_sal INTEGER, crestere INTEGER) IS
236

salariu_curent INTEGER;
lipsa_salariu EXCEPTION;
BEGIN
SELECT sal INTO salariu_curent FROM angajati
WHERE cod = cod_sal;
IF salariu_curent IS NULL THEN
RAISE lipsa_salariu;
ELSE
UPDATE angajati SET sal = sal + crestere
WHERE cod = cod_sal;
END IF;
EXCEPTION
WHEN NO_DATA_FOUND THEN
INSERT INTO erori
VALUES (cod_sal, 'Nu exista nici un angajat cu acest
cod');
WHEN lipsa_salariu THEN
INSERT INTO erori
VALUES (cod_sal, 'Salariul este necunoscut);
END crestere_salariu;
n momentul apelrii, aceast procedur are ca parametrii codul angajatului i valoarea cu care
crete salariul. Codul angajatului este folosit pentru a selecta salariul curent. Dac nu exist nici un
angajat cu acest cod sau dac salariul este necunoscut, se genereaz o excepie. Altfel, valoarea
salariului crete cu valoarea parametrului crestere al procedurii.
O procedur este apelat ca orice instruciune
crestere_salariu de mai sus poate fi apelat:

PL/SQL.

De

exemplu,

procedura

crestere_salariu (101, 50000);


n continuare vom exemplifica funcia sal_cunoscut, care verific dac salariul unui anumit
angajat este cunoscut sau nu:
FUNCTION sal_cunoscut (cod_sal INTEGER) RETURN BOOLEAN IS
salariu_curent INTEGER;
gasit
BOOLEAN :=False;
BEGIN
SELECT sal INTO salariu_curent FROM angajati
WHERE cod = cod_sal;
IF salariu_curent IS NOT NULL THEN
gasit :=True;
END IF;
RETURN gasit;
EXCEPTION
WHEN NO_DATA_FOUND THEN
INSERT INTO erori
VALUES (cod_sal, 'Nu exista nici un angajat cu acest
cod');
RETURN gasit;
END sal_cunoscut;
n momentul apelrii, aceast funcie are drept parametru de intrare codul angajatului. Codul
237

angajatului este folosit n continuare pentru a selecta salariul curent. Dac nu exist nici un angajat
cu acest cod, se genereaz o excepie iar funcia ntoarce valoarea False. Altfel, dac salariul este
cunoscut funcia ntoarce valoarea True iar dac salariul este necunoscut funcia ntoarce valoarea
False.
O funcie este apelat ca parte a unei atribuiri. De exemplu, funcia sal_cunoscut de mai sus,
poate fi apelat:
succes := sal_cunoscut (cod_s);
Instruciunea RETURN
Aa cum am observat n exemplul de mai sus, instruciunea RETURN determin ntreruperea
imediat a execuiei subprogramului i revenirea n programul apelant. Execuia continu n
programul apelant cu instruciunea care urmeaz dup apelul procedurii. A nu se confunda
instruciunea RETURN cu clauza RETURN, clauz care specific tipul de dat returnat de funcie. Un
subprogram poate conine mai multe instruciuni RETURN dar utilizarea mai multor puncte de ieire
dintr-un subprogram nu este recomandat.
n cazul unei proceduri instruciunea RETURN nu poate conine nici o expresie deoarece dintr-o
procedur nu se ntoarce nici o valoare, aceast instruciune determinnd ntreruperea nainte de a se
ajunge la sfritul procedurii.
n cazul unei funcii instruciunea RETURN trebuie s conin n mod obligatoriu o expresie care
este evaluat la momentul execuiei instruciunii. Acest lucru este impus chiar de definiia unei
funcii care trebuie s ntoarc n mod obligatoriu o valoare. Valoarea rezultat n urma acestei
evaluri este atribuit numelui funciei care acioneaz n acest sens ca o variabil ce are tipul
specificat n clauza RETURN.
Parametrii subprogramelor
Procedurile i funciile pot avea sau nu parametrii. Parametrii sunt folosii pentru a transfera
informaii ntre subprogram i mediul apelant. Variabilele sau expresiile referite n lista de
parametri la apelul unei proceduri se numesc parametrii actuali. De exemplu, urmtorul apel al
procedurii crestere_salariu (procedur descris anterior) conine parametrii actuali
cod_angaj i bonus:
crestere_salariu (cod_angaj, bonus);
Variabilele declarate n specificaia unui subprogram i referite n corpul acestuia se numesc
parametrii formali. De exemplu, procedura crestere_salariu conine parametrii formali
cod_sal i crestere declarai n specificaia acesteia.
PROCEDURE cretere_salariu (cod_sal INTEGER, crestere INTEGER) IS
Este recomandabil s se utilizeze nume diferite pentru parametrii actuali i parametrii formali. n
momentul apelrii parametrii actuali sunt evaluai iar valorile rezultate sunt atribuite parametrilor
formali corespondeni. Parametrul actual i parametrul formal corespunztor acestuia trebuie s aib
tipuri de date compatibile.
Asupra unui parametru nu se poate impune constrngerea NOT NULL. De asemenea, nu se pot
238

specifica constrngeri asupra dimensiunii tipului de dat al parametrului. De exemplu, urmtoarea


declaraie este incorect deoarece impune o constrngere asupra dimensiunii parametrului.
PROCEDURE insert_sal (cod_sal NUMBER(4)) IS ...
--incorect deoarece trebuie s fie NUMBER
Exist trei moduri de transmitere a parametrilor ntre mediul apelant i subprogram: IN (parametrii
de intrare), OUT (parametrii de ieire) i IN OUT (parametrii de intrare-ieire). Semnificaia fiecrui
mod n parte este descris n continuare. n cazul n care modul de transmitere nu este specificat n
mod explicit, valoarea default a acestuia este IN.
Modul de transmitere

Descriere
Transmite o valoare dinspre mediul apelant n subprogram.

IN (default)
(parametru de intrare)

Parametrul formal nu poate fi schimbat n interiorul


subprogramului deci am putea spune c acioneaz ca o constant.
Parametrul actual poate fi o constant, un ir de caractere, o
variabil iniializat sau o expresie.
Parametrul actual este transferat prin valoare (printr-o copie a
valorii)

OUT
(parametru de ieire)

Returneaz o valoare din subprogram n mediul apelant.


Parametrul formal trebuie s fie o variabil, nu o constant sau o
expresie. Acest parametru se comport ca o variabil
neiniializat i nu poate fi folosit n expresii. n interiorul
subprogramului parametrului OUT trebuie s i se atribuie o
valoare care se dorete a ajunge n mediul apelant.
Parametrul actual trebuie s fie o variabil.
Parametrul actual este transferat prin referin (printr-un pointer
ctre valoarea parametrului de intrare)

IN OUT
(parametru de intrareieire)

Transmite o valoare dinspre mediul apelant n subprogram, i


dup execuia acestuia, returneaz din subprogram n mediul
apelant o valoare posibil diferit.
Parametrul formal se comport ca o variabil iniializat. n
interiorul subprogramului trebuie s i se atribuie o valoare.
Parametrul actual trebuie s fie o variabil.
Parametrul actual este transferat prin referin (printr-un pointer
ctre valoarea parametrului de intrare)

Un subprogram poate s transmit anumite valori mediului apelant n dou moduri:


- prin intermediul numelui unei funcii deoarece aceasta trebuie s returneze n mod obligatoriu o
valoare;
- prin intermediul parametrilor de ieire OUT sau IN OUT.
n cazul n care este necesar transmiterea unei singure valori mediului apelant este recomandat
folosirea unei funcii prin intermediul numelui acesteia. n cazul n care este necesar transmiterea
mai multor valori mediului apelant este recomandat folosirea unei proceduri ce conine parametri
de ieire. Este de evitat folosirea parametrilor de ieire OUT sau IN OUT n cazul unei funcii
deoarece scopul unei funcii este de a returna o singur valoare.
239

n continuare vom prezenta exemple ce conin anumite erori datorate modului greit de folosire al
parametrilor pentru fiecare mod de transmitere n parte.
Aa cum am mai menionat anterior, ntr-un subprogram un parametru IN acioneaz ca o constant
i prin urmare nu i se pot atribui valori. Urmtorul exemplu va genera o eroare de compilare
datorat ncercrii de a atribui unui parametru de intrare IN o anumit valoare:
PROCEDURE bonus (cretere INTEGER) IS
bonus_minim CONSTANT INTEGER:= 100000;
BEGIN

IF bonus_minim > cretere THEN


cretere := bonus_minim;
-- n acest punct se va genera o eroare de compilare
END IF;

END bonus;
Un parametru OUT acioneaz ca o variabil neiniializat i deci valoarea ei nu poate fi atribuit
unei alte variabile. Exemplul de mai jos ilustreaz o procedur care va genera o eroare de compilare
datorat ncercrii de a atribui valoarea unui parametru OUT unei alte variabile.
PROCEDURE calc_bonus (cod_angaj IN INTEGER, bonus OUT INTEGER) IS
cretere INTEGER;
BEGIN
SELECT sal * 0.30 INTO bonus FROM angajai
WHERE cod = cod_angaj;
cretere := bonus;
-- n acest punct se va genera o eroare de compilare
END calc_bonus;
Parametrul actual ce corespunde unui parametru formal OUT trebuie s fie o variabil, i nu o
constant sau expresie. Prin urmare apelurile urmtoare sunt incorecte:
calc_bonus (101, 200000);
sau
calc_bonus (101, salariu + comision);
Ca i variabilele, un parametru formal OUT este iniializat cu valoarea Null. Prin urmare, nainte de
a iei dintr-un subprogram n mod obligatoriu parametrilor formali OUT trebuie s li se atribuie o
valoare. n caz contrar, parametri actuali corespondeni acestora vor avea valoarea Null.
Un parametru IN OUT permite transferul unei valori n subprogramul apelat i returneaz mediului
apelant o alt valoare. n interiorul unui subprogram, un parametru IN OUT acioneaz ca o
variabil iniializat. Prin urmare, acestui parametru i pot fi atribuite valori sau poate fi atribuit
unor alte variabile. Cu alte cuvinte, un parametru formal IN OUT poate fi folosit ca o variabil
obinuit.
9.14.1 Proceduri i funcii stocate
Subprogramele pot fi definite de orice utilitar Oracle care folosete limbajul PL/SQL. Utilitare
240

precum Forms i Reports stocheaz aceste subprograme local, caz n care ele sunt accesibile numai
aplicaiei i utilitarului respectiv. Pentru ca aceste subprograme s poat fi folosite de orice utilitar
Oracle, ele trebuiesc stocate n baza de date. Astfel de proceduri sau funcii se numesc proceduri
sau funcii stocate. Odat ce sunt compilate i stocate n dicionarul de date, procedurile i funciile
devin obiecte ale bazei de date care pot fi accesate de orice numr de aplicaii conectate la acea baz
de date.
Aceste funcii i proceduri sunt stocate gata compilate. Deci, n momentul cnd sunt apelate, ele
sunt ncrcate i transmise motorului PL/SQL imediat. De asemenea, funciile i procedurile stocate
beneficiaz de capacitatea de a utiliza n comun memoria sistemului Oracle. Doar o copie a oricrui
subprogram trebuie s fie ncrcat n memorie pentru mai muli utilizatori.
9.14.2 Crearea, recompilarea, distrugerea i utilizarea subprogramelor
Crearea subprogramelor
Procedurile i funciile stocate pot fi create folosind comenzile SQL CREATE PROCEDURE i
respectiv CREATE FUNCTION. O procedur sau funcie stocat nu poate fi modificat ci trebuie s
fie nlocuit cu o nou definiie sau trebuie s fie distrus. Opiunea OR REPLACE (CREATE OR
REPLACE PROCEDURE i CREATE OR REPLACE FUNCTION) permite nlocuirea definiiei
unei funcii sau proceduri fr a fi necesar distrugerea n prealabil a acesteia. Practic, acest
opiune se folosete pentru a nlocui o versiune mai veche a unei proceduri cu o nou versiune.
Aceast nlocuire pstreaz intacte toate privilegiile. n schimb, dac distrugei procedura i o
recreai, privilegiile sunt distruse i trebuie s le reconstruii. Dac comanda CREATE
PROCEDURE sau CREATE FUNCTION este folosit fr opiunea OR REPLACE pentru a crea
o procedur sau funcie care exist deja, va fi generat un mesaj de eroare.
Exemplul de mai jos creeaz funcia stocat select_manager, funcie ce returneaz codul
managerului unui salariat, iar n cazul n care salariatul este inexistent returneaz valoarea -1.
CREATE OR REPLACE FUNCTION select_manager (v_cod IN number)
RETURN NUMBER IS
v_manager number(10):= -1;
BEGIN
SELECT manager INTO v_manager FROM salariat
WHERE cod_salariat = v_cod;
RETURN v_manager;
EXCEPTION
WHEN NO_DATA_FOUND THEN RETURN v_manager;
END select_manager;
Recompilarea subprogramelor
Procedurile i funciile existente pot fi recompilate folosind comenzile SQL ALTER FUNCTION i
respectiv ALTER PROCEDURE. Recompilarea unei proceduri sau funcii nu modific declaraia
sau definiia procedurii. Dac recompilarea se ncheie cu succes, procedura sau funcia devine
valid iar la momentul execuiei nu se mai recompileaz. Aceasta duce la eliminarea procesrilor
suplimentare i a erorilor de compilare la execuie.
Exemplu:
ALTER FUNCTION select_manager COMPILE;

241

Distrugerea subprogramelor
Pentru a distruge o procedur sau funcie se folosesc comenzile DROP PROCEDURE sau DROP
FUNCTION.
Exemplu:
DROP FUNCTION select_manager;
Apelarea subprogramelor
Apelurile funciilor definite n blocuri PL/SQL i subprograme pot aprea n instruciuni
procedurale, dar nu n comenzi SQL. De exemplu, urmtoarea comand INSERT este ilegal:
INSERT INTO angajai (cod_salariat, nume, prenume, data_nastere,
manager)
VALUES
(sal_seq.nextval,
'Ion',
'Clin',
'11-JAN-67',
select_manager (10));
Apelarea unei proceduri sau funcii stocate se poate face din mai multe medii: SQL*Plus,
Oracle*Forms sau alte instrumente Oracle, precum i din alte proceduri sau funcii sau dintr-un
declanator. Exemplul urmtor apeleaz funcia select_manager din SQL*Plus:
SQL> VARIABILE cod NUMBER
SQL> EXECUTE :cod:=select_manager (10);
O procedur sau funcie poate fi executat i de ctre ali utilizatori dac acetia au acest privilegiu.
Privilegiul de execuie este acordat direct utilizatorilor i nu unor anumite roluri. Utilizatorul care
are drepturi de execuie are implicit i drepturi asupra obiectelor coninute de procedura sau funcia
respectiv, dar numai prin intermediul acesteia. Dac nu se dorete ca utilizatorii s acceseze
tabelele bazei de date n mod direct, se poate crea o aplicaie n care utilizatorii s poat accesa
tabelele bazei de date numai prin intermediul procedurilor sau funciilor. Acest lucru reprezint o
puternic facilitate ce duce la mrirea securitii.
Vederea USER_SOURCE din dicionarul de date conine codul surs al unei proceduri, funcii sau
pachet stocat. Pentru a putea de exemplu s vizualizm codul surs al funciei select_manager vom
folosi urmtoarea interogare:
SELECT text FROM user_source
WHERE name = select_manager AND type = FUNCTION
ORDER BY line;
Dac se dorete ca utilizatorii s nu poat vizualiza codul surs al unei proceduri sau funcii, se
poate utiliza utilitarul Oracle Wrapper. Acest utilitar convertete codul surs n format binar,
fiierele rezultate avnd extensia *.plb.
Avantajele folosirii subprogramelor
Avantajele folosirii procedurilor si funciilor stocate:
- deoarece sunt stocate n baza de date pot furniza un control centralizat, sunt portabile i
minimizeaz traficul de reea ntr-un mediu client/server. Odat validate, ele pot fi folosite n
mod repetat fr a fi necesar redistribuirea lor n reea;
- sunt lansate n execuie fr a se mai recompila;
242

deoarece funciile i procedurile au nume ele pot fi referite din alte uniti de program, acest
lucru permind folosirea unui cod de mai multe ori fr a se mai rescrie;
prin utilizarea utilitarului PL/SQL Wrapper codul surs poate deveni invizibil utilizatorului final
prin scrierea blocurilor PL/SQL n format binar. Acest lucru duce la mrirea securitii i
permite protejarea informaiilor mpotriva modificrii;
accesul la baza de date se poate restrnge, utilizatorii neputnd accesa datele dect prin
intermediul procedurilor rezidente.

9.15 Pachete
Din punct de vedere literar un pachet reprezint unul sau mai multe obiecte nfurate ntr-o
nvelitoare. Un pachet n sine nu are nici o valoare, dar permite prezentarea unui produs ntr-o
form mai frumoas. Un pachet Oracle are un neles similar, adic permite gruparea mai multor
obiecte PL/SQL ntr-un tot unitar. Aceste obiecte pot fi constante, variabile, cursoare, funcii,
proceduri i excepii. Cu toate c formatul unui pachet este asemntor cu formatul subprogramelor,
spre deosebire de acestea, pachetul nsui nu poate fi apelat sau imbricat i nu i se pot transfera
parametrii.
Pachetele sunt formate din dou pari: specificaia (package specification) i corpul pachetului
(package body).
Specificaia este partea pachetului care realizeaz interfaa acestuia cu aplicaia. Aici se declar
variabilele, constantele, excepiile, cursoarele i subprogramele (proceduri sau funcii) publice,
adic obiectele care urmeaz a fi folosite n afara pachetului. Astfel, putem spune c specificaia
unui pachet conine declaraii publice.
Corpul pachetului conine detalii de implementare i declaraiile care nu pot fi vzute n afara
pachetului. Declaraiile coninute de corpul unui pachet sunt declaraii private. Corpul pachetului
definete complet cursoarele, funciile i procedurile, implementnd n acest fel specificaia.
Uneori, corpul pachetului nu este necesar - nu exist nici declaraii locale i nici partea de
implementare - deci poate lipsi. Acest lucru se ntmpl dac specificaia pachetului declar numai
variabile, constante i excepii.
Corpul pachetului poate fi modificat sau nlocuit fr a fi necesar schimbarea specificaiei acestuia,
adic schimbarea interfeei cu aplicaia. Se poate astfel modifica definiia unui obiect din corpul
pachetului, fr ca prin aceasta Oracle s invalideze celelalte obiecte care apeleaz obiectul
respectiv sau care fac referire la el, cum s-ar ntmpla dac ai modifica specificaia pachetului.
Sintaxa specificaiei i a corpului unui program sunt prezentate n continuare.
Specificaia pachetului:
PACKAGE nume IS
declaraii de tipuri i obiecte publice
specificaiile subprogramelor publice
END [nume];
Corpul pachetului:
PACKAGE nume IS
declaraii de tipuri i obiecte private
implementarea subprogramelor
[BEGIN
instruciuni de iniializare]
END [nume];
243

9.15.1 Pachete stocate


n mod similar cu procedurile i funciile de sine stttoare, pentru ca un pachet s poat fi utilizat
de orice utilitar sau aplicaie Oracle, este necesar ca acesta s fie stocat n baza de date dup ce a
fost n prealabil compilat. Astfel de pachete se numesc pachete stocate.
Specificaia i corpul pachetului sunt stocate separat. Acest lucru face ca celelalte obiecte s
depind numai de specificaie, nu i de corpul pachetului. Aceast separare permite modificarea
definiiei unui obiect din corpul pachetului, fr ca prin aceasta Oracle s invalideze celelalte
obiecte care apeleaz obiectul respectiv sau care fac referire la el, cum s-ar ntmpla dac s-ar
modifica specificaia pachetului.
9.15.2 Crearea, recompilarea, distrugerea i utilizarea pachetelor stocate
Crearea pachetelor
Specificaia unui pachet se poate crea folosind comanda SQL CREATE PACKAGE, iar corpul unui
pachet folosind comanda SQL CREATE PACKAGE BODY. Opiunea OR REPLACE (CREATE
OR REPLACE PACKAGE i CREATE OR REPLACE PACKAGE BODY) permite modificarea
specificaiei sau corpului unui pachet fr a fi necesar distrugerea n prealabil a acestora.
n exemplul urmtor, se creeaz specificaia pachetului gestiune_angajati ce cuprinde un tip
de dat nregistrare, un cursor i dou proceduri.
CREATE OR REPLACE PACKAGE gestiune_angajati AS
TYPE tip_angaj IS RECORD (cod_angaj INTEGER, salariu REAL);
CURSOR salariu_descresc RETURN tip_angaj;
PROCEDURE
cretere_salariu
(cod_sal
INTEGER,
crestere
INTEGER);
PROCEDURE concediaz_angajat (cod_sal NUMBER);
END gestiune_angajati;
Definiiile obiectelor publice declarate n specificaia pachetului gestiune_angajati sunt
coninute n corpul acestuia. Corpul pachetului se creeaz n modul urmtor:
CREATE OR REPLACE PACKAGE BODY gestiune_angajati AS
CURSOR salariu_descresc RETURN tip_angaj IS
SELECT cod, sal FROM angajati ORDER BY sal DESC;
PROCEDURE
cretere_salariu
(cod_sal
INTEGER,
crestere
INTEGER) IS
salariu_curent INTEGER;
BEGIN
SELECT sal INTO salariu_curent FROM angajai
WHERE cod = cod_sal;
UPDATE angajai SET sal = sal + crestere
WHERE cod = cod_sal;
EXCEPTION
WHEN NO_DATA_FOUND THEN
INSERT INTO erori
VALUES (cod_sal, 'Nu exist nici un angajat cu
acest cod');
244

END crestere_salariu;
PROCEDURE concediaza_angajat (cod_sal NUMBER) IS
BEGIN
DELETE FROM angajati WHERE cod = cod_sal;
END concediaza_angajat;
END gestiune_angajati;
Pentru a face referire la obiectele unui pachet, trebuie folosit notaia cu punct. Sintaxa general
este urmtoarea:
nume_pachet.nume_obiect
Aa cum am mai menionat, obiectele care sunt declarate n corpul pachetului nu pot fi utilizate
dect n pachetul respectiv. De exemplu, codul PL/SQL din exteriorul pachetului nu poate face
referire la nici una dintre variabilele care au fost declarate n corpul pachetului. Pentru ca variabila
s fie vizibil n exteriorul pachetului, aceasta trebuie declarat n partea de specificaie i nu n
corpul pachetului.
O observaie foarte important este faptul c variabilele, constantele i cursoarele au un anumit
domeniu de vizibilitate ce depinde de locul n care apare declaraia. De exemplu, n cazul
procedurilor sau funciilor, variabilele, constantele i cursoarele exist numai pe durata apelului i
i pierd valoarea atunci cnd execuia procedurii sau funciei se ncheie. Dac variabilele,
constantele i cursoarele sunt declarate n specificaia sau n corpul unui pachet, atunci valorile lor
exist pe toat durata sesiunii utilizatorului. n schimb, valorile lor se pierd atunci cnd pachetul
este recompilat.
Recompilarea pachetelor
Pachetele existente pot fi re-compilate folosind comanda SQL ALTER PACKAGE, avnd sintaxa:
ALTER PACKAGE nume_pachet COMPILE [PACKAGE|BODY];
n cazul n care dup cuvntul cheie COMPILE apare opiunea BODY, este recompilat doar corpul
pachetului, iar n caz contrar - dac apare opiunea PACKAGE sau opiunea este omis - sunt
recompilate att specificaia ct i corpul pachetului.
Distrugerea pachetelor
Distrugerea unui pachet se realizeaz cu comanda DROP PACKAGE, avnd sintaxa:
DROP PACKAGE nume_pachet [PACKAGE|BODY];
n cazul n care apare opiunea BODY, este distrus doar corpul pachetului, iar n caz contrar - dac
apare opiunea PACKAGE sau opiunea este omis - sunt distruse att specificaia ct i corpul
pachetului.
Atunci cnd pachetul este distrus, toate obiectele dependente de acesta devin invalide. Dac este
distrus numai corpul unui pachet, nu i specificaia acestuia, toate obiectele dependente rmn
valide. n schimb, nu putei apela nici una dintre procedurile i funciile rezidente declarate n
specificaia pachetului, pn cnd nu recreai corpul pachetului.
Pentru a distruge un pachet, acesta trebuie s se gseasc n schema dumneavoastr sau s posedai
privilegiul de sistem DROP ANY PROCEDURE.
245

Suprancrcarea
Sistemul Oracle permite existena n acelai bloc, subprogram sau pachet a mai multor funcii sau
proceduri cu acelai nume. Aceast tehnic este cunoscut sub numele de suprancrcare.
Suprancrcarea se folosete atunci cnd se dorete executarea unei proceduri sau funcii de mai
multe ori ns cu argumente de tipuri diferite. Oracle determin care dintre procedurile sau funciile
cu acelai nume va fi apelat prin verificarea parametrilor formali ai acesteia.
Avantajele folosirii pachetelor stocate
Pachetele ofer urmtoarele avantaje:
- funciile i procedurile stocate sunt organizate mai eficient prin gruparea acestora n funcie de
anumite criterii;
- pachetele permit suprancrcarea procedurilor i funciilor, rezolvnd conflictele de nume din
cadrul unei scheme. Suprancrcarea unei proceduri sau a unei funcii nseamn crearea n
acelai pachet a mai multor proceduri sau funcii cu acelai nume, dar cu argumente diferite;
- variabilele publice i cursoarele pachetelor persist pe durata ntregii sesiuni. Prin urmare,
acestea se pot referi din orice mediu sau procedur;
- gestionarea funciilor i a procedurilor stocate se realizeaz cu uurin datorit facilitii de a
putea modifica corpul unui pachet fr a modifica i specificaia acestuia;
- se mbuntete securitatea funciilor i procedurilor stocate prin ascunderea codului surs
astfel nct utilizatorii nu pot avea acces la acesta;
- privilegiul de executare al unui pachet include privilegiul de executare al tuturor funciilor i
procedurilor coninute de acesta, prin urmare nu este necesar acordarea privilegiilor pentru
fiecare funcie sau procedur n parte, permind astfel acordarea de privilegii n mod eficient;
- se mbuntete performana prin ncrcarea n memorie a ntregului pachet n momentul
primei apelri a acestuia. Prin urmare, apelrile viitoare ale pachetului duc la mbuntirea
timpului de rspuns datorit faptului c vor fi necesare mai puine operaii de I/O.
Sfaturi n legtur cu utilizarea pachetelor stocate
Pentru a realiza o ct mai bun performan la utilizarea pachetelor, n continuare vom prezenta
cteva sfaturi:
- n momentul crerii pachetelor acestea trebuiesc s fie ct mai simple i generale pentru a putea
fi reutilizate n aplicaii viitoare;
- evitai crearea pachetelor care reproduc funcionaliti Oracle existente;
- deoarece un pachet reflect design-ul aplicaiei, creai corpul pachetului dup ce ai conceput
aplicaia. n specificaia pachetului trebuiesc plasate numai acele obiecte care vrei s fie vizibile
tuturor utilizatorilor;
- pentru a reduce necesitatea recompilrii atunci cnd codul este modificat, plasai ct mai puine
obiecte n specificaia unui pachet. Modificarea corpului unui pachet nu necesit recompilarea
procedurilor dependente. n schimb, modificarea specificaiei unui pachet face ca toate
subprogramele rezidente care fac referire la pachetul respectiv s fie recompilate.
9.15.3 Pachete predefinite
Baza de date Oracle furnizeaz o serie de pachete predefinite ce ajut la realizarea aplicaiilor
bazate pe PL/SQL. Numele i funcionalitatea celor mai importante pachete sunt prezentate n
tabelul urmtor, pentru informaii suplimentare privind funciile i procedurile coninute n
pachetele utilizate mai frecvent urmnd a consulta anexa 7.

246

Nume pachet predefinit

Funcionalitate
Afieaz informaii (n general, pe ecran) atunci cnd se
DBMS_OUTPUT
execut un bloc sau un subprogram PL/SQL, ajutnd la testarea
i depanarea acestuia.
Recompileaz proceduri, funcii sau pachete i analizeaz
DBMS_DDL
indeci, tabele sau clusteri.
Utiliti DBA (analizeaz obiectele dintr-o anumit schem,
DBMS_UTILITY
verific dac serverul ruleaz n mod paralel i returneaz
timpul n sutimi de secund, etc).
Modific anumite caracteristici ale sesiunii unui utilizator,
DBMS_SESSION
seteaz rolul unui utilizator i reiniializeaz starea unui pachet.
DBMS_SQL
Acceseaz baza de date folosind SQL dinamic.
Controleaz i mbuntete performanele tranzaciilor bazei
DBMS_TRANSACTION
de date.
Operaii de comunicare ntre dou sau mai multe sesiuni
DBMS_PIPE
conectate la aceai instan Oracle.
Avertizeaz o sesiune atunci cnd apere un eveniment n baza
DBMS_ALERT
de date.
DBMS_LOCK
Folosirea exclusiv sau partajat a unei resurse.
Permite execuia perodic a procedurilor stocate, oferind o cale
DBMS_JOB
de a gestiona procesele ce se execut n fundal.
DBMS_APPLICATION_INFO Informeaz serverul de aciunile ntreprinse de o aplicaie.
DBMS_SNAPSHOT
Proceduri pentru exploatarea instantaneelor.
DBMS_REFRESH
Administreaz grupurile de remprosptare.
DBMS_LOB
Permite accesul eficient la date de tip LOB.
Permite citirea i scrierea fiierelor text ale sistemului de
UTL_FILE
operare.

247

9.16 Triggere (declanatori)


Un trigger (declanator) al bazei de date este un bloc PL/SQL stocat n baza de date, care este
asociat unui tabel i care este executat n mod implicit ori de cte ori asupra tabelului asociat este
lansat o anumit comand DML (INSERT, UPDATE sau DELETE). Triggerul este invocat fie
nainte, fie dup executarea instruciunii DML, iar creatorul triggerului va specifica momentul
executrii declanatorului n raport cu instruciunea DML corespunztoare. O noutate adus de
versiunea Oracle8 sunt triggerele INSTEAD OF, care se execut n locul instruciunilor DML
efectuate asupra unei vederi; despre acestea vom vorbi ceva mai trziu, la sfritul acestei seciuni,
n ceea ce urmeaz referindu-ne deocamdat numai la triggerele asociate tabelelor.
Dei prezint similariti cu procedurile stocate, triggerele difer de acestea prin urmtoarele:
Un trigger este invocat n mod implicit la lansarea unei comenzi DML pe tabelul asociat, n timp
ce o procedur este invocat n mod explicit. n plus, utilizatorul care lanseaz comanda DML nu
are nevoie de nici un privilegiu pentru executarea triggerului. Practic triggerul este executat
indiferent de utilizatorul care este conectat la baza de date sau de aplicaia care este utilizat. Mai
mult dect att, utilizatorul respectiv nu are nici un control asupra execuiei triggerului;
Un trigger este stocat n baza de date ca text i compilat n momentul rulrii. Din acest motiv este
recomandat ca un trigger s fie alctuit n principal din apeluri de proceduri stocate;
Un trigger este asociat unui tabel, dar nu i unei vederi sau sinonim al tabelului. Practic, atunci
cnd este executat o instruciune DML asupra unei vederi, sunt executai declanatori asociai
tabelelor de baz ale vederii.
Scopurile pentru care sunt utilizai declanatorii
Declanatorii bazei de date garanteaz c o aciune este executat n momentul cnd o tabel este
modificat. Declanatorii suplimenteaz facilitile standard Oracle prin furnizarea anumitor
elemente de gestiune a bazelor de date. De exemplu, un declanator poate impune restricii asupra
execuiei operaiilor DML asupra unui tabel ntr-un anumit interval de timp, cum ar fi n afara
orelor de program sau n week-end. Declanatorii mai pot fi folosii i n alte scopuri, cum ar fi:
- impunerea respectrii unor condiii complexe de integritate (referenial sau de comportament);
dac aceste constrngeri sunt prea complicate i nu pot fi definite prin intermediul
constrngerilor de integritate ale tabelelor, ele pot fi implementate cu ajutorul triggerelor;
- popularea coloanelor redundante n cazul tabelelor denormalizate (de exemplu, calculul unui
total);
- transformarea ntr-un anumit format standard a datelor ce urmeaz a fi inserate n tabel; de
exemplu, dac se dorete conversia tuturor numelor ntr-un format predefinit nainte de a fi
inserate ntr-un tabel, triggerele pot furniza o conversie centralizat a acestora;
- culegerea de informaii statistice n legtur cu accesarea tabelelor;
- ntreinerea sincronizat a copiilor tabelelor situate n diferite noduri ale unei baze de date
distribuite; dei exist opiuni de replicare Oracle, triggerele se pot folosi n mod extensiv pentru
duplicarea datelor.
Declanatorii trebuiesc folosii numai atunci cnd este necesar. Utilizarea excesiv a declanatorilor
poate duce la o interdependen complex care va face dificil gestionarea unei aplicaii mari. De
exemplu, cnd un declanator este invocat, aciunile coninute de acesta pot invoca la rndul lor alt
declanator. Atunci cnd o comand coninut de un declanator invoc la rndul ei un alt
declanator, se spune c declanatoarele sunt n cascad. n acest sens trebuie acordat o foarte
mare atenie folosirii declanatorilor deoarece acetia pot deveni recursivi. Acest lucru se ntmpl
n cazul n care o comand coninut de un declanator invoc la rndul ei acelai declanator,
acesta executndu-se pn la terminarea resurselor de memorie.

248

Observaie: Declanatorii unei baze de date nu trebuiesc confundai cu declanatorii utilitarului


Oracle Forms, acetia din urm fiind definii, stocai i executai n mod diferit de ctre acest
utilitar.
9.16.1 Declanatorii i constrngerile de integritate
Majoritatea aspectelor privind integritatea datelor pot fi definite i impuse folosind constrngerile
de integritate furnizate de ctre Oracle. Pentru condiiile mai complexe, care nu pot fi definite n
acest mod, se pot folosi triggerele bazei de date. Triggerele nu trebuie folosite ns pentru a simula
constrngeri de integritate existente (NOT NULL, UNIQUE, PRIMARY KEY, FOREIGN KEY,
CHECK). Cel mai frecvent, triggerele se folosesc n urmtoarele cazuri:
pentru a impune integritatea referenial la modificarea sau tergerea rndurilor din tabelele
master prin atribuirea valorii Null sau unei valori implicite cheilor strine care fac referin la
datele terse sau modificate
pentru a impune reguli de integritate referenial ntre tabele situate n diferite noduri ale unei
baze de date distribuite.
pentru impunerea unor constrngeri complexe de comportament care nu pot fi definite utiliznd
constrngerea CHECK.
9.16.2 Sintaxa declanatorilor i modul de creare
Un trigger este alctuit din trei pri:
1. evenimentul declanator instruciunea cere a dus la invocarea declanatorului:
- INSERT
- UPDATE
- DELETE
2. condiia de declanare
3. corpul declanatorului un bloc PL/SQL
Pentru crearea unui declanator al bazei de date asociat unei anumite tabele, se utilizeaz
instruciunea CREATE TRIGGER. Sintaxa utilizat pentru a crea un declanator este urmtoarea:
CREATE [OR REPLACE] TRIGGER nume_declanator
{BEFORE|AFTER} eveniment_declanator ON nume_tabel
{REFERECING {NEW AS | OLD AS} nume_calificativ}
[FOR EACH ROW]
[WHEN {condiie}]
[DECLARE
Seciune declarativ opional ce conine toate declaraiile
tipurilor,
variabilelor,
constantelor
i
subprogramelor
locale.]
BEGIN
Seciunea executabil a declanatorului
[EXCEPTION
Seciune opional de tratare a excepiilor.]
END;
Urmtorul exemplu creeaz un declanator asociat tabelei salariai:
CREATE OR REPLACE TRIGGER modificari_salariu
BEFORE INSERT OR UPDATE ON salariati -- evenimentul declanator
FOR EACH ROW
249

WHEN (new.cod > 0)


-- restricia de declanare
DECLARE
-- corpul declanatorului
dif_sal
NUMBER;
BEGIN
dif_sal := :new.sal - :old.sal;
DBMS_OUTPUT.PUT_LINE('Salariu vechi: ' || :old.sal);
DBMS_OUTPUT.PUT_LINE('Salariu nou: ' || :new.sal);
DBMS_OUTPUT.PUT_LINE('Diferenta ' || dif_sal);
END;
Dup ce declanatorul a fost creat, n momentul n care va fi lansat n execuie o comand DML,
ca de exemplu:
UPDATE salariati SET sal = sal + 500.00
WHERE nrdept = 10
declanatorul va fi executat n mod implicit. Prin urmare, pentru exemplul de mai sus, va fi afiat
salariul vechi, salariul nou i diferena dintre cele dou salarii pentru fiecare rnd afectat de ctre
comanda UPDATE. Pseudo-nregistrrile :new i :old sunt utilizate de ctre declanatoarele la
nivel de rnd pentru a accesa valorile noi i vechi ale coloanelor rndului curent procesat de ctre
trigger. Mai multe detalii despre aceste pseudo-nregistrri vor fi prezentate ceva mai trziu, n
seciunea dedicat declanatoarelor la nivel de rnd.
Ca i n cazul procedurilor sau funciilor stocate, opiunea OR REPLACE permite modificarea unui
declanator fr a fi necesar tergerea n prealabil a acestuia.
n aceeai schem nu pot exista doi declanatori cu acelai nume. n schimb, numele declanatorilor
pot fi identice cu numele altor obiecte ale schemei, cum ar fi tabele, vederi sau proceduri. De
exemplu, un tabel i un trigger pot avea acelai nume, dar este recomandabil s se evite aceast
situaie.
n continuare, pornind de la exemplul anterior, vom explica fiecare parte a unui declanator precum
i unele caracteristici ale acestora.
Evenimentul declanator
Evenimentul declanator este o comand DML (INSERT, UPDATE sau DELETE) care face ca un
declanator s fie executat. n acelai declanator al bazei de date poate fi inclus orice combinaie
de evenimente declanatoare, ns trebuie specificat cel puin un eveniment. n exemplul de mai sus
combinaia de evenimente declanatoare este:
INSERT OR UPDATE ON salariati
iar evenimentul care declaneaz efectiv acest trigger este:
UPDATE ON salariati
Dac n cazul operaiilor INSERT i DELETE condiia de declanare nu poate face referin dect la
ntreaga nregistrare, n cazul operaiei UPDATE se poate face referire i la una sau mai multe
coloane ale nregistrrii. Prin urmare, n cazul comenzii UPDATE evenimentul declanator al
triggerului bazei de date poate fi definit sub forma:

250

UPDATE OF sal, nrdept ON salariati


n acest caz, orice comand UPDATE care va modifica un alt cmp dect sal sau nrdept, nu va
produce activarea declanatorului.
Pentru a realiza un declanator care s controleze operaii DML multiple executate asupra aceleiai
tabele dar totui s execute blocuri de cod diferite, n funcie de instruciunea declanatoare, se pot
utiliza predicatele INSERTING, DELETING sau UPDATING. Pentru a nelege modul de
funcionare al acestor predicate, vom modifica exemplul anterior astfel nct declanatorul s
execute blocuri diferite n funcie de instruciunea care a provocat declanarea.
CREATE OR REPLACE TRIGGER modificari_salariu
BEFORE INSERT OR UPDATE ON salariati
FOR EACH ROW
WHEN (new.cod > 0)
DECLARE
dif_sal
number;
BEGIN
IF UPDATING THEN
dif_sal := :new.sal - :old.sal;
dbms_output.put_line('Salariu vechi: ' || :old.sal);
dbms_output.put_line('Salariu nou: ' || :new.sal);
dbms_output.put_line('Diferenta ' || dif_sal);
END IF;
IF INSERTING THEN
dbms_output.put_line('Se insereaz un nou angajat');
END IF;
END;
Condiia de declanare
Restricia de declanare specific o expresie boolean care trebuie s fie adevrat pentru ca
declanatorul s fie activat. Aceast condiie nu poate s fie o condiie PL/SQL, ci trebuie s fie o
condiie SQL ce nu poate conine o subinterogare. Spre deosebire de celelalte seciuni ale
declanatorului, aceast seciune poate lipsi. Restricia de declanare este specificat cu ajutorul
clauzei WHEN. n exemplul de mai sus restricia de declanare este:
new.cod > 0
n momentul n care clauza WHEN este inclus, expresia este evaluat pentru fiecare nregistrare
afectat. Dac restricia de declanare are valoarea false sau este necunoscut aciunile coninute
de un declanator nu sunt executate. Evaluarea expresiei din clauza WHEN nu are nici un efect
asupra execuiei comenzii declanatoare, adic comanda nu este anulat dac expresia nu este
adevrat.
De exemplu, pentru triggerul modificari_salariu de mai sus, corpul declanatorului nu va fi
executat dac noua valoare a cmpului cod are valoarea zero, null sau negativ.
Corpul declanatorului
Corpul declanatorului este un bloc PL/SQL ce este executat atunci cnd se ncearc execuia unei
comenzi cuprinse n evenimentul declanator i cnd restricia de declanare ia valoarea true
251

(dac aceasta exist). Ca orice procedur stocat, corpul declanatorului poate conine comenzi SQL
i PL/SQL, poate defini variabile, constante, cursoare i excepii, i poate apela alte proceduri
stocate. n plus, pentru declanatorii la nivel de rnd (descrii n continuare) exist cteva
construcii speciale ce pot fi incluse n blocul PL-SQL:
- predicatele INSERTING, DELETING i UPDATING;
- nume de corelare pentru vechile i noile valori ale coloanelor rndului curent procesat de trigger;
- opiunea REFERENCING.
Ultimele dou construcii speciale sunt descrise n seciunea ce trateaz declanatorii la nivel de
rnd.
Asupra corpului unui declanator se aplic urmtoarele restricii:
- nu poate conine o interogare sau o modificare a unui tabel aflat n plin proces de modificare n
timp ce declanatorul acioneaz. De exemplu, executarea unei instruciuni UPDATE asupra
unui tabel nu va permite ca declanatorul ce acioneaz ca rezultat al acestei instruciuni s
interogheze sau modifice tabelul respectiv;
- nu poate conine o comand de control a tranzaciilor, cum ar fi COMMIT, ROLLBACK i
SAVEPOINT;
- nu poate conine nici o comand DDL deoarece aceasta apeleaz n mod implicit comanda
COMMIT nainte de se executa;
- coloanele de tip LONG sau LONG ROW ale unei tabele nu pot fi folosite n interiorul unui
declanator dect dac au fost convertite n prealabil n tipul CHAR sau VARCHAR2.
Dac n timpul execuiei unui trigger este declanat o excepie, toate efectele corpului triggerului
precum i comanda declanatoare sunt derulate napoi. Astfel, corpul unui trigger poate preveni
execuia unei comenzi declanatoare prin activarea unei excepii n interiorul acestuia. n acest
context, excepiile definite de utilizator sunt des folosite pentru a impune constrngeri de integritate
sau autorizri complexe pentru securitatea datelor.
Dac corpul declanatorului necesit mai mult de 60 de linii de cod, este preferabil s mpachetai
codul ntr-o procedur stocat separat, i s apelai apoi aceast procedur din interiorul
declanatorului.
9.16.3 Tipuri de declanatori
Aa cum am vzut n sintaxa comenzii CREATE TRIGGER, exist anumite clauze folosite pentru a
crea un anumit tip de declanator. Din acest punct de vedere exist mai multe tipuri de declanatori:
n funcie de numrul de ori de care este executat un declanator
- la nivel de rnd (FOR EACH ROW) declanatorul se execut pentru fiecare rnd n parte ce
este afectat de instruciunea declanatoare;
- la nivel de instruciune declanatorul se execut o singur dat pentru instruciunea
declanatoare indiferent de numrul de linii afectate;
n funcie de momentul n care declanatorul este executat:
- BEFORE declanatorul este executat naintea executrii instruciunii declanatoare;
- AFTER declanatorul este executat dup executarea instruciunii declanatoare;
Prin urmare, tipurile posibile de declanatori ce pot fi creai pentru o tabel, n funcie de frecvena
de execuie, instruciunea declanatoare i momentul declanrii, sunt cele prezentate n tabelul de
mai jos:

252

Nume

Funcie

BEFORE INSERT

Acioneaz o singur dat, naintea executrii unei


instruciuni INSERT

BEFORE INSERT FOR EACH ROW

Acioneaz nainte de crearea fiecrei noi nregistrri

AFTER INSERT

Acioneaz o singur dat, dup executarea unei


instruciuni INSERT

AFTER INSERT FOR EACH ROW

Acioneaz dup crearea fiecrei noi nregistrri

BEFORE UPDATE

Acioneaz o singur dat, naintea executrii unei


instruciuni UPDATE

BEFORE UPDATE FOR EACH ROW

Acioneaz nainte de actualizarea fiecrei nregistrri

AFTER UPDATE

Acioneaz o singur dat, dup executarea unei


instruciuni UPDATE

AFTER UPDATE FOR EACH ROW

Acioneaz dup actualizarea fiecrei nregistrri

BEFORE DELETE

Acioneaz o singur dat, naintea executrii unei


instruciuni DELETE

BEFORE DELETE FOR EACH ROW

Acioneaz nainte de tergerea fiecrei nregistrri

AFTER DELETE

Acioneaz o singur dat, dup executarea unei


instruciuni DELETE

AFTER DELETE FOR EACH ROW

Acioneaz dup tergerea fiecrei nregistrri

n cazul n care sunt definii mai muli declanatori de acelai tip, acetia nu sunt executai ntr-o
anumit ordine. Prin urmare trebuie avut n vedere faptul c integritatea bazei de date nu trebuie s
depind n acest caz de ordinea de execuie. Dac ordinea de execuie este important se recomand
rescrierea ntr-un singur declanator.
Declanatorii la nivel de rnd
Un declanator la nivel de rnd este executat de fiecare dat cnd un rnd este afectat de
instruciunea declanatoare. De exemplu, dac o comand UPDATE actualizeaz 10 rnduri,
declanatorul este executat de 10 ori. Dac instruciunea declanatoare nu afecteaz nici o
nregistrare, declanatorul nu este executat de loc. Un declanator la nivel de rnd este creat prin
specificarea opiunii FOR EACH ROW. Dac opiunea nu este inclus, declanatorul este considerat
a fi un declanator la nivel de instruciune.
Declanatorii la nivel de rnd sunt foarte folositori atunci cnd aciunile cuprinse n corpul
declanatorului depind de valorile rndurilor care sunt afectate de instruciunea declanatoare.
Aa cum am mai menionat, declanatorii la nivel de rnd conin construcii speciale ce pot fi
incluse n corpul acestuia: predicatele condiionale (INSERTING, DELETING i UPDATING),
nume de corelare pentru vechile i noile valori ale coloanelor rndului curent procesat de trigger,
precum i opiunea REFERENCING.
Nume de corelare pentru valorile noi i vechi ale coloanelor

253

n interiorul corpului unui declanator, se pot accesa noile i vechile valori ale coloanelor rndului
curent procesat de trigger. n acest context exist dou nume de corelare pentru valorile fiecrei
coloane ale tabelului ce este actualizat: un nume pentru vechile valori i un nume pentru noile
valori. Dac o instruciune are nevoie de o valoare dintr-o nregistrare nou sau actualizat, se
utilizeaz :new. Dac o instruciune are nevoie de valoarea unei coloane nainte ca ea s fi fost
modificat, se utilizeaz :old. n funcie de tipul comenzii declanatoare, anumite nume de
corelare nu pot avea nici o semnificaie. n cazul unei instruciuni INSERT, vechile valori ale
coloanelor au valoarea Null, n timp ce n cazul instruciunii DELETE sunt Null noile valori ale
coloanelor.
Numele de corelare se pot utiliza att n corpul declanatorului ct i n clauzele opionale WHEN i
REFERENCING. Cele dou puncte care preced cuvintele cheie new i old sunt obligatorii atunci
cnd acestea se utilizeaz n interiorul declanatorului. Cele dou puncte nu sunt permise atunci
cnd se utilizeaz cuvintele cheie new i old n clauzele opionale WHEN i REFERENCING.
Cuvintele cheie new i old nu pot fi utilizate cu coloane de tip LONG i LONGRAW.
Opiunea REFERENCING
Opiunea REFERENCING poate fi specificat n interiorul unui declanator la nivel de rnd pentru a
evita conflictele de nume ce apar ntre numele de corelare i o tabel a bazei de date ce este
denumit new sau old. Conflictele de nume ce apar se datoreaz faptului c new i old nu sunt
cuvinte rezervate, i prin urmare se pot crea tabele denumite new sau old, fapt care ar provoca
ambiguiti. n general aceast opiune este destul de rar utilizat pentru c se evit crearea unor
tabele denumite new sau old.
Presupunem c avem un tabel numit new ce conine cmpurile camp1 (number) i camp2
(character). Urmtorul exemplu creeaz un declanator asociat tabelei new, exemplu n care se evit
conflictele de nume dintre numele tabelului i numele de corelare pentru valorile vechi i noi ale
coloanelor rndului curent procesat de trigger:
CREATE OR REPLACE TRIGGER modificari_salariu
BEFORE ON new
REFERENCING new AS nou
FOR EACH ROW
BEGIN
:nou.camp2 := TO_CHAR (:nou.camp1);
END;
n exemplul de mai sus, prin utilizarea opiunii REFERENCING new AS nou, noile valori ale
coloanelor rndului curent procesat de trigger sunt referite utiliznd numele de corelare nou, n loc
de new.
Declanatorii la nivel de instruciune
Un declanator la nivel de instruciune este executat o singur dat pentru instruciunea
declanatoare, indiferent de numrul nregistrrile afectate (chiar i n cazul n care nu este afectat
nici o nregistrare). De exemplu, dac o instruciune UPDATE actualizeaz 10 rnduri, declanatorul
este executat o singur dat.
Declanatorii la nivel de instruciune sunt foarte folositori atunci cnd aciunile cuprinse n corpul
declanatorului nu depind de valorile rndurilor care sunt afectate de instruciunea declanatoare.
254

De exemplu, dac un declanator realizeaz o constrngere de securitate referitoare la data i ora la


care un utilizator poate modifica anumite tabele, atunci se va utiliza un declanator la nivel de
instruciune.
Declanatorii BEFORE
Declanatorii BEFORE sunt executai naintea instruciunii declanatoare. Acest tip de declanator
este n general folosit n urmtoarele situaii.
- pentru a modifica valorile coloanelor naintea finalizrii instruciunii declanatoare INSERT
sau UPDATE;
- pentru a determina dac instruciunea declanatoare trebuie executat sau nu. n acest fel se
pot elimina procesrile inutile ale instruciunii declanatoare.
Declanatorii AFTER
Declanatorii AFTER sunt executai dup executarea instruciunii declanatoare. Acest tip de
declanator este n general folosit n urmtoarele situaii.
- cnd instruciunea declanatoare se dorete a fi executat indiferent de alte condiii;
- pentru a executa aciuni suplimentare fa de aciunile declanatorului BEFORE, cnd acesta
exist.
Noile i vechile valori ale coloanelor rndului curent procesat de trigger sunt disponibile pentru
declanatorii la nivel de nregistrare, att BEFORE ct i AFTER. Noile valori ale coloanelor pot fi
modificate ntr-un declanator la nivel de nregistrare BEFORE, ns nu pot fi modificate ntr-un
declanator la nivel de nregistrare AFTER deoarece instruciunea declanatoare se execut nainte
ca declanatorul s fie invocat. Dac un declanator la nivel de nregistrare BEFORE schimb
valoarea new.coloan, un declanator la nivel de nregistrare AFTER invocat de aceeai
instruciune declanatoare vede modificrile realizate de ctre declanatorul BEFORE.
Declanatorii la nivel de nregistrare AFTER sunt ceva mai eficieni dect declanatorii BEFORE la
nivel de nregistrare. Pentru un declanator BEFORE la nivel de nregistrare, blocul de date afectat
de instruciunea declanatoare trebuie citit logic de dou ori: o dat pentru declanator i o dat
pentru instruciunea declanatoare. n schimb, pentru un declanator AFTER la nivel de nregistrare,
blocul de date afectat de instruciunea declanatoare trebuie citit logic o singur dat, att pentru
declanator ct i pentru instruciunea declanatoare.
Odinea de execuie a triggerelor
Ordinea de execuie a triggerelor depinde de tipul acestora. La apariia unei comenzi DML se
execut urmtorul algoritm:
1. Se execut toi declanatorii BEFORE la nivel de instruciune;
2. Pentru fiecare rnd afectat de comanda DML:
a. Se execut toi declanatorii BEFORE la nivel de rnd;
b. Se blocheaz i modific rndul afectat i se verific constrngerile de integritate.
Blocarea rmne valabil pn n momentul n care tranzacia este permanentizat.
c. Se execut toi declanatorii AFTER la nivel de rnd;
3. Se verific constrngerile de integritate amnate;
4. Se execut toi declanatorii AFTER la nivel de instruciune.
Algoritmul de execuie a triggerelor poate s prezinte mici variaii sau s devin recursiv, n funcie
de declanatorii n cascad i de tipul declanatorilor lansai. O remarc important este faptul c
toate aciunile i verificrile efectuate ca urmare a apariiei unei instruciuni declanatoare trebuie s
255

se deruleze cu succes. Dac n interiorul unui trigger este generat o excepie care nu este tratat n
mod explicit, triggerul este oprit i toate modificrile efectuate de el sunt derulate napoi.
Declanatorii INSTEAD OF
O noutate adus de versiunea Oracle8 sunt declanatorii INSTEAD OF. Spre deosebire de
declanatorii AFTER sau BEFORE, acestea se execut n locul instruciunii DML (INSERT,
UPDATE, DELETE) specificate. Deci cnd o instruciune de actualizare activeaz un declanator
INSTEAD OF, n locul instruciunii originale de actualizare este executat declanatorul respectiv.
n plus, spre deosebire de declanatorii AFTER sau BEFORE, declanatorii INSTEAD OF se
definesc pentru o vedere, nu pentru un tabel. Declanatorii INSTEAD OF se pot defini att pentru
vederi relaionale ct i pentru vederi obiect. n mod implicit, declanatoarele INSTEAD OF
acioneaz la nivel de rnd.
Dup cum s-a discutat n seciunea 6.2.2, operaiile DML efectuate asupra unor vederi pot crea
ambiguiti n ceea ce privete actualizarea tabelelor de baz ale vederilor. n aceast categorie intr
unele vederi bazate pe mai multe tabele, ct i vederi a cror interogare conine operatori cu
mulimi, funcii de grup, clauzele GROUP BY, CONNECT BY, START WITH i operatorul
DISTINCT. Vederile obiect prezint probleme suplimentare privind actualizarea, de exemplu
vederile obiect sunt utilizate frecvent pentru a realiza o relaie master/ detaliu, a cror actualizare
creeaz ambiguiti. Restricionarea operaiilor DML asupra tuturor acestor tipuri de vederi se
datoreaz tocmai acestor ambiguiti.
Declanatorii INSTEAD OF furnizeaz o modalitate transparent de actualizare a vederilor
relaionale sau obiect care nu pot fi actualizate direct prin operaii DML. Prin urmare, se pot scrie
comenzi obinuite INSERT, DELETE sau UPDATE asupra unei vederi, iar declanatoarele
INSTEAD OF acioneaz invizibil utilizatorului n locul acestor comenzi, rezolvnd problema
ambiguitii acestor comenzi.
S considerm urmtorul exemplu, in care vederea jucator_info este bazat pe tabelele
jucator, club i turneu:
CREATE TABLE club
(cod_club NUMBER(5)
PRIMARY KEY,
nume_club VARCHAR2(10),
localitate
VARCHAR2(10));
CREATE TABLE jucator
(cod
NUMBER(7)
nume
VARCHAR2(20),
cod_club NUMBER(5)

PRIMARY KEY,
REFERENCES club(cod_club));

CREATE VIEW jucator_info AS


SELECT j.cod, j.nume, c.cod_club, c.nume_club
FROM jucator j, club c
WHERE
j.cod_club = c.cod_club;
CREATE OR REPLACE TRIGGER jucator_info_insert
INSTEAD OF INSERT ON jucator_info
FOR EACH ROW
DECLARE
numar
NUMBER(1);
256

BEGIN
SELECT COUNT(*)
INTO numar
FROM DUAL
WHERE EXISTS (SELECT 'x' FROM club
WHERE club.cod_club = :new.cod_club);
IF numar = 0 THEN
INSERT INTO club(cod_club, nume_club)
VALUES (:new.cod_club, :new.nume_club);
ELSE
UPDATE club
SET nume_club = :new.nume_club
WHERE cod_club = :new.cod_club;
END IF;

END;

SELECT COUNT(*)
INTO numar
FROM dual
WHERE EXISTS (SELECT 'x' FROM jucator
WHERE jucator.cod = :new.cod);
IF numar = 0 THEN
INSERT INTO jucator(cod, nume, cod_club)
VALUES (:new.cod, :new.nume, :new.cod_club);
ELSE
UPDATE jucator
SET nume = :new.nume, jucator.cod_club = :new.cod_club
WHERE cod = :new.cod;
END IF;

Pentru fiecare rnd inserat n vederea jucator_info, declanatorul de mai sus testeaz mai nti
dac exist rndurile corespunztoare n tabelele de baz. n funcie de rezultatul acestui test sunt
inserate rnduri noi sau sunt actualizate cele existente.
9.16.4 Modificarea i tergerea unui declanator
Modificarea unui declanator const n recompilarea, activarea sau dezactivarea acestuia i se
realizeaz prin comanda ALTER TRIGGER. Comanda are sintaxa:
ALTER TRIGGER nume_declansator {ENABLE|DISABLE|COMPILE}
Activarea i dezactivarea declanatorilor
Un declanator se poate afla n dou stri: activat sau dezactivat. n momentul n care un
declanator a fost creat fr erori, el este n mod implicit activat, adic acesta se execut de fiecare
dat cnd se ndeplinesc simultan dou condiii: instruciunea declanatoare este executat i
restricia declanatorului este adevrat. Dac declanatorul este dezactivat atunci declanatorul nu
se execut chiar dac cele dou condiii au fost ndeplinite. n anumite mprejurri se poate dori ca
la un anumit moment declanatorul s fie dezactivat temporar. Acest lucru se poate realiza cu
ajutorul comenzii:
ALTER TRIGGER nume_declansator DISABLE

257

Pentru a activa un declanator se va folosi aceeai comand dar cu clauza ENABLE:


ALTER TRIGGER nume_declansator ENABLE
Deoarece un declanator este asociat unui tabel, la nivelul tabelului se pot activa sau dezactiva toi
declanatorii asociai acestuia folosind comenzile:
ALTER TABLE nume_tabel DISABLE ALL TRIGGERS
ALTER TABLE nume_tabel ENABLE ALL TRIGGERS
Recompilarea unui declanator
Pentru a evita recompilarea unui trigger invalid n momentul rulrii (care se face implicit), se poate
folosi comanda:
ALTER TRIGGER nume_declansator COMPILE;
Aceast comand recompileaz n mod explicit un trigger indiferent dac acesta este valid sau
invalid. Recompilarea nu modific definiia declanatorului existent.
tergerea unui declanator
n momentul n care un tabel este ters, n mod implicit sunt teri i declanatorii asociai acestuia.
Dac se dorete tergerea unui anumit declanator se folosete comanda:
DROP TRIGGER nume_declanator

258

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