Sunteți pe pagina 1din 189

Capitolul 2

Serverul de baze de date

Viaa (destul de lung, furtunoas i, nu n ultimul rnd,


misterioas) serverelor de baze de date" este marcat, am putea
spune, de dou evenimente cheie" n istoria tehnologiilor legate de
aplicaiile tranzacionale de prelucrare a datelor: pe de o parte,
afirmarea, confirmarea i contestarea arhitecturilor
client/server care au luat n considerare separarea
managementului datelor de aspectele de prelucrare concrete i, pe
de alt parte, proliferarea sistemelor de organizare a bazelor de
date r e l a i o n a l e .
Ca urmare, prin definiie", dar i istorie, SGBD-ul produs de
compania Oracle se integreaz n sistemele client/server i are n
primul rnd valene" relaionale (dar nu numai).

2.1. Ce este un server de baze de date?


Arhitectur general
Un s e r v e r n general reprezint o entitate care poate oferi servicii
n cadrul unei arhitecturi distribuite. Prin urmare, serverul de baze
de date reprezint o entitate care ofer servicii legate de stocarea i
gestiunea datelor. Aceste servicii rezult de fapt din clasarea
acestor servere n categoria SGBD-urilor.
Influena paradigmei client/server n domeniul aplicaiilor cu baze
de date a avut ca efect migrarea de la tehnologiile legate de
partajarea fiierelor la aplicaiile de reea. Astfel, n primul caz,
accesul la o baz de date nsemna n primul rnd transferarea pe
client att a executabilului SGBD-ului, ct i a copiilor indecilor
fiierelor de date. Rezultatul: trafic considerabil n reea, mecanisme
slabe i fragile" pentru tranzacii i suport pentru concuren
precar (mecanismele de blocaj asupra datelor realizndu-se exclusiv
la nivelul fiierelor fizice). e r v e t e l e d e b a z e d e d a t e au
nsemnat nlocuirea transferului de fiiere cu transfer de mesaje
coninnd fraze SQL (n cazul cererilor clienilor) i date (n cazul
rspunsurilor la cererile clienilor). Rezultatul: reducerea traficului
pe reea, gestiune centralizat i creterea siguranei datelor,
Oracle. Ghidul dezvoltrii aplicaiilor profesionale 21

Descrierea datelor accesibile utilizatorilor;


Suport pentru tranzacii;
Servicii de control pentru concuren;
Servicii de recuperare a bazeior de date n cazul cderilor
(avariilor);
Servicii de autorizare a accesului de date (securitatea);
Servicii de comunicare a datelor;
Servicii privind integritatea datelor;
Servicii care s asigure integritatea datelor;
Servicii utilitare pentru importul datelor, faciliti de
monitorizare i analiz statistic a activitii bazei de date,
de audit al bazei de date .a.

2.2. Probleme generale ale administrrii unei


baze de date
n legtur cu aspectele manageriale i tehnice privind datele
deinute de o organizaie se face de regul o distincie funcional
(i formal) n a d m i n i s t r a r e a d a t e l o r, a d m i n i s t r a r e a b a z e i
d e d a t e i a d m i n i s t r a r e a s i s t e m u l u i . Aspectele considerate
mai manageriale" (decizii pe termen mediu i lung) cad n sarcina
a d m i n i s t r a t o r u l u i d e d a t e care ar trebui s se ocupe, n primul
rnd, cu stabilirea politicilor i a standardelor generale privind
datele pentru ntreaga organizaie. Detaliile tehnice privind
proiectarea structurilor de date i implementarea lor n contextul
unui anumit SGBD sunt considerate un atribut definitoriu al
administratorului bazei de date. Exist organizaii (n general, de
mari dimensiuni) care, lund n considerare impactul implementrii
diferitelor tehnologii de infrastructur, printre care se gsesc i
SGBD-urile, au i u n a d m i n i s t r a t o r d e s i s t e m ce instaleaz i
configureaz SGBD-urile. Dei aceste trei funcii sunt frumos
structurate i definite n teorie, n practic administratorul bazei de
date este considerat omul bun la toate" n privina datelor,
personalizat sub forma unui ins adesea morocnos, grbit,
imperativ i stresat, aflat i n postura managerial" de a lua
decizii cu privire la achiziionarea software-ului privind datele i n
postura tehnic" (sau tehnocrat) de a rezolva problemele oricrui
utilizator de date sau dezvoltator de aplicaii cu aceste date 24 de
ore din 24, pltit totui civilizat pentru aceast munc (bineneles,
n rile civilizate).
Ca urmare a acestei unificri practice, atribuiile funciei unui
administrator de baze de date sunt separate n dou categorii
diferite: prima desemneaz rolul managerial, iar cealalt, rolul
tehnic:
22 Serverul de baze de date

Construirea i aplicarea politicilor, procedurilor i a


standardelor. Un DBA trebuie s defineasc, s comunice i
s aplice" proceduri care vor acoperi arii de aciune cum sunt:
modelarea i proiectarea bazei de date, documentarea bazei
de date, testarea, securitatea i integritatea acesteia, plus
crearea copiilor de siguran i restaurarea ei.
Asigurarea securitii i integritii bazei de date - adic
managementul accesului utilizatorilor (definirea utilizatorilor,
atribuirea parolelor, definirea privilegiilor de acces), definirea
view-urilor pentru protejarea i controlul domeniului de acces
la date al utilizatorilor autorizai.
t

Crearea copiilor de siguran i restaurarea bazei de date, plus


administrarea cderilor i pierderilor de date. n acest cadru
se impun: msuri privind backup-ul bazei de date, cu alte
cuvinte, crearea periodic a copiilor de siguran a datelor,
identificarea corect a acestora, stocarea corect i sigur a
lor, protecia fizic n ceea ce privete att software-ui, ct i
hardware-ul i msurile privind managementul tranzaciilor i
concurenei n BD.
Utilizarea datelor distribuite - pentru asigurarea integritii
tranzaciilor cu aceste date i pentru asigurarea unor
performane rezonabile privind timpii de interogare.

2) Rolul tehnic al administratorului unei baze de date


Selectarea, evaluarea i instalarea SGBD-ului, innd cont de
factori precum: modelul de date (relaional, obiectual),
scalabilitatea n ceea ce privete capacitatea de stocare,
suportul pentru dezvoltarea aplicaiilor, caracte risticile de
securitate i integritate a datelor, utilitile de efectuare a
copiilor de siguran (backup) i de recuperare a datelor
(recovery), controlul accesului concurent, performana,
instrumentele de administrare, suportul pentru distribuirea
datelor, portabilitatea etc.
Proiectarea : implementarea bazelor de date i a aplicaiilor.
Testarea i implementarea bazelor de date i a aplicaiilor.
Operarea cu SGBD-ul, utilitarele i aplicaiile acestuia. Aceste
operaii, efectuate apelnd la ut itile de baz ale SGBD-ului,
pot fi mprite n patru arii importante: suportul software al
SGBD-ului, monitorizarea performanelor i optimizarea bazei
de date, efectuarea activitilor de b a c k u p i r e c o v e r y,
monitorizarea i auditul securitii.
Oracle. Ghidul dezvoltrii aplicaiilor profesionale 23

2.3. Serverul de baze de date Oracle


Pn acum am privit lucrurile oarecum detaat de o tehnologie
proprietar anume i am irosit astfel vreo patru pagini n ncercarea
de a forma o imagine general sau, s zicem, principial asupra a
ceea ce reprezint un server de baze de date i personalul (sau
impersonalul) din preajma lui. Se cuvine ns s dm cezarului ce-i al
cezarului, i lui Oracle ce-i al lui Oracle. Prin urmare, n continuare
vom pune lupa" (nu microscopul electronic) asupra serverului
Oracle 8/8i/9i...

2.3.1. Structurile de organizare a elementelor


unei baze de date oferite de serverul Oracle
n cazul Oracle, structurile de memorie intern i procesele care
asigur funcionalitatea clasic a SGBD-ului iau forma concentrat"
a unei i n s t a n e O r a c l e . La nivelul sistemului de operare, aceast
structur se materializeaz sub forma unui serviciu distinct cu
numele O r a c l e S e r v i c e S I D j , unde SID reprezint numele
personalizat al instanei.
Din punct de vedere logic, serverul Oracle pune la dispoziia
utilizatorilor urmtoarele structuri de organizare logic a datelor:
Tabele, coloane, restricii
Tabelele constituie mecanismul de stocare a datelor specific unei
baze de date Oracle i conin un set fix de coloane ce descriu
atribute ale relaiilor (n cazul modelului relaional) sau ale
obiectelor (n cazul modelului orientat obiect) din schema logic.
Caracteristicile unei coloane se refer la: tipul de date i lungime
(plus precizia i scala n cazul n care tipul de date este NUMBER).
Tipurile de date de baz suportate n sistemul Oracle sunt:
pentru iruri de caractere: CHAR, de lungime fix, i VARCHAR2, de
lungime variabil;
pentru numere: NUMBER;
pentru dat calendaristic: DATE;
pentru date binare: RAW;
pentru obiecte de mari dimensiuni: LONG, LONG RAW, BLOB, CLOB,
BFILE.

O dat cu crearea unei tabele se pot specifica, printr-o serie de


clauze, diferite restricii, cum ar fi:
chei primare - PRIMARY KEY;
restricii pentru valorile nenule - NOT NULL;
valori implicite - DE FAULT;
restricii de unicitate, diferite de cheia primar - UNIQUE;
24
Oracle. Ghidul dezvoltrii aplicaiilor profesionale Serverul de baze de
25date

Restriciile
o coloan dintr-oimplementate
tabel relaional prin clauzele
care conine comenzii SQL CREATE
mai multe valori
pentru o singur linie. Un tablou variabil este asemntor c
TABLE mai sunt numite i r e s t r i c i i n e p r o c e d u r a l e , pentru cu se
o
refer la restricii formalizate prin expresii
tabel ncapsulat, ns este limitat sub aspectul numrului de linii foarte exacte (vezi
capitolul
pe care le4).poate
Implementarea
conine (pentru restriciilor de vezi
detalii, integritate
capitolul se poate face
8). Aceste
tipuri de structuri reprezint de fapt c o n s t r u c t o r i c o l e c t ode
i sub form de reguli active cunoscute de obicei sub numele ri
declanatoare (t r i g g e r e - vezi capitolul 10).
putnd implementa entiti aflate n relaie una-la-mai-multe ce se Aceste restricii sunt
considerate
regsesc, dep robicei,
o c e d u rprin
a l e . normalizare, n dou tabele relaionale
distincte.
Declanatoarele sunt proceduri ce se execut atunci cnd are loc
n ce privete implementarea schemei logice a bazei de date n
un eveniment specific bazei de date ce afecteaz nregistrrile unei
locaii distribuite, soluia n sistemele Oracle se bazeaz pe
anumite tabele. Ele pot fi folosite pentru a implementa reguli sau
p a r t i i i . Astfel, schema de fragmentare a unei baze de date
restricii refereniale mai complexe care nu pot fi formalizate prin
distribuite poate fi implementat n Oracle folosind partiiile.
clauzele comenzii CREATE TABLE. De asemenea, mai pot fi folosite i
Acestea porioneaz tabelele de date dup anumite criterii precizate
pentru a aplica anumite caracteristici de securitate sau anumite
i le poziioneaz n locaXiile stabilite prin schema de alocare.
opiuni de a u d i t a r e . In versiunile Oracle exist, de regul, dou
categorii
Clustere principale de declanatoare la nivel de tabel:
la nivel
Tabelele de fraz
care SQL - se declaneaz
sunt accesate frecvent mpreun, o singur n dat la nivel
general cele
de fraz
aflate SQL;relaie una-la-mai-multe, pot fi stocate fizic mpreun.
ntr-o
la a
Pentru nivel de linie
le stoca n- se declaneaz
acest mod estepentru creat fiecare linie dinspecial
o structur tabel
afectat de fraza SQL executat.
numit c l u s t e r (sau dac vrei ciorchine"), care va pstra n
aceleai locaii liniile legate ntre ele ale ambelor tabele. Scopul
Pentru
const implementarea
n minimizarea logiciide
fluxului aplicaiei,
I/E generat ntr-un sistem Oracle
de interogrile i
sunt disponibile
actualizrile datelor. urmtoarele
Coloanele prin structuri
care esteprocedurale: proce
fcut legtura duri
dintre
stoca
cele t e , ftabele
dou u n c i i formeaz
i p a c h e cheia
t e ( p acluster-ului.
c k a g e - u r i ) .Aceast cheie este
folosit la generarea index-ului clusterului, valorile acesteia fiind
Pr o c e d u r i l e s t o c a t e reprezint blocuri ce cuprind cod surs
stocate o singur dat pentru multiplele tabele ale cror linii sunt
(PL/SQL n cazul Oracle) pstrate n dicionarul bazei de date,
stocate mpreun n cluster.
apelabile din declanatoare sau de ctre eventualele aplicaii
implementate.
Tabele virtuale - view-uri
Ca structur o tabel virtual este n mare parte similar cu o
Fu n c i i l e se aseamn cu procedurile, ns, spre deosebire de
tabel obinuit: este format din linii i coloane. n schimb, dei se
acestea din urm, sunt obligate s returneze anumite valori
pot interoga sau actualiza date, un view nu stocheaz fizic date.
programelor care le apeleaz.
Acestea se gsesc n tabelele pe baza crora s-a creat respectivul
view.Pa c Conceptual,
h e t e l e suntun structuri
view poate maifi neles
complexe ca ofiindc
masc" suprapus
sunt folosite
peste tabelele de baz prin mecanismul unei fraze
pentru a organiza sau reuni procedurile i funciile n grupuri logice. SELECT. Ceea ce
se se stocheaz
Anumite elemente n baz estepachet
dintr-un definiia view-ului,
(variabile, adic interogarea
proceduri, pe
funcii) pot
care se bazeaz, formatul coloanelor, privilegiile
fi declarate publice sau private. Elementele publice sunt accesibile acordate. Spre
deosebire de tabele, view-urile
din afara package-ului, n timp nu pot fiprivate
ce cele indexate.sunt accesibile numai
procedurilor sau funciilor din interiorul package-ului.virtuale pot fi
Din punctul de vedere al proiectrii, tabelele
invocate ca mecanisme pentru maparea schemei externe pe schema
conceptual
Tipuri abstracte implementat
de date prin structura intern a bazei de date. n
acest context,
Tipurile view-urile
abstracte de pot
datefi sunt
folosite
tipu ir pentru
i d e daplicarea
a t e d e fi anumitor
nite de
politici de securitate la nivelul liniilor sau coloanelor din
u t i l i z a t o r i . Ele se bazeaz pe tipurile scalare definite mai sus i tabele.
pot fi folosite Ia definirea coloanelor din tabelele de date relaionale
sauIndecila definirea atributelor obiectelor stocate n t a b e l e l e d e
Un index reprezint o structur utilizat de server-ul bazei de
Oracle. Ghidul dezvoltrii aplicaiilor profesionale 27

ale crui valori


administrat sunt tablespace-uri
de aceste astfel construite nctdin
provine s fiierele
se poatde deduce
date
care fac parte din baza de date. Regula este ca un fiier de date sun
locaia fizic a fiecrei nregistrri: fiecare linie dintr-o tabel are
unic RowID.
furnizeze Intrrile
spaiu unui unui
de stocare index de tabel
singur sau cluster sunt definite
tablespace.
ntr-o baz de date Oracle utiliznd mecanismul B*-tree ce
garanteaz cel mai rapid acces (cea mai scurt cale) Ia o valoare
cheie. Fluxul de intrare-ieire (I/E) cerut pentru a gsi o valoare
cheie este minim, iar o dat gsit, este citit RowID-ul pereche cu
care se va avea acces direct la nregistrarea corespunztoare din
tabela de baz.
Indecii sunt creai automat, implicit, la crearea unei tabele prin
clauze de tip UNIQUE, PRIMARY KEY care implementeaz anumite
restricii de integritate. Crearea explicit a indecilor, n special din
raiuni de optimizare a anumitor interogri, se realizeaz printr-o
comand CREATE INDEX.

Alte structuri Oracle


n dicionarul unei baze de date Oracle se mai pot gsi i definiii
de s e c v e n e . Secvenele au fost create pentru a uura efortul de
programare, furniznd liste secveniale de valori unice. Cnd este
interogat pentru prima dat, o secven va returna o valoare
predefinit.
Figura 2.2. Fiecare interogare
Tablespace-uri succesiv
ntr-o asupra
baz de date secvenei va
Oracle
produce o valoare care crete (sau descrete) cu un anumit
Spaiul utilizat
increment. Secvenele de o potbazfi de datesau
ciclice Oracle este controlat
pot crete succesiv prin
pn
urmtoarele structuri logice:
cnd este atins o valoare maxim (sau minim) specificat.
Pentru
b l o c ual identifica
d e d a t ecomplet
- unitatea de stocare
un obiect dintr-oOracle ceadate
baz de mai trebuie
mic
(unitatea
specificat cel puinde baz).numeleDimensiunea acestuia reprezint
schemei (deintorul obiectului)un i
numele multiplu
acestuia al (ladimensiunii
care se adaug blocului sistemului
n bazele de date de distribuite
operare
numele (parametrul
mainii - DB_BLOCK_SIZE
al calculatorului dingazd
fiierul denumele
- i parametri);
serverului de
e x t e n t - u l , care const din mai multe
baze de date - al instanei). Pentru a simplifica acest proces, blocuri de date
pot fi
continue pe disc. Poate fi considerat unitatea
create s i n o n i m e care s puncteze direct ctre respectivele obiecte de alocare a
spaiului
din baza pentru
de date, segmentele
astfel de date;
c utilizatorii nu trebuie s cunoasc dect
s e gsinonimului.
numele m e n t u l , care const dintr-un
Sinonimele set fi
publice pot deutilizate
extenturide utilizate
ctre toi
pentru a stoca un anumit tip specific de date.
utilizatorii bazei de date, n timp ce cele private sunt vizibile doar de
ctre cei care le-au creat i prin urmare le dein.
Segmentele
Bazele de date pot fiOracle
socotiteau corespondentul
posibilitatea sfizic facalreferine
obiectelor la din
date
baza de date. Segmentele stocheaz date
care sunt stocate n afara bazei de date locale. n mod normal, (tabele, indeci etc.),
spaiul
pentrude stocareastfel
a realiza necesarde fiind preluat
referine din tablespace-urile
trebuie specificat numele bazei de
complet
date. Alocareastocat
al obiectului spaiului de stocare
la distan. pentru sinonim,
Printr-un un segment de date
se poate se
preciza
face
doarprin intermediul
numele obiectului extent-urilor, care sunt formate
i al deintorului, din seturi
neputndu-se indicade i
blocuri
locaia. dePentru
date adiacente
a specifica - continue
ntreagape disc.
cale de Atunci
acces cnd
pentrueste
un creat
obiect
un segment, acesta const din cel puin un
stocat ntr-o baz de date la distan, este necesar crearea unui extent. O dat cu
l e g t u r i d e b a z e d e d a t e . Cnd este creat un astfel de obiect,
care poate fi la fel ca im sinonim - public i privat - se precizeaz
contul, parola i numele de serviciu pentru baza de date aflat la
distan, conexiunea devenind astfel transparent.
28 Serverul de baze de date

Figura 2.3. Diagrama E-R pentru relaiile dintre structurile logice


i fizice de stocare

Figura 2.4. Formarea segmentelor din extent-uri i a extent-urilor

din blocuri de date

Tipuri de segmente de date


Am menionat c segmentele reprezint de fapt obiectele ce
ocup spaiul din baza de date. Din acest punct de vedere, se
Oracle. Ghidul dezvoltrii aplicaiilor profesionale 29

Ta b e l e l e neclusterizate i nepartiionate sunt cele mai


cunoscute structuri de stocare a datelor intr-o baz de date. Datele
dintr-o tabel sunt stocate fr o ordine precis determinat, astfel
c administratorul bazei de date nu are prea mult control asupra
locaiei fizice a liniilor din blocurile de date.
Pa r t i i i l e din t a b e l e . Din motive de scalabilitate i
disponibilitate, o tabel relaional poate fi stocat n mai multe
partiii, fiecare dintre ele putndu-se afla ntr-un alt tablespace i,
astfel, chiar ntr-o alt locaie. Dac o tabel este partiionat,
fiecare partiie este un segment separat cu parametri de stocare
specifici.
C l u s t e r - e . Un cluster (un ciorchine") conine una sau mai
multe tabele (grupate dup o coloan comun - key-column).
Tabelele dintr-un cluster aparin aceluiai segment i deci au
parametri de stocare comuni.
I n d e c i . Fiecare index are un segment de date separat, astfel c
dac pentru o tabel sunt definii trei indeci, atunci sunt necesare
trei segmente diferite. Pentru un index partiionat, fiecare partiie
corespunde unui segment separat.
S e g m e n t e l e r o l l b a c k . Segmentele rollback sunt utilizate de
tranzaciile care modific datele din baza de date. nainte de a face
o modificare asupra datelor, procesul server salveaz vechea
valoare n segmentul de rollback. Aceast imagine este utilizat
pentru:
anularea (Undo) modificrilor dac tranzacia este abandonat
(sau roll- back-uit, cum se mai spune adeseori);
mpiedicarea celorlalte tranzacii s vad" modificrile
necomise determinate de o fraz DML (asigurarea consistenei
la citire);
refacerea bazei de date ntr-o stare consistent n cazul
cderilor.
S e g m e n t e t e m p o r a r e . Pentru comenzi SQL cum sunt CREATE
INDEX, SELECT
DISTINCT i SELECT GROUP BY, serverul Oracle va trebui s efectueze
sortri suplimentare n memorie, sortri care sunt, de regul, mari
consumatoare de spaiu. Cnd apare o astfel de sortare (cum ar fi n
cazul n care este construit un index pe o tabel de dimensiuni mari)
sunt stocate pe disc rezultatele intermediare, n asemenea cazuri
sunt create segmente temporare.
Alte tipuri de segmente se refer la: s e g m e n t e LOB pentru
coloanele din tabele n care se stocheaz obiecte mari (LOB - Large
Binary Objects adic documente, imagini, secvene video),
s e g e m e n t e i n d e x LOB create pentru segmentele LOB propriu-zise,
t a b e l e n c a p s u l a t e (nested table) pentru coloanele definite ca
tabele n tabelele relaionale obinuite i s e g m e n t u l b o o t s t r a p
necesar la crearea bazei de date (rularea scriptului sql.bsq) i la
30 Serverul de baze de date

F i i e r e d e d a t e : stocheaz dicionarul bazei de date,


obiectele utilizatorilor, imaginile iniiale ale datelor schimbate
de tranzaciile curente (segmentele rollback). Exist cel puin
un astfel de fiier rezervat, bineneles, catalogului bazei de
date.
Fiierele de jurnalizare sau redo log: conin
nregistrri ale schimbrilor fcute n baza de date pentru a o
putea reconstrui n cazul unor cderi. Sunt necesare cel puin
dou astfel de fiiere.
Fiierele de control: conin informaiile necesare
meninerii i verificrii integritii bazei de date. Acestea, de
fapt, dau informaiile concrete asupra localizrii celorlalte
fiiere din baza de date i asupra strii lor. Este necesar cel
puin un astfel de fiier.
n momentul crerii bazei de date, automat se aloc i
formateaz spaiul pe disc, care ns nu conine nc datele
utilizatorilor. Cu alte cuvinte, serverul Oracle rezerv pe disc spaiu
pentru viitoarele segmente alocate n respectivele tablespace-uri.
Un tablespace poate fi format din unul sau mai multe fiiere de date.
Cum segmentele de date sunt alocate intr-un anumit tablespace,
atunci se poate presupune c schema unui utilizator se poate
ntinde n mai multe fiiere de date. Dimensiunea fiierelor de date
poate fi modificat ulterior, n funcie de necesitile bazei de date.
Fiierele de jurnalizare (redo log) sunt utilizate pentru
minimizarea pierderilor de date intr-o baz de date. Ele sunt
valorificate n momentul n care o instan cade (colapseaz"), iar
modificrile tranzaciilor declarate comise nu sunt scrise nc pe
disc. La repornirea instanei aceste fiiere sunt citite pentru
refacerea bazei de date n stare consistent, recupernd toate
tranzaciile comise i anulnd toate tranzaciile necomise.
Un fiier de jurnalizare face parte dintr-un g r u p r e d o l o g .
Membrii unui grup r e d o l o g sunt identici din punctul de vedere al
dimensiunii, al numrului secvenei log 1 i al informaiei stocate,
procesul LGWR (vezi paragraful urmtor) scriind simultan n toate
fiierele unui astfel de grup. Aceste grupuri sunt utilizate ntr-o
manier circular: dup ce ultimul grup este plin se trece la
suprascrierea primului.
Alte fiiere eseniale n funcionarea serverului Oracle, dar n
afara bazei de date, sunt:
fi i e r u l d e p a r a m e t r i : definete caracteristicile instanei
Oracle.
fi i e r u l d e p a r o l e : autentific utilizatorii privilegiai ai bazei

1. Log secjuence number - numrul alocat de ervetul Oracle la fiecare nou scriere n grupul redo log.
Oracle. Ghidul dezvoltrii aplicaiilor profesionale 31

de un serviciu numit l i s t e n e r 2 . Sarcina acestuia este s


interpreteze s t r i n g - u l de conectare (numele bazei de date furnizat
de utilizator) i s verifice dac exist un serviciu-instan
corespunztor. Dac instana indicat exist i este activ, se
creeaz cte un p r o c e s s e r v e r pentru fiecare conexiune (ntr-o
arhitectur dedicat) care va prelua sarcina administrrii acesteia i
va satisface cererile exprimate prin comenzi SQL ale utilizatorului.
n cazul unei arhitecturi MTS (Multi-Threaded- Server), un singur
proces server (s h a r e d s e r v e r p r o c e s s ) poate deservi mai multe
conexiuni simultane.
I n s t a n a Oracle reprezint elementul esenial care asigur
funcionalitatea specific SGBD-ului. La nivelul sistemului de
operare se materializeaz sub forma unui s e r v i c i u specific care
asigur practic funcionalitatea atribuit s e r v e r u l u i de baze de
date. Concret, aceasta este format dintr-o zon de memorie
intern - numit s y s t e m g l o b a l a r e a - i o serie de p r o c e s e
b a c k g r o u n d care funcioneaz ntr-o manier colaborativ.

System Global Area conine date i informaii de control pentru


serverul Oracle. SGA este format din urmtoarele structuri:
S h a r e d S Q L P o o l - stocheaz informaii cum ar fi, pe de o
parte, cele mai recente fraze SQL executate (L i b r a r y
C a c h e ), adic textul SQL, arborele de analiz i planul de
execuie, i, pe de alt parte, datele din dicionarul de date
cele mai recent utilizate (D a t a d i c t i o n a r y c a c h e ) , adic
definiii de tabele i coloane, nume de utilizatori, parole i
privilegii. Dimensiunea componentei Shared Pool din instan
este determinat de parametrul SHARED_POOL_SIZE din
fiierul de parametri.
D a t a b a s e B u ff e r C a c h e ( D B C a c h e ) , bufferele pentru
date - este zona n care sunt stocate blocurile de date
provenind din segmentele de date cel mai recent utilizate.
Mrimea fiecrui buffer din aceast zon este egal cu
mrimea unui bloc de date specificat prin parametrul
DB_BLOCK_SIZE, n timp ce numrul de buffere este precizat
prin parametrul DB_BLOCK_BUFFERS. Pentru a gzdui noi
blocuri de date n D B C a c h e , Oracle folosete un algoritm
prin care sunt trimise pe disc blocurile de date care nu au fost
accesate recent (LRU - Last Recent Use) pentru a face loc
celor noi. -
Re d o L o g B u ff e r, bufferele pentru nregistrrile r e d o l o g -
memoreaz modificrile fcute asupra datelor din BD de ctre

2. La nivelul sistemului de operare, numele acestuia este, de regul, Oracle{HOME}TNSListener.


2 Serverul de baze de date
Procesele de background execut funciile obinuite necesare
satisfacerii cererilor utilizatorilor concureni, asigurnd integritatea
datelor i meninnd performanele sistemului. Cele mai importante
sunt:
Database Writer (DBWR): responsabil de scrierea datelor
modificate din buffer cachc pe disc, n fiierele bazei de date.
Prin urmare, blocurile de date care conin nregistrrile
afectate de comenzile DML (trimise spre execuie de Ctre
utilizatori) sunt ncrcate mai nti n bufferele interne (buffer
cache), dac nu se gsesc deja acolo, dup care sunt
modificate. Procesul DBWR va scrie (la momentul oportun)
aceste buffere napoi pe disc n fiierele de date de unde au
fost citite, asigurnd astfel existena unui numr suficient de
buffere libere (care nu conin blocuri de date modificate sau
care pot fi suprascrise atunci cnd sunt cerute noi blocuri de
date de pe disc) n DB cache.
Log Writer (LGWR): are sarcina de a scrie n fiierele redo log
nregistrrile redo din bufferul redo log.
System Monitor (SMON): are, n primul rnd, funcia s verifice
consistena bazei de date i s iniieze restaurarea acesteia tn
momentul cnd este pornit instana i este deschis BD. De
asemenea, mai are rolul i de a cura" baza de date prin
eliminarea obiectelor tranzacionale care nu mai sunt
necesare.
Process Monitor (PMON): elibereaz resursele blocate cnd
cade" unul dintre procesele utilizator (pentru ca procesele de
pe server care le deservesc s nu blocheze inutil resurse). La
fel ca i SMON, PMON verific periodic dac este necesar s
intervin pentru meninerea unei funcionri corespunztoare
a instanei.
Procesul Checkpoint (CKPT): este responsabil de actualizarea
informaiilor despre starea bazei de date de fiecare dat cnd
schimbrile din DB cache sunt nregistrate definitiv n baza de
date.
Procesul ARCH. Procesul LGWR scrie In fiierele redo log active
(on line) ntr-o manier circular, astfel c n momentul n care
Oracle. Ghidul dezvoltrii aplicaiilor profesionale 33

Fiiere de date

1 . Procese utilizator
2, 3 - Procese Oracle
ARCH 3 2 - Procese Server
3 - Procese Background
PMON - Process monitor
SMON - System monitor
RECO - Recovery BBWR -
Database writer LGWR -
Log writer LCKn - Parallel
server lock CKPT -
Checkpoint ARCH - Archiver

Figura 2.5. Serverul Oracle: instana (SGA i


procesele background) i fiierele care
compun baza de date
Pr o c e s e l e s e r v e r : sunt dedicate administrrii conexiunilor la
baza de date i iniiaz fluxuri de I/E ntre instana bazei de
date i fiierele de date n scopul satisfacerii cererilor

2.3.5. Instalarea software-ului Oracle pentru serverul bazei de date

n paragraful anterior, am trecut n revist structura stufoas,


nerecomandat cardiacilor, a serverului Oracle (instana plus
fiierele ce formeaz baza de date), fr a furniza ns vreun indiciu
asupra modului cum vor putea fi obinute respectivele elemente. n
aceste condiii, este normal ca pe umerii unui nou-venit n lumea
serverelor de baze de date s apese un sentiment de mpovrare i
frustrare, dat fiind avalana de detalii tehnice (prea) deseori
criptice legate de intimitatea
SGBD-ului. Vestea bun este c nivelul asistentei n domeniul
instalrii soft-
/
ware-ului specific SGBD-ului i obinerii unei baze de date vioaie i
funcionabile este destul de bun. Vestea proast este c, i pentru
34 Serverul de baze de date

Prin urmare s purcedem la trecerea n revist a pailor implicai


de instalarea sofware-ului Oracle. Cteva cerine premergtoare
sunt ns neaprat necesare:
Facei rost de CD-urile cu Oracle (9i) - cel mai bine cu tot cu
licen (i fr banii necesari achiziionrii ei) - sau procurai-
v (doar n scopuri explorative" i pentru un utilizator solitar)
kit-urile disponibile la http://otn.oracle.com/, corespunztoare
sistemului de operare ndrgit" de calculatorul
dumneavoastr;
Mai este nevoie, bineneles, i de un calculator (proprietate
personal sau n leasing) cu ceva RAM consistent (un 128
mcar, un 256+ ar fi i mai bine), mcar cu Windows2000 (sau
un sistem de operare incompatibil cu Windows-ul, dar
compatibil cu kit-ul pe care l deinei);
Timp de ncercare i ceva rbdare (dac nu i tutun).
Lsnd tonul ugub la o parte, este bine s consultai mai
nainte detaliile privind cerinele minime din documentaia de
instalare: primul disc al kit-ului de instalare conine un document
We l c o m e . h t m l de unde mergnd pe link-ul D o c u m e n t a t i o n vei
putea avea acces la O r a c l e 9 i D a t a b a s e I n s t a l l a t i o n G u i d e .
Utilitarul de instalare al Oracle se lanseaz fie din ecranul de
ntmpinare implicit al a u t o r u n - u l u i primului disc al kit-ului, fie
direct prin executabilul s e t u p . e x e . Fereastra ochioas" a O r a c l e
U n i v e r a l I n s t a l l e r -ului pe care o vei obine astfel este creat
integral n Java, aa nct prima lansare^ s-ar putea s dureze puin
pn cnd va fi instalat n prealabil JRE 3-ul, dac nu este deja
instalat. Normal, primul lucru pe care l putem face este s prsim
ecranul de bun- -ntmpinare" i s mergem (N e x t ) n al doilea
ecran, dar care este primul pas obligatoriu al procesului de instalare:
1. Etapa de specificare a cilor - F i l e L o c a t i o n s . In aceast
etap ne ntmpin trei rubrici: s o u r c e p a t h , d e s t i n a t i o n
n a m e i d e s t i n a t i o n p a t h . Prima rubric face legtura cu
fiierul ce conine detaliile de instalare a tuturor
componentelor care formeaz software-ul Oracle - pentru o
prim instalare de pe discul din unitatea CD-ROM nu este
necesar s o modificm. A doua rubric va conine propunerea
de nume pentru r e e d i n a (HOME) produselor nou- -instalate
- aici se cuvin cteva precizri: dac este prima instalare i nu
suntei pretenioi, numele implicit poate fi fr probleme
pstrat, dac ns mai este deja instalat ceva software Oracle,
atunci ni se va sugera numele primului HOME n ordinea
instalrii ceea ce ns nu este ntotdeauna o soluie fericit
fiindc, n cazul unei versiuni diferite, suprapunerea instalrii

3. Java Runtime Engine.


Oracle. Ghidul dezvoltrii aplicaiilor profesionale 35

^Oracle Universal Installer: File Locations

File Locations
Source...
Enterthe full path of the tile representing the product(s) you want to install:
Pa
tti: F:\stage\products.jar
Browse.

Destination

Enter or select an Oracle Home narnaand Itsfyll path: Name: [o raHome92

Path: ' : D:\oracle\ora92

About Oracle Universal Installer.

Installed Products Previous

Figura 2.6. Specificarea cilor de instalare

2. Pasul urmtor ne pune n faa unei (prime) dileme: c e m o d d e


i n s t a l a r e s f o l o s i m . Prima distincie pe care o putem face
este c exist s e r v e r e de baze de date i c l i e n i pentru aceste
servere, iar a doua c exist i n s t r u m e n t e d e a d m i n i s t r a r e
s i m p l doar pentru baza de date i clienii acesteia, i exist u n
c a d r u d e a d m i n i s t r a r e c o m p l e x pentru software-ul de
ntreprindere n care se integreaz aceste servere de baze de
date i clienii lor. Deocamdat, ca utilizatori novici ce suntem,
ne intereseaz n primul rnd s obinem baza de date,
instrumentele minime de administrare i un client simplu (pe
aceeai main cu serverul BD) cu ajutorul cruia s ne legm la
serverul BD. Acest mod de abordare presupune selectarea primei
opiuni. Eventual, dup ce avem o baz de date funcional i
vom dori s ne conectm de la o alt main din reea, atunci
putem invoca i ultima opiune. Deocamdat rmnem fideli
36 Serverul de baze de date

Available Products

Select a product to install.


* Oracle9i Database 9.2.0.1.0
.
Installs an optional pre-configured starter database, product options, management tools, networking basic
client software for an Oracle database server.

r
Oracle9l Management and Integration 9.2.0.1.0
Installs the management server, management tools, Oracle Her net Directory, Oracle Integration S
services, USities and basic client software. .. J"

..- ^serterpnse management tods, networking services,kites, development toots an^preco.


software

Product Languages.

Installed Products. Previous

Figura 2.7. Specificarea instalrii unei baze de date locale


3. O dat cu apsarea butonului N e x t , un nou ecran (cu trei
opiuni) ne zgndrete rbdarea - I n s t a l l a t i o n Ty p e s
O r a c l e 9 i D a t a b a s e . Problema s-ar putea formula astfel:
ce fel de baz de date dorim s obinem: una superpotent
(pentru aplicaii tranzacionale solicitante, depozite de date
sau aplicaii Internet-intensive), una mai cuminte pentru
aplicaii departamentale, dar i ceva faciliti pentru
distribuire, replicare i chiar aplicaii Web, sau una i mai
cuminte, destinat doar testrii n condiii mai degrab
single-user a unor aplicaii totui serioase care exploreaz
caracteristicile obinuite ale unui server din clasa Oracle?
Deocamdat nu ne considerm zmei", i vom renuna
(prematur poate) la prima opiune, lucrm n echip i ne
mndrim totui cu o main-server acceptabil, deci vom
exclude varianta 3 (recomandabil dac, de exemplu, avem la
dispoziie un laptop de pe care dorim s portm ulterior
munca noastr ntr-ale bazelor de date pe un server
36 Serverul de baze de date

Oracle Universal Installer: Available Products jjjBSflIBil i

:-
Available Products . - --

' r'i
Select a product to
install. j services, utilities and

* Oracle9i Database 9.2.0.1.0


' m&Pi
Installs an optional pre-contigured starter database, product options, management tools,
basic client software for an Oracle database server.
r
Oracle9l Management and Integration 9.2.0.1.0
,
Installs the management server, management tools, Oracle trier net Directory, Oracle jnte
services, utilities and basic client software.

Oracle9i Client 9.2.0.1.0


ivelopment tools and preci

I' -rt.--r fc/ji*.
Installs enterprise management tools,

Product Languages.

Installed Products. Previous

Figura 2.7. Specificarea instalrii unei baze de date locale


3. O dat cu apsarea butonului N e x t , un nou ecran (cu trei
opiuni) ne zgndrete rbdarea - I n s t a l l a t i o n Ty p e s
O r a c l e 9 i D a t a b a s e . Problema s-ar putea formula astfel:
ce fel de baz de date dorim s obinem: una superpotent
(pentru aplicaii tranzacionale sobei fante, depozite de date
sau apbcaii Internet-intensive), una mai cuminte pentru
aplicaii departamentale, dar i ceva facibti pentru
distribuire, replicare i chiar aplicaii Web, sau una i mai
cuminte, destinat doar testrii n condiii mai degrab
single-user a unor apbcaii totui serioase care exploreaz
caracteristicile obinuite ale unui server din clasa Oracle?
Deocamdat nu ne considerm zmei", i vom renuna
(prematur poate) la prima opiune, lucrm n echip i ne
mndrim totui cu o main-server acceptabil, deci vom
exclude varianta 3 (recomandabil dac, de exemplu, avem la
dispoziie un laptop de pe care dorim s portm ulterior
munca noastr ntr-ale bazelor de date pe un server
Serverul de baze de date
38
Oracle. Ghidul dezvoltrii aplicaiilor profesionale 37

: Oracle Universal Installer


'Oracle Universal Installer: Installation Types mm ]*!

Database Configuration
Instaiiaton Types
0racle9i Database 9.2.0.1.0
Select a database suited to your needs.
*What
General Purpose
type of installation do you want?
r Installs a pre-configured database optimized (or genera! purpose usage
Enterprise Edition (2.86GB)

Provides data management
Transaction Processingfor high-end applications such as high volume on-line tre
environments, query-intensive data warehouse and demancing Internet applications meet
Installs a pre-configured database optimized (or transaction procssin9

r
V '
the avaSabilty and scalability requirements of mission-critical applications.

Data Warehouse
* Standard Edition (2.80GB) -
installs a pre-configured database'optimized for data warehousing
Targeted for workgroup or d(
n inter
r
Customized
s option take
with Orac

tailed Produc:
Installed Products. Previous

Figura 2.9. Selectarea unui model pentru baza de date


Figura 2.8. Tipurile de instalare
5. Trecnd superficial peste pasul O r a c l e S e r v i c e s f o r M T S ,
4. Urmtorul
ne grbim ecran
s maiD apsm"
a t a b a s e unC o nNfieg
xut ri...
a t i orbdare,
n ne permitebaza de s
mai
datelum o decizie:
trebuie s aibputem un nume obine- G ldin
o b amomentul
l D a t a b ainstalrii
s e N a m ei,
baza de date trebuie
iar instana ale creiidentificat
caracteristici i s
eafie determinate
prin rubrica S Ide D .unulNu
dintre modelele pre-fabricate incluse n kit-ul de instalare
ignorai aadar pasul D a t a b a s e I d e n t i fi c a t i o n , pentru c,
(opiunile
oricum, frGen e r a l Pu r p oacestor
completarea s e , Tr a n s a c t inici
rubrici, o n Pr
nsotcaelsl e
s irn g,
- ul,
D a t a Wa r enu
prevztor, l i o nmerge
s e ) sau maiputem
departe. optaCapentru crearea rapid
s rezolvm unei
baze de date n procesul creia s intervenim
dilema legat de nume, s-i spunem pur i simplu O r a c l e (nu eventual n
cunotin
este ns un de cauz.
principiu Dac dorim ns
universal s amnm
recomandabil, crearea
putei s
acesteia, putem merge pe varianta S o f t w a r e O n l y.
Oracle. Ghidul dezvoltrii aplicaiilor profesionale 39

Vs? Oracle Universal Installer: Database Identification

Database Identification

An 0racle9i database is uniquely identified by a Global Database Name, typically of the fornl Enter
the Global Database Name for this database.

Global Database Name: Oracle

A database is referenced by at least one Oracle9i instance which is uniquely Identified from ai
Instance on this computer by an Oracle System Identifier (SID). A suggested SID has beet
::
can accept or change to a valueyou prefer. - '

Oracle

Installed Products Previous

Figura 2.10. Specificarea numelui bazei de date


6. Pasul urmtor ne propune o c a l e p e n t r u fi i e r e l e b a z e i
d e d a t e , de regul n interiorul r e e d i n e i (HOME)
specificat n pasul F i l e L o c a t i o n s . Ca s nu avem ulterior
probleme la pornirea bazei de date, e bine s fim de acord cu
directorul implicit.
7. Pasul D a t a b a s e C h a r a c t e r S e t are pentru noi (romnii) o
anume importan legat de posibilitatea reprezentrii n
baza de date a caracterelor diacritice ( , z, , , ). Cei care
vor dori aplicaii (de exemplu pentru Web) care s redea
corect textul n romnete vor trebui s aprofundeze aceast
problem a suportului multinaional, dar, deocamdat, s nu
fim naionaliti" i s acceptm setul de caractere d e f a u l t .
8. In sfrit, ajungem n ecranul S u m m a r y care nu mai conine
butonul N e x t , ci I n s t a l l , prin urmare, dup tergiversri i
discuii (n contradictoriu), s lsm I n s t a l l e r - u l s-i fac
treaba i s introducem pe rnd, n ordine, atunci cnd ni se
va solicita, celelalte discuri ce formeaz kit-ul de instalare.
9. Dup un timp de ateptare mai mult sau mai puin ndelungat
(depinde de performanele mainii-server, dar oricum nu cade
4. Pn la versiunea 9i, bazele de date Oracle erau create implicit cu parolele
manager pentru SYSTEM i changejonjntall pentru SYS. Pentru evitarea
problemelor de securitate implicate de
40 Serverul de baze de date
Oracle. Ghidul dezvoltrii aplicaiilor profesionale 41

conturile cu privilegii de administrare a sistemului i sunt


Oracle Universal Installer: Configuration
creai implicit. Pe lngTools acetia, Oracle mai furnizeaz i
cteva conturi care conin scheme BD exemplu, destinate
iniierii nou-veniilor. n acest sens cea mai cunoscut schem
esteConfiguration
S C O T T, care Tools
solicit la conectare parola t i g e r.
The following tools will be automatically started for you:
Database creation complete. Check
'
These tools are optional.
Database ItInformation:
is recommended, although not required, that these tools be run successfully.
~Cf
Global Database Narm
Tool Name
System Identifier(SID): Status
Oracle
Server Parameters File Net Configuration Assistant
v succeeded
Oracle Database Configuration Assistant
- Change Passwords M accounts inv- F
in progress...
specify! :
[|. fiction Jiiew j j !*
Agent Configuration Assistant
Forsecurityfeasons, -ft foc? i pending.. 1 1 xj
1
1i!SiW* ?
assword: n
Re
SYS
iMfC *v i stop
J Details
Name tor
:M0 racle database Configuration As sista' j
Tree
Passv Description
1 Status 1 A
Confirm SYSTEM
Setting Password:
^ Services (Local) Password: Listener service to start automatically.
OradeMTSRecoveryService J
Listener configuration complete.
Note: All database accounts except SYS
OradeOraHome92Agent
Default local naming
ie Password configuration
Management bul ! complete.
OradeOraHome92ClientCache
the database accounts. From successful. The exit code is 0
Oracle Net Services configuration
runts you will use. Oracle Corf^3
OradeOraHome92HTTPServer
irds immediately after unlockln ver *
OradeOraHome92PagingSer
' * i . -
c %OradeOraHome925NMPPeerEncapsulator
i . - ' C
in stalled Products p Previous
^OradeOraHome92SNMPPeerMaster Agent

L ?OracleOraHome92TN5Listener Started . *
OradeSer viceOR ACLE i Started
<!
Figura 2.12. n final, configurarea ultimelor instrumente printre care i
acelea
p ' " ~ ............................................................................... "legate
' "1 de gestionarea conectrii clienilor din reea la
serverul bazei de date
Dac ntreaga
Figura procedur
2.11. Trebuie s-a ncheiat
specificate cu succes,
parolele pentru atunci putem
conturile
de administrare S Y S i
verifica mai nti din C o n t r o l Pa n e l Ad m i n i s t r a t i v e To o l s
S Y S T E M create implicit
S e r v i c e s (pentru MS Windows 2000) serviciile create pentru baza
10. Ultimul pas presupune iniializarea i configurarea ctorva
de date i mediul aferent ei pe server.
instrumente necesare pentru bunul mers i buna gospodrire
a bazei de date nou- -nscute". Cele mai importante se
refer la O r a c l e N e t C o n fi g u r a t i o n pentru c au n vedere
gestionarea cererilor eventualilor clieni (de pe alte
calculatoare din reea) ai serverului BD (sarcin delegat
serviciului L i s t e n e r ) i configurarea clientului local pentru a
ne putea conecta la baza de date direct de pe maina-server.
De regul, stratul care asigur conectarea i comunicarea cu
serverul BD se bazeaz pe aa-numite adaptoare" pentru
protocoalele de reea cele mai rspndite (TCP/IP, SPX/IPX
etc.), ns clientul local se bazeaz pe un protocol de inter-
comunicare ntre procese, aa nct nu vor fi solicitate

nemodificarea ulterioar a acestor parole, n 9i se solicit expres, din


momentul instalrii, specificarea noilor parole.
Oracle. Ghidul dezvoltrii aplicaiilor profesionale
42 Serverul de baze de43
date

Cele asupra crora ne vom opri apoi n configurare sunt


O r a c l e T N S L i s t e n e r i O r a c l e S e r v i c e O R AC L E . Primul este
gestionarul cererilor clienilor din reea pentru baza de date, iar cel
de-al doilea reprezint i n s t a n a bazei de date numite n cazul
nostru O R AC L E (vezi pasul 5). Din acest motiv, este recomandabil
(n special pentru a crua o parte din resurse) s fie oprite celelalte
servicii, iar modul acestora de pornire s fie M a n u a l , pentru a nu fi

Figura 2.15. Ecranul de ntmpinare SQL*PLUS. Conectarea la


baza de date
Pentru a verifica eventualele structuri de tabele din schema
curent putem interoga dicionarul bazei de date, apoi putem s
executm o fraz SELECT-SQL pentru o tabel specific.

' I Manual al
' Co p yrig ht ( c) 1 98 2, Or acle Co rp o rat io n. All rig ht s
2 08 2 , Configurarea
re s e rve
Figura 2.14. d modului de pornire
Co nne ct e d t o :serviciilor Windows 2000 m
Acestea fiind spuse, putem ncerca o conectare la baza de date
0 rac le 9 i Re le as e 8 - Pro d uct io n
9 .2 .0
jJSe folosind
.1 .r Re le as e
r ve instrumentul
- Pro d uct io n cel mai cunoscut (i, probabil, cel mai
9 .2 .0 .1 .0nepopular), vechiul S Q L P l u s din S t a r t Pr o g r a m s O r a c l e -
SQL > se le ct t ab le _name f ro n us e r_t ab le s ;
Home Application D e v e l o p m e n t . Ecranul de conectare
TABL E_N AM E
cuprinde trei rubrici: n u m e u t i l i z a t o r - u s e m a m e , p a r o l -
BON US p a s s w o r d i n u m e ( s e r v i c i u ) b a z d e d a t e - h o s t s t r i n g .
DEP T
EM P Vom specifica S C O T T pentru utilizator, t i g e rA pentru parol i vom
SAL GRADlsa E necompletat ultima rubric, ceea ce nseamn ** c dorim s ne
SQL > se le ct * f ro m .
d ep t ; V
DEP TN O D Nil H E L 0 C
10
A CCOUN TIN G N EW YORK fu
2 0 RESE ARCH DAL L AS
3 0 SAL ES CH IC AGO ,'f:
i> 0 BOSTON
OPER ATION S
rj
Figura 2.13. Serviciile Oracle
SQL > | <1 1
U
Figura 2.16. Utilitarul SQL Pas

2.3.6. Crearea unei baze de date Oracle


Am vzut n paragraful anterior cum se poate instala software-ul
Oracle intr-o variant care s includ i o baz de dat implicit
(donat" de fapt pe baza unei
44 Serverul de baze de date
Oracle. Ghidul dezvoltrii aplicaiilor profesionale 45

structuri prefrabricate de pe kit-ul de instalare). S-ar putea s


database Configuration Assistant, Step 1 of 8 : Operations
existe ns civa crcotai" care au avut rbdarea s citeasc
paragrafele 2.3.2 i 2.3.3 (despre structurile logice i fizice) i care
ie operation you want to perform
nu privesc cu ochi buni" modul n care se obine noua baz de date
sau, mai exact, modul n care aceasta acapareaz n mare secret i
fr avertizare resursele, probabil destul de limitate, ale
:onfigure database

calculatorului de test. Acetia vor dori un control mult mai


amnunit asupra instanei i celorlalte structuri fizice ale bazei de
lanage Templati
date. Din acest motiv vor amna momentul crerii bazei de date,
selectnd n pasul D a t a b a s e C o n fi g u r a t i o n din procesul de
instalare opiunea S o f t w a r e O n l y.

Folosirea mediului de asisten pentru crearea unei


baze de date personalizate
Asistentul pentru configurarea (mai) amnunit a bazei de date

Next

Figura 2.18. Operaiile care se pot realiza cu asistentul de configurare al bazei


de date
Mergnd pe varianta crerii asistate a bazei de date, n primul
pas (important, fiindc este al doilea n ordinea real) - D a t a b a s e
Te m p l a t e s - vor fi propuse mai multe modele (t e m p l a t e s )
predefinite, fiecare avnd anumite caracteristici preconfigurate,
astfel:
D a t a Wa r e h o u s e - suport pentru interogri complexe
efectuate asupra unor mari cantiti de date ce necesit timp
de rspuns rezonabil i acuratee maxim. Aceste interogri
pot varia ca rezultat, de la cteva nregistrri, dar cu mari
disponibiliti de agregare, pn la mii de nregistrri
rezultate din criterii relativ simple, dar provenind dintr-o
multitudine de tabele joneionate;
G e n e r a l Pu r p o s e - suport pentru o varietate de sarcini, de
Figura 2.17. Ecranul de ntmpinare
la tranzacii simple pn al DBla Configuration Assistant
interogri complexe. Acest model
este recomandabil n special n
Acest utilitar poate fi folosit pentru crearea unei noi baze de
miiig du tettw
date, dar i la (re)configurarea opiunilor unei baze de date prg-pmducpg
unor cu
existente, tergerea unei baze de date sau gestionarea abloanelor
(modelelor) predefinite.
funcionaliti complexe i variate;
Tr a n s a c t i o n p r o c e s s i n g (sau OLTP) - suport n special
pentru tranzacii obinuite, adic actualizarea (inserare,
tergere, modificare) unui numr rezonabil de tabele (eventual
i consultarea prealabil a acestora) n aceeai unitate
operaional, ns n medii concureniale - solicitri simultane
deseori asupra acelorai date (acelorai nregistrri sau altor
nregistrri, dar din aceleai tabele) provenind de la un numr
46 Serverul de baze de date
Oracle. Ghidul dezvoltrii aplicaiilor profesionale 47

fDatabase Configuration Assistant, Step 2 of 8: Database Templates

a template
Select Specify thefrom the following
following databaselist to create a database:
Information.

Select Template
An 0racle9l Name_______
database Is uniquely Identified by a Global Database Name, typically of the form "name.domaln*.

Data Warehouse
Global Database Name: JoracTej
Q j General Purpose
A database is referenced
C Transaction Processing by at least one Oracle9i instance which is uniquely Identified from any other instance
on this computer by an Oracle System identifier (SID).
------------------------------------------------
------------------------------------------------
New Database

Show Details... \

Cancel

Figura
Figura 2.20.
2.19. Pasul necesar
Modelele pentru specificarea
de configurare identitii bazei de date
predefinite
Alegem G e n e r a l Pu r p o s e i mergem mai departe (N e x t ). La
fel ca i n cazul instalrii implicite, n pasul urmtor - D a t a b a s e
Select the mode in which you rant your database;to operate by default
I d e n t i fi c a t i o n - se vor solicita numele global al bazei de date i
* Dedicated Server Mode
numele instanei care o client
For each vaconnection
deservi. Numele
the database implicit
will allocate a resource dedicated al acestei
to serving only that ,
instane va fi sugerat pornind de la numele bazei de date.
client. Use.this mode when the number oftotal client connections Is expected to be small or
when Clients will be making persistent, long-running requests to the database.
n pasul urmtor ni se i solicit . imperativ
. ..v ~ modul n care dorii s
c Shared Server Mode
opereze implicit baza deconnections
; Severaiclient date" share a - D a t a bpool
database-allocated a soferesources.
C oUsenn thisemode
c t iwhen
on
more than a small number of users need toconnectto the database simultaneously while
O p i o n s . Dei formularea este destul de neclar, totui, pentru
efficiently utilizing system resources. The Oracle shared server feature will be enabled.
fiecare opiune exist o scurt descriere. Pe scurt, principiul
di She red Con ne stidn s pe ramefers.
colaborrii ntre clieni i serverul Oracle se bazeaz la nivelul
acestuia din urm pe un proces separat ce comunic direct cu
procesul client i intermediaz cererile acestuia asupra bazei de
date. Aceste procese intermediare pot fi alocate separat, cte unul
pentru fiecare conexiune a fiecrui client (modul de dedicat), caz n
care comunicarea se face direct, fr cozi de ateptri i fr riscul
unor timpi mori" la nivelul proceselor client, sau, pentru a
drmui" mai bine resursele serverului (n ceea ce privete RAM-ul
necesar), un singur proces server poate deservi simultan mai muli
clieni, caz n care, atunci cnd apar mai multe cereri simultan,
Elnish

Figura 2.21. Detalii legate de modul de deservire a cererilor clienilor bazei de


date
48 Serverul de baze de date
Oracle. Ghidul dezvoltrii aplicaiilor profesionale 49
n cunotin (mai mare sau mai mic) de cauz s alegem modul
Hg *1 M
implicit (dedicat) i s mergem mai departe n pasul cel mai complex
al acestui proces Initialization Pa m m e t e r s . Ecranul
corespunztor acestei etape este mprit n mai multe cadre:
M e m o r y. Parametrii corespunztori acestui cadru se refer la
modul n care este gestionat memoria intern dedicat
instanei care deservete baza de date. Semnificaia acestor
parametri se leag n mare parte de descrierea elementelor
Parametri model OLTP
din paragraful 2.3.2, i anume:
S h a r e d P o o l - cache-ul destinat datelor consultate din
dicionarul bazei de date i informaiilor despre frazele SQL
rulate. Pentru o baz de date tranzacional se recomand
o valoare n jur a 30M, care, eventual, ar putea fi mrit
dac exist dese interogri complexe i variate (aplicaii
gen DSS);
- B u ff e r C a c h e - bufferele Oracle (nu direct ale sistemului
de operare) dedicate replicrii n memoria intern a
blocurilor de date care conin nregistrrile solicitate de
interogri sau tranzacii. In general, cu ct baza de date
este mai tranzacionat" (modelul OLTP), cu att pentru
aceast zon este rezervat mai mult spaiu. Se recomand
o valoare mai mare (s zicem n jur de 50M) pentru a crete
performanele bazelor de date puternic tranzacionate,
valoarea obinuit pentru bazele de date normale" fiind n
jur de 30M;
- Java P o o l - destinat analizei/interpretrii/execuiei
codului Java stocat n baza de date sub forma procedurilor
stocate (opiune disponibil de la versiunile 81). Exist i
un prag minim pentru dimensiunea acestei zone (pentru un
calculator cu 256MB-RAM, automat se recomand 20M);
- L a r g e P o o l - reprezint o zon de memorie relativ
opional, util pentru operaiile frecvente de creare a
copiilor de siguran i de restaurare a bazei de date.
Pentru baze de date n producie se recomand o
dimensiune n jur de 10M, altminteri, doar pentru test, se
poate minimiza aceast valoare;
- P G A - reprezint volumul de memorie (maxim) alocat
pentru un proces server care colaboreaz cu celelalte
procese din instan pentru a deservi cererile proceselor-
client.
Shared Pool:
Stabilirea parametrilor anteriori se poate face:
32 MBytes Shared Pod: y 32 M Bytes - Shared Pool: 32 MBytes

Buffer Cache 63 M Bytes. Buffer Cai on: : 48 MBytes Buffer Cache; . . 32 M Bytes .
-, j-.T
Java Pool M Bytes Java Pool; 20 MBytes Java Pool; . MBytes
20 ~n 20

Large Poof M Bytes Large Pool:' MByte 3 Large Pool: j M Bytes V


11 11 11
PGA; 21 M Bytes PGA;
. 26
MBytes PGA 42 MBytes
s 1 ii

Oracle Process Size: 40 MBytes Oracle Process Size: 40 M Bytes Oracle Process Size: 40 MBytes
:

Total Memoryfbr Oracle: 177 M Bytes - Total Memory for Oracle; 177 MBytes Total Memory for Oracle: 177 MBytes
- :
-T ^ - yv -yy yy- >\ ''sy.-'* ^ pvip
4
*( ' .. ;' ,4. fgi,
i Close | Close i-v -f . : Close j
{32 *3
.gj

J3 2 UH

|20
m

F l3
jjav

P'"--

1
,t..

aiM

Parametri model Multipurpose Parametri DataWarehousing

Figura 2.22. Valorile parametrilor determinani pentru gestiunea


memoriei interne
specifice pentru diverse modele
- C u s t o m , variant n care trebuie precizai toi parametrii de
mai sus. Pentru a simi c facem ceva totui important i
responsabil, vom merge pe aceast variant i vom
specifica n ordine valori (n MB): 32, 32, 20,4, 16, la care
se vor aduga nc 40MB destinai proceselor background
ale instanei.
Database Configuration Assistant, Step 5 of 7: Initialization Parameters

Memory
S&8BS
Typical

Percentage of physical memory (255 MB) for Oracle: fTix

Database Type: Data Warehousing


Showdistribution ci f.tmnoiy .

Custom Shared

Pool

Buffer Cache:

Total Memory for Oracle: 140 MBytes


. ......
Total memory includes 40MB of Oracle Process Size and the defaults for the empty parameters ,
If any.'

All Initialization Parameters File L.o.ctlo'n.Variafcles:..'f


50 Serverul de baze de date

D B S i z i n g - sun cam impropriu, pentru c se refer de fapt


la zona de memorie intern care va fi dedicat proceselor de
sortare datorate executrii unei fraze SELECT ce implic
principii de ordonare (ORDER BY, GROUP BY, operatori de
agregare) sau crerii unor indeci specifici.
F i l e L o c a t i o n s - se refer, n primul rnd, la localizarea
fizic a fiierului de parametri al instanei relativ
O R AC L E _ B A S E , adic o locaie cum ar fi D : \ O r a c l e (nu
D : \ O r a c l e \ O r a 9 2 , care nseamn O R AC L E _ H O M E ) , i a
fiierului de parametri dinamici S P F I L E ;
Archive - modul arhivare (bifarea checkbox-ului
A r c h i v e L o g M o d e ) , care reprezint cel mai obinuit mod de
a realiza o copie de siguran a datelor tranzacionale prin
arhivarea fiierelor de jurnalizare (log). n cazul unei cderi,
starea bazei de date se poate reface dac mai exist o copie a
fiierelor de date i arhivele fiierelor jurnalizate de la
momentul efecturii respectivei copii de siguran. Pentru
bazele de test nu este necesar activarea modului de arhivare
a jurnalelor, ns pentru o baz de date n producie trebuie
realizat o politic de backup/recovery ce va include i
arhivarea automat a jurnalelor tranzaciilor din fiierele log.

Pasul urmtor are n vedere s t r u c t u r i l e fi z i c e d e s t o c a r e ,


mai exact fiierele de control, de jurnalizare i de date - D a t a b a s e
S t o r a g e . Ecranul este organizat n dou zone distincte: zona din
stnga prezint structurile fizice mprite pe categorii legate
printr-o arborescen, iar n dreapta sunt prezentate detaliile
fiecrei categorii.

Prima ramur C o n t r o l fi l e prezint detalii despre fiierele de


control, adic localizarea i multiplicarea lor (cadrul G e n e r a l ) ,
precum i modul de repartizare a spaiului n funcie de intrrile
care vor reflecta structura bazei de date - numrul de fiiere de
date, de grupuri redo-log (jurnalizare), de membri per fiecare grup
(cadrul O p t i o n s ) .

A doua ramur D a t a fi l e s prezint detaliile legate de localizarea


fiierelor de date care vor forma tablespace-urile bazei de date. De
exemplu, S Y S T E M 0 1 . D B F corespunde tablespace-ului S Y S T E M ,
singurulFigura
care2.23. Specificarea
trebuie creatmodului
n modn care va fi repartizat
obligatoriu memoria
fiindc va gzdui
destinat instanei
dicionarul sau catalogul bazei de date.
bazei de date
C h a r a c t e r S e t s - setul de caractere are importan dup
cum spuneam i n paragraful anterior pentru naturalizarea"
bazei de date Oracle la caracterele naionale specifice.
.. File Directory
File Name
1 CWMLITE01 .DBF {ORACLE_BASE}toradata\{DB_NAME}t
2 DRSYS01.DBF {ORACLE_BASE}\oradata\{DB_NAME)\ iffi
p
EXAMPLE01 .DBF {ORACLE_BASE>toradatat{DB_NAME}t
3
INDX01 DBF Oracle. Ghidul
{ORACLE dezvoltrii
BASE}toradata\{D8 NAME}\ aplicaiilor profesionale 51
4
(PI
5 ODM01 DBF {ORACLE_BASE}\oradata\{DB_NAME}\
6 SYSTEM01.DBF {ORACLE_BASE}toradatat{DB_NAME}\ iii
8 ! Database Confi guration Assistant. Step 6 of 7 : Database Storage
7 TOOLS01.DBF {0 RACLE_B AS E}\o ra d ata\{ D B_NAM E }l
UNDOTBS01.DBF -IJ Storage
{ORACLE BASE}\oradatat{DB NAME}! iSl
8
USERS01 DBF -fj Controlle
{ORACLE_BASE}\oradata\{DB_NAME}\ ___________m
9
i- XDB01.DBF --jSS5
{ORACLE_BASE}toradatat{DB_NAMEB
:
kK-JRedo Log Groups
TEMP01 .DBF {0 RAC LE_BAS E }\o r a d ata\{ D B_NAM E }\ V
. U
52 Serverul de baze de date

Cile specificate pentru fiecare dintre fiierele discutate anterior


sunt ncriptate folosind anumite variabile, ale cror valori reale le
putem afla apsnd butonul F i l e L o c a t i o n Va r i a b l e s . . .

Use variables to specif/ tile locations for


iniializai other Iile used by database. . '
.1 , - --

For example, initialization file may be


specified as (ORACLE..BASE)tadmin\
(DB_NAMEitinit{SID}.oi
Variable Value
ORACLE_BAfcE Dtoracle
ORACLE_HOME Diioradeb

DBJNAME -7

L?:Zr.
wm Oracle .. v - : ,. x-
r-;~r? jc
-
... ' '-S'vii

r
'i:* - .

' Add] .Remove


WV; File Location Variables... t

Cancel j i gack Next W) Finish )


ri OK Cancel
;; : .

Figura 2.24. Numele i plasarea fiierelor de dale care vor


Figura 2.26. Valorile variabilelor care determin
formacile
bazafizice
dede
date
localizare
Database Confi guration Assistant. Step 6 of ?; Database Storage
a fiierelor bazei de date
<cKlj Storage -i)
CaControlle
urmare, putemGeneraldeduce
HmHHP % structura de directoare care va rezulta
fp Group #: J
n urma acestui proces (vezi paragraful urmtor).
-LJDatales >
File Size: 102400
Ultimul Logpas C r e a t i o t i O p t i o n s prezint dou opiuni n
CJRedo

legtur
Groups
cu finalizarea acestui proces: File Directory
crearea (fizic) a bazei de
Redo Log
date i/sau salvarea acestei configuraii sub forma unui model
Members: File
(template) care ar putea REDO01.LOG
Name
fi refolosit ulterior pentru specificarea
{0 RAC LE_0AS E }to ra d aiat( D B_N AM E {t
parametrilor unei alte baze de date.

n fine, butonul F i n i s h marcheaz sfritul procesului de


configurare i nceperea procesului efectiv de stocare care se va
ncheia cu crearea i pornirea serviciilor Oracle descrise n
paragraful anterior i cu crearea structurii de directoare descrise n
paragraful urmtor.
De asemenea, spre deosebire de versiunile anterioare, n
Oracle9i procesul de creare a bazei de date mai are un efect:
nregistrarea (n fiierul de configurare
rl l i s t e n e r.Filo
o rLocation
a , Variables
seciunea
Add | Remove - IV^
S I D _ L I S T _ L I S T E N E R ) de ctre procesul L i s t e n e r a noii baze de
date, cererile de conectare ctre instana acesteia fiind deservite
Finish
automat, plus nregistrarea unui serviciu-descriptor pentru noua
Figura 2.25. Repartizarea i plasarea n structura fizic a fiierelor de jurnalizare
Oracle. Ghidul dezvoltrii aplicaiilor profesionale 53

Select the following database creation

options: y Create Database r S3ve as

a Database Template

Name:

Description:

Figura 2.27. Finalizarea procesului de configurare: creare unei noi baze de


date i/sau a unui nou model (template)

Structura de directoare
Dup cum se poate concluziona de altfel i din figura care
prezint variabilele O R AC L E _ B A S E , O R AC L E _ H O M E , D B _ N A M E
i S I D , structura de directoare implicat se prezint astfel (pentru
MS Windows 2000):
rdcina o reprezint directorul O r a c l e , printe pentru toate
fiierele suport sau ale bazelor de date stocate pe server.
Acest director prezint trei subramuri (subdirectoare):
- directorul O r a 9 2 (pentru Oracle9i2) destinat fiierelor
suport ale software-ului Oracle (serverul BD i utilitare)
plus fiierele de configurare ale clientului local etc.;
- directorul a d m i n n care va fi creat cte un subdirector
specific pentru fiecare baz de date local. Un astfel de
subdirector destinat unei BD locale prezint, la rndul lui,
alte cinci subdirectoare b d u m p , c d u m p , c r e a t e , p fi l e ,
u d u m p . Dintre acestea, fiierul de parametri I n i t . o r a ,
spre exemplu, este plasat n p fi l e - ,
- directorul o r a d a t a care va conine Ia rndul su cte un
director dedicat fiecrei BD locale. ntr-un astfel de
FoU*rs ' 't
i -Q ele

54
, i i -Cj admm
Serverul de baze de date
iii; S -D Orede #I

!
1 1 ! j ; ~D bdump fI
* * 1 j-Qedump * vj
! 11
! Cl create

; ; ; ! -c^ flew Ffiyortti


, , 1 !j si- Back
Cj udump
1 i ! |Q 92 .* i.

j Ajjdre |D D:\orade\oradata\Orade
! l i D data <1
DEEE3 _jd

{.22CB !gMyConw*w
: 4.22 GB)
r

' V jJ- .. ....................V .


:ORACLE .
56 Serverul de baze de date
Normal
Oracle. Ghidul dezvoltrii
' 1 yr | aplicaiilor profesionale 55

PrimaOracle
opiune din
enterprise Manager fereastra
Console, Standalone de mai sus ne permite introducerea
parametrilor de configurare
pie Ma^igatoi Obistl.'Tools' ConfigurationaHelpunui nou descriptor de serviciu, dac
acesta nu exist INeKo'i. deja. Dac acesta este CONTROLO deja definit (de exemplu,
I lji| REDO03.LOG
- .CTL
Oracle %
Enterprise ISYSTEM01 DBF
Manager
prin rularea anterioar
Databas
a utilitarului Net Configuration
CONTR0t02.CTl TEMPO 1. DBF
______
Assistant -
vezi paragraful Oracle
2.5), poate fi selectat dinCONTROl03.Cn
es -S
% lista din partea inferioar
kajTOOtSOl.DBF I
Oracle Enterprise Manager is a managementUNDOTBSOl .DBF
care devine disponibil prin view Its
selectarea
description.
Administer
use celei
an Item to which you canCWMLITE01.0eF
Selectfrgm.gBfl.rk to:
the completeDRSYS01.0=
Oracle environment,
de-a doua opiuni
SuSERSOt.DBF on* M*,,
MXDB01.D6F
Add...from your local tnsnames.ora See also: file...
including databases, IASWservers, applications,
.
EXAMPIEOI DBF
!)INDX01.0BF
and services
Mv Documents Hv

Dup aducerea n OEM a Diagnose,
Network bazelor de
Placesmodify, and tune date
H multiple
dorite, ncercarea de
. databases.
OOMOI OBF
RED001.LOG S
tfrOywiy
deschidere a unui nod automat Schedule vatasksduce lasystems
on multiple deschiderea
at varying dialogului de
Monitor database conditions throughout the

Figura 2.28. Structura local de fiiere


Administer specifice
multiple network bazei de date
nodes and services
O RACL E EwTEi>RtSE M ANAGER
Share tasks with other administrators.
Group related services together to facilitate
2.3.7. Consola Oracle

Enterprise
administration tasks. Manager. Configurare
Launch integrated Oracle and third-party tools. y0 |eam more about the Cons.
i
utilitate clickthe Quick Tour button
Username: j|
Consola Oracle Enterprise Manager ft',': -(OEM) .
reprezint
--
instrumentul de
- Password:
administrare al bazelor de date furnizat direct de Oracle. Acesta
---------------- i;--------- Quick Tour
funcioneaz fie independent (standalone), ----- fie n colaborare cu un
Setvice: ORACLE
server de administrare dedicat (Oracle ---------------- Management Server), care
Figura 2.30.ConnectOrganizarea
gs: Normal suprafeei de lucru a OEM
poate asigura automatizarea sarcinilor de administrare pentru o reea
n caz contrar, se poatefffxcrea un nod
r save As (de Local fapt,Preferred descriptor de serviciu)
concertat de baze de date (n special, pentru BD distribuite).
Credentials
din N a v i g a t o r - ^ Ad d D a t a b a s e Cancel To Tr , ee.
Deocamdat, pentru sarcinile de rutin, dar eseniale n
administrarea bazei de date pe care am obinut-o, vom fi (foarte)
mulumii de varianta simpl. Add a database manuali

Hostname: .. jOra
V k V. "s'" y. .. .
Port Number. 'jl521
r' !'. ' A l L l b :
SID: Oracle

lame: {oracle_Oraj

r Add selected latabases from your local tnsnames.ora file


located in D: oracle\ora92\NETWORMADMIN

Figura 2.29. Ecranul de ntmpinare al OEM


Fereastra principal OEM cuprinde o suprafa de lucm
structurat n dou zone: n stnga se gsete o arborescen,
nodul D a t a b a s e s cuprinznd cte o ramur pentru fiecare baz de
date administrat. Aceste noduri reprezint sau se bazeaz de fapt
Figura 2.31. Fereastra pentru specificarea descriptorilor-servicii pentru bazele
pe serviciile-descriptor de pe clientul local. innd cont de
de date ce se doresc a fi administrate din consola OEM
precizrile fcute n finalul paragrafului 2.3.6.1, ar trebui s existe
implicit o astfel de ramur pentru baza de date creat local. *
Figura 2.32. Fereastra de conectare

De obicei, conectarea se face printr-un cont administrator, de


regul SYSTEM, ns, dac se dorete i efectuarea unor operaii mai
deosebite, cum ar fi nchiderea/deschiderea bazei de date, atunci este
necesar conectarea cu un cont cu privilegii S Y S D B A . S lum n
considerare acest ultim caz: dac vom dori s ne conectm la baza de
date nou-creat (Oracle), vom face click pe nodul de intersecie al
acesteia (sau click-drepta i C o n n e c t ) , dup care precizm ca
U s e m a m e SYS; parola va fi cea specificat la crearea bazei de date,
iar n rubrica C o n n e c t a s vom selecta S Y S D B A .
Nodul corespunztor bazei de date selectate se va deschide, fiecare
ramur reprezentnd o sarcin distinct de administrare, dintre care
cele mai reprezentative:
Din I n s t a n c e putem porni/opri baza de date (dac suntem
conectai ca SYSDBA) sau putem s-i schimbm parametrii de
Oracle. Ghidul dezvoltrii aplicaiilor profesionale 57

ghtj Network
general. ferr
^CJDatabases
^ORACLE - sys AS SYSDBA Instance Stale

^instance -r Shutdown

MD Sessions
Locks tfj/t < Open Snow
GResource Consumer d Ail States
yp-C3Resource Plans | '-
Database and Instance Information........................................... . . ................. - -
iQResource Plan Schee]
Host Name: ORA
-^Schema DB Name: ORACLE
Security f >111 Storage DB Version: Orade9i Enterprise Edition Release 9.2.0.1.0 - Production
Distributed t/3 Warehouse ig With the Spatial, OLAP, .
Workspace ^XML Database Q and Oracle Data Mining options
Instance Name: oracle
ORACLE_ORA
Instance Start Time: 11-Feb-2003 11:29:13 AM
Restricted Mode: (no :
Archive Log Mode: NOARCHIVELOG

Read Only Mode: i;

started With spflle: %ORACLE_HOME%tDATABASEtSPFILE%ORACL_SID%.ORA


" " ' ' . ' \.............. '
All Initialization Parameters... j

Figura 2.33. Administrarea instanei bazei de date


Din nodul S c h e m a avem posibilitatea verificrii tuturor
obiectelor din baza de date grupate sub schemele fiecrui
utilizator;

Figura 2.34. Administrarea schemelor de obiecte din OEM


Oracle. Ghidul dezvoltrii aplicaiilor profesionale
58 Serverul de baze de59
date

Conceptele
Din nodul de baz S t o rpentru a g e avem a stabili autentificarea
posibilitatea s unui utilizator
administrm
spre astructurile
avea acces fizice la de o baz
stocare, de date
adic i sspre crem a noi
stabili relaiile de
tablespace-uri,
apartenen
s crem ntre noiobiectele fiiere nstocate n baza de date
noi tablespace-uri sau i n creatorul
tablespace-lor
sunt curile
o n t uexistente,
l i s c h e ms a .redimensionm sau chiar s ndeprtm din
Astfel,
baza pentru
de dateaccesarea aceste fiiere datelor
(ceea dintr-oce nu baz implic,de dedate Oracle
regul, i
trebuie utilizat un cont
tergerea fizic la nivelul sistemului de operare); utilizator care are asociate anumite drepturi
(privilegii) cu privire Ia aciunile sale fa de serverul Oracle sau fa
de obiecteleNetwork stocate
4-0 n baza de date. n mod implicit, printr-un cont
Databases
utilizator devin &4UORACLE - accesibile
sys AS SYSDai Instance toate obiectele din schema asociat.
^Schem
O schem a Securityreprezint
Storage o colecie de obiecte format din tabelele,
Datafiles

view-urile, cluster-ele, f rj procedurile USERS01 DBF


stocate, package-urile .a.
; D:\ORACLE\ORAD.. 25

deinute de unjy Controffile anumit utilizator. Aceasta este creat implicit la


crearea contului t
ft>^respectiv, de aceea numele ei i numele
ZJTablespaces

utilizatorului vor CWM fi utilizate ca fiind echivalente.


UTE
<M|
0R8V
2.4.1. Crearea 8 utilizatorilor i obinerea schemelor de
obiecte
EXAMPLE
fMfcl
NDX
iM&O
Dup cum am vzut y-UOatafiles intr-un paragraf anterior, procesul de creare a
D:\ORAC
bazei de date Oracle
ORoiibackSe a>^XDB produce i doi utilizatori privilegiai,
mputernicii"Segments! sc O Redoefectueze
KJ Datafiles t >ORollback
Log Groups j
sarcinile de administrare care necesit
drepturi speciale, adic SYS, ce deine schema n care se gsesc toate
ffHjArchlYe Logs

obiectele ce formeaz catalogul sau dicionarul bazei de date plus


responsabilitatea de a pomi manual" baza de date aflat n stadiul
shutdown", Figura i SYSTEM, 2.35. Administrarea administratorul structurilorde facto (chiar
fizice din OEM dac i SYS
poate efectua o parte din sarcinile sale), care are, prin urmare, i
Din nodul S e c u r i t y se pot crea noi conturi, roluri sau profile i
puterea" de a crea noi conturi n baza de date sau de a modifica
se pot acorda i revoca privilegii.
detaliile celor deja existente.
Crearea unui cont utilizator nseamn implicit i asigurarea
condiiilor pentru formarea schemei de obiecte asociate acestui
2.4. Utilizatori, privilegii, roluri - ntr-un
cont.
cuvnt,
Practic, la crearea securitate unui utilizator trebuie specificate cel puin
urmtoarele elemente:
Ceicaren use
me l e utilizatorului
hotrsc s investeasc care va ntr-o fi deinfrastructur
fapt numele pentru schemei de
date
obiecte;
avnd n centru un server de baze de date de categorie medie-
grea" psea r ateapt,
o l a ca modalitate bineneles, standard
i la un de suport autentificare n baza de
corespunztor de
date Datele
securitate. (mai trebuie exist s i fie alte
sigure" posibiliti din punctul de de autentificare
vedere al
externally"
accesului: fiecare innd utilizator seama de conturile
s poat vedea" utilizatorilor
i modifica" sistemului
numai
de operare local sau
ceea ce este autorizat. n sistemele de aplicaii cu funcionalitate de reea);
t a b lcare
complex e s p areclam c e - u l danumite e f a u l t n care vor
aspecte legatefi stocate implicit
de confidenialitate
obiectele
i dictate de regulile din schema asociatimplementate,
de afacere" contului; problema devine
tn
critic a bcondiiile
l e s p a c e -unui u l pmediu e n t r u cu s emai
gme n t e lutilizatori,
muli e t e m p o rfiecare
a r e dinavnd
care
va fi utilizatspecifice
responsabiliti spaiul de imemorie
regsindu-se suplimentar necesarunui grup
sub tutela
operaiilor de sortare costisitoare.
De asemenea, tot n momentul definirii unui cont, se poate
.. y- G.--

{default pi . .
5
,G G'vJ.y ;V:r.v> V.S: v.
_______ ........: ______
o V .- - ... .... ,

60 Serverul de baze de date


Oracle. Ghidul dezvoltrii aplicaiilor profesionale 61

graie pentru schimbarea parolei, numrul de ncercri euate de


conectare, blocarea contului etc.
Cel mai simplu mod de a obine un nou utilizator i, implicit, o
nou schem n baza
Network MU de date const n folosirea consolei grafice
O r a c l e E n tDatabases
e r p r - i s e M a n a g e r. Primul pas este, bineneles,
conectarea prin 0BDSTUDconsola
. OEM la serverul bazei de date (local sau
remote) folosind un cont de administrator (SYSTEM, SYS sau un alt
0 ORA

utilizator deinnd rolul DBA). Fereastra


hd^VINZARI - system -
Use Securityde conectare
Management to: pe care o
fp Instance (+>-^
obinei de regul fcnd click pe nodul corespunztor
Create users, roles andbazei
profiles.de date
Schema
sau din meniul N a v i g a t o r C o n n e c t vAlter vausers,
surprinde (probabil) cu
roles and profiles.
Securit/
urmtoarele rubrici: Drop users, roles and profiles.
-CJ Users d>- * Grant privileges and roles to
u s e m a m e - unde ADAMS
putei specifica numele
database users. SYSTEM;
p a s s w o r d - parola lui SYSTEM Viewaa cumgranted
privileges ai precizat-o
to users and la
crearea bazei de date; roles.
AGENT1
s e r v i c e - numele AGENT10(serviciului) bazei de date corespunztor
nodului curent din zona N a v i g a t o r a ferestrei OEM;
<> AGENT11
Quick Tour ; j
c o n n e c t a s - modul de conectare. Cum SYSTEM nu poate

Figura 2.37. Nodul Se curit y

a. Create User - systenrvs'VINZARI

General t Role f System | Object ; Quota v Consumer Group ? Proxy Users

Name: MASTER

W Profile: {DEFAULT

Authentication {password
\ _______________:
__________________;
Enter Password:
-----________
Con,m password: |==j
I------ _
ird Now

Figura
: - Tablespaces 2.36. Conectai-v ca SYSTEM
Default:
n urma unei conectri reuite (sperm), nodul corespunztor
bazei de date se va expanda i vei putea regsi astfel un subnod
Status
intitulat sugestiv S e c u r i t y. Acesta conine Unlocked
trei ramuri U s e r s ,
Ro l e s , Pr o fi l e s . Dup cum v nchipuii, nodul cu care vei avea
de furc n continuare este U s e r s .
Fie prin click pe link-ul create users" din dreapta, fie pe butonul
C r e a t e din stnga, selectnd apoi, din noua fereastr afiat,
rubrica u s e r s , putei obine fereastra C r e a t e U s e r. Aceast
fereastr conine, de fapt, un cadru cu mai Cancel multe Show
pagini:
SQL

primul cadru, G e n e r a l , implic specificarea numelui, profilului


(implicit cel D e f a u l t ) , parolei cu confirmare (pentru modul
de autentificare p a s s w o r d ) , tablespace-urilor d e f a u l t i
62 Serverul de baze de date

al doilea cadru, etichetat Ro l e , implic i specificarea ctorva


drepturi prin intermediul structurilor de tip rol (vom vedea
imediat c r o l - u r i i e reprezint o modalitate simpl de
organizare n grupuri a privilegiilor). Implicit, consola v invit
s v alegei C o m i e c t care asigur un minim de privilegii cu
privire la deschiderea unei sesiuni pe server i permisiunea
crerii ctorva obiecte de baz. Pentru utilizatorii care sunt
implicai n dezvoltarea bazei de date i a aplicaiilor ce
utilizeaz baza de date se mai obinuiete s se asigure i
rolul Re s o u r c e . Coloana D e f a u l t din dreapta semnific

Figura 2.39. Cadrul Role al ferestrei Create User

Dac se dorete o restricionare mai detaliat a modului n care


un utilizator poate folosi spaiul rezervat pentru date, se poate
utiliza cadrul Q u o t a , n care se gsete un tabel ale crui rubrici
reprezint fiecare tablespace n parte. Rolul Re s o u r c e presupune
implicit c utilizatorul va dispune de un privilegiu special prin care
va putea crea obiecte n baza de date nerestricionat din punctul de
vedere al spaiului.
Figura 2.38. Cadrul Ge ne r al al ferestrei Cre at e Us e r
Oracle. Ghidul dezvoltrii aplicaiilor profesionale 63

Butonul C r e a t e va determina crearea unui nou utilizator folosind


specificaiile din diferitele cadre, specificaii care, de fapt, se
materializeaz sub forma comenzilor CREATE USER i GRANT necesare.
Aceste comenzi pot fi vizualizate prin apelarea butonului S h o w
SQL. t Create User - system'S'VINZARI

, Authenllcalion [pass*

EPaW,d F= Confirm Password: j1"

ablespaces-

Temporary P
'.F': -TT

T Locked Unlocked

Cancel 1 Hide SQL

iCREATE USER"MASTER" PROFILE 'DEFAULT'


IDENTIFIED BY maitre DEFAULT TABLESPACE "USERS"
! TEMPORARY TABLESPACE -TEMP-
i''ACCOi UNLOCK;
GFANT "CONNECT TO "MASTER";
|0RANTHRES0URCE" TO "MASTER'

Figura 2.40. Comenzile SQL (DDC) generate pentru a obine" un nou utilizator
Dac, n final, vei obine urmtorul mesaj
Oracle Enterprise Manager

Figura 2.41. Confirmarea succesului n crearea


unui nou utilizator putei considera c v-ai fcut treaba
acceptabil.
64 Serverul de baze de date

2.4.2. Privilegii i roluri

Am menionat mai sus c n procesul de creare a unui nou utilizator, pentru a-


i putea realiza n baza de date operaiile pe care i le propune, acesta
trebuie s dispun de anumite drepturi. Astfel, securitatea unui server de
baze de date trebuie s asigure, pe lng autentificarea utilizatorilor, i
securitatea accesului la obiectele bazei de date plus securitatea aciunilor
generice de manipulare a obiectelor sau a bazei de date n sine. n cazul
Oracle, privilegiile de care poate dispune un utilizator pentru buna
desfurare a responsabilitilor sale sunt mprite n dou categorii:
privilegii la nivel de obiecte, care permit executarea unor
comenzi specifice (UPDATE, DELETE, SELECT) asupra obiectelor
existente n baza de date;
privilegii la nivel de sistem, care se refer la permisiunea crerii,
tergerii sau modificrii proprietilor globale ale obiectelor
(prin comenzi precum CREATE, ALTER, DROP etc.), la permisiunea
conectrii la serverul bazei de date (deschiderea unei sesiuni)
sau, mai mult (pentru SYS, de exemplu), la permisiunea de
nchidere/ deschidere a instanei bazei de date.

Responsabilitile legate de o anumit funciune a unei aplicaii se


dovedesc, uneori, foarte complexe datorit tranzaciilor pe care le presupune,
fapt care poate implica foarte multe privilegiile^nivel de obiect (n SELECT-uri
pentru consultarea a n-tabele, n-UPDATE-uri sau INSERT-uri pentru
actualizarea a n-tabele etc.). Din acest motiv, necesitatea organizrii
privilegiilor n structuri suplimentare devine imperativ. Elementul-cheie n
acest context l reprezint rolurile. Astfel c, pentru a se evita acordarea
repetat a unei structuri coerente de privilegii, acestea pot fi grupate n
roluri, iar acordarea acestora se face o singur dat pentru un utilizator. De
asemenea, folosirea autorizat a acestor structuri de privilegii se poate
realiza prin mecanismele de activare predefinite la nivelul rolurilor. Astfel c,
dup conectare, un utilizator poate dispune de anumite roluri (care i-au fost
acordate n prealabil), iar, pe parcurs, n funcie de contextul
responsabilitilor sale n baza de date, poate solicita activarea altor roluri
(care pot presupune chiar i o re- autentificare suplimentar prin asocierea
unor parole specifice la nivelul lor).
Rolurile mai pot avea o utilitate esenial. La nivelul SGBD-ului
Oracle, nu exist explicit noiunea de grup de utilizatori. Grupurile
de utilizatori sunt necesare ns pentru gestiunea drepturilor
comune pe categorii. Pentru a avea un echivalent al acestor
categorii specifice de utilizatori se pot defini tot roluri. Astfel c, n
funcie de rolurile acordate unui utilizator, se poate stabili din ce
categorie face parte. Acestor roluri/categorii de utilizatori li se pot
acorda privilegii specifice prin acordarea rolurilor care delimiteaz
diversele funciuni ale aplicaiilor.
66 Serverul de baze de date
Oracle. Ghidai
Oracle. dezvoltm
Ghidul aplicaiilor
dezvoltrii profesionale
aplicaiilor profesionale 65 67

activarea lui, se poate alege din rubrica A u t e n t i fi c a t i o n un


privilegiul UNLIMITED TABLESPACE, ce i permite s foloseasc spaiul
mod de autentificare, cum ar fi p a s s w o r d ;
din oricare dintre tablespace-urile pentru date. Rolul DBA, care se
apoi, n cadrul O b j e c t , se selecteaz din arborele din stnga
acord administratorilor bazei de date, conine att privilegii
schema i apoi obiectele ale cror privilegii sunt necesare.
speciale, ce i permit manipularea obiectelor indiferent de
Dup selectarea unui anumit obiect, n stnga va aprea o
proprietarul lor (independent de schem), cum ar fi SELECT ANY
list cu privilegiile disponibile ce vor fi selectate i
TABLE, ct i o serie de alte roluri care i asigur o serie de drepturi
consemnate n tabelul din partea de jos.
eseniale n munca de administrare, cum ar fi SELECT CATALOG ROLE,
Comenzile necesare care vor fi generate n urma acestui proces
ce i permite consultarea tuturor Obeielor dicionarului bazei de
sunt CREATE ROLE i GRANT.
Trebuie menionat c, pentru o astfel de operaiune, sunt
necesare urmtoarele drepturi:
privilegiul sistem CREATE ROLE;
privilegiile obiect pe schema care conine obiectele FAC T E M ,
I Oracle SQL*Plus De Lasemenea,
I N I I F E i C Lpentru
I E N I . ca un rol s fie util, trebuie
Ji xil acordat
utilizatorilor care au nevoie de el. Acest lucru se realizeaz n cadrul
pe Joarch Options tHp
Connected to:
utilizatorului
Ro l e al ferestrei (saudea rolului)
(re)definirerespectiv:
a A
m
0racle8i Enterprise Edition Release 8.1.7.0.0 - Production
With the Partitioning option
JSeroer Release 8.1.7.8.8 - Production ;umer=Q;
SQL> connect MRSTEROvinzari Enter password: ***
Connected.
AQ_AD MINI STRAT 0 R_R 0 LE
SQL> set role GESTFRCT identified by EMISE;
AQ_USER_ROLE
CK_ORACLE_REPOS_OWNER
Role set. CONNECT
CTXAPP
SQL>
DBA 3
-iU ....................................................... . ..........
D E LETE_CATALO G_R 0 LE if
EXECUTE_CATALOG_ROLE
EXP FULL DATABASE

HS_ADMIN_ROLE

Granted:

CONNECT
GESTFACT
RESOURCE

Figura 2.42. Definirea unui rol

Crearea asistat a unui rol se poate face analog utilizatorilor,


dintr-o opiune C r e a t e . . . a Oracle Enterprise Manager (OEM), dup
care se selecteaz rubrica r o l e . Pentru crearea, de exemplu, a unui
rol G E S T FAC T care Figura s Qiprijfcd
2.43, Acordareaprivilegiile
unui Ro l obiecte pentru
consultarea tabelei C L I E N I i inserarea n tabele FAC T E M i
L I NOI I F
mare
E , se importan n acest cadru o are coloana (rubrica)
procedeaz astfel:
D e f a U l tmai
. Bifarea"
nti, n ei semnific
cadrul G e n e ractivarea implicit
a l al ferestrei Creaa trespectivului
e r o l e , va fi
rol specificat
la conectarea utilizatorului la baza de date. n caz contrar,
un nume pentru noul rol i, eventual, dac se dorete este
o
necesar activarea rolului printr-o comand SET ROLE:
68 Serverul de baze de date
Figura 2.44. Activarea unui
rol
prin protocoalele de transport gen TCP/IP, precumcare i s
cer transmit
Clauza i d e n t i fi e d b y este necesar numai pentru
comenzile SQL ctre servere care au n grij bazele de date.
autentificare
rolurile suplimentar (prin parol).
Legtura cu protocolul de transport al reelei se face prin aa-
numitele aclejp adaptoare, furnizate de Oracle, i care asigur
(GL0BAL_D6WAME = Or (ORACLE_HOME = D:\0
independena racle\ora92jl aplicaiilor client de infrastructura de reea existent.
L a n i v e l u l s e r v e r u l u i , elementul esenial l constituie
(sid_name = Oracle)

serviciul L i s t e n e r care ascult" pe un port specific (1521) cererile


clienilor, interpreteaz numele bazelor de date solicitate
consultnd o list de identificatori interni (vezi fiierul
% O R AC L E _ H O M E % \ n e t w o r k \ a d m n \ i s t e n e r. o r a ) i, dac
pentru serviciul BD solicitat exist o instan disponibil, creeaz un
p r o c e s s e r v e r care va prelua sarcina gestiunii mai departe a
dialogului cu clientul care a transmis cererea iniial.
Configurarea L i s t e n e r - u l u i se face, de regul, implicit la
instalare dac se alege inclusiv i crearea unei baze de date. Dac
ns se alege varianta instalrii doar a software-ului necesar
serverului pentru administrarea BD, dar se amn crearea bazei de
date, atunci n pasul explicit al configurrii O r a c l e N e t se cer i
cteva detalii legate de L i s t e n e r (nume, IP-ul mainii server, portul
s e r v2.5. i c i u l u iClieni L i s t e n ei
r - servere
implicit 1521). Oracle
Este util s verificai, la nivelul serverului BD, n C o n t r o l Pa n e l
Ad Pn
m i n acum i s t r a tnu ive am To fcut
o l s consideraii
-> S e r vfoarte
i c e s , explicite
existena asupra modului
serviciului
O nr a ccarel e { Htrebuie O M E J T Nconfigurai
S L i s t e n e xclienii
- Dac din nu reea
exist,pentru creai-1 a se cu putea
Net
conecta la
Mi tistener.ora - Notepad serverul pe care este rezident baza de date. Singurele
^jnjxj
detalii
File Edit Format pe care le tim se refer la faptul c cererile acestora sunt
Help________________________________________________________________________________________
gestionate
# LISTENER iniial de
.ORA Network Configuration File: un serviciu numit L i s t e n e r i c, pentru
D:\orac1e\ora92\network\adrrnn\l'
# Generated by oracle configuration tools.
clientul local, nu sunt necesare configurri suplimentare n afara
celor implicite
LISTENER = de la instalarea software-ului Oracle. ns, pentru o
(DESCRIPTION_LI5T =
aplicaie
(DESCRIPTION client/server
= serioas, tocmai posibilitatea separrii i
fizice a clienilor constituie
(ADDRESS = (PROTOCOL = TCP)(HOST
un atu.= ora)(PORT = 1521))
)
Pentru a gestiona cadrul conectrii clienilor la serverele de baze
(DESCRIPTION =
IPC)(KEY = EXTPROC0))
de 3 date (ADDRESS sau,= (PROTOCOL
mai exact, pentru a crea posibilitatea construirii
>
aplicaiilor pe dou (sau mai multe straturi), Oracle a creat un
protocol specific
SID_LIST_LIST ENER = numit (acum, pentru 9i) O r a c l e N e t . n decursul
istoriei sale acest protocol a mai fost cunoscut ca N E T 8 (pentru
(SID_LIST =
(SID_DESC
Oracle 8.0NAME
(SID_NAME sau= PLSEXtProcl
Oracle 8i) sau chiar S Q L * N E T (pentru Oracle 7,
(ORACLE_F
versiunea 7.3.4). HOME = D:\oracle\ora92)
(PROGRAM = extproc)
O r a c l e N e t permite conectarea clasic a clienilor grei ( f a t
c l i e n t ) la servere de baze de date, colaborarea ntre serverele de
baze de date n arhitecturi distribuite la nivelul BD sau conectarea
serverelor de aplicaii la serverele de baze de date n cadrul
arhitecturilor pe trei straturi cu clieni uori ( t h i n c l i e n t ) . Acest
protocol permite, de fapt, transparena infrastructurii de reea,
fcnd posibil lucrul doar cu nume, sinonime (sau pseudonime) care
s nu implice detalii legate de adresele fizice ale mainilor pe care
sunt distribuite aplicaiile client i serverele.
Figura 2.45. Fiierul de configurare al serviciului lis te ne r, la nivelul serverului
70 Serverul de baze de date
Oracle. Ghidul dezvoltrii aplicaiilor profesionale 69

Oracle Net Configuration Assistant: Net Service Name


Dac aceast informaie nu exist, putei s o adugai
(respectnd sintaxa sugerat n figura de mai sus), dup care va
trebui repornit serviciul Oracle{HOMEfTNSListener din
utilitarul S e r v i c e s al sistemului de operare.
Configurarea clienilor se face:
fie la instalarea software-ului serverului Oracle pentru clientul
For an Oracle8i or later database or service you must
local; provide its service name. An Oracle8i or later databases
service name is normally its global database name.
fie la instalarea software-ului client pentru o main din reea
care va gzdui o aplicaie local (sau un server de aplicaii);
Service Name: jOracle|
fie prin invocarea utilitarului Net C o n fi g u r a t i o n
A s s i s t a n t sau N e t M a n a g e r (mai complet, dar mult mai
complex) din meniul C o n fi g u r a t i o n a n d M i g r a t i o n To o l s
Oracle Net Configuration Assistant: Welcome

Cancel J Help
Welcome to the Oracle Net Configuration
Assistant. This tool takes you through the
following common configuration steps:
Figura 2.47. Specificarea numelui bazei de date
Choose

Apoi vom specifica (de fapt, vom alege dintr-o list) numele
0 Listener

TCP.
mm
protocolului de transport al reelei, astzi, n majoritatea cazurilor,
, r
Naming Methods configuration

Cancel

Figura 2.46. Fereastra de ntmpinare a utilitarului Orac le Ne t Co nfi g u rat io n As s is t ant

Pentru configurarea unui descriptor de pe un client care s


puncteze la o baz de date instalat pe un server din reea se alege
din fereastra de ntmpinare a O r a c l e N e t C o n fi g u r a t i o n
A s s i s t a n t opiunea L o c a l N e t S e r v i c e N a m e c o n fi g u r a t i o n .
n pasul urmtor se opteaz pentru crearea unui descriptor de
serviciu nou opiunea Ad d . Pasul al treilea presupune specificarea
versiunii bazei de date care urmeaz s fie accesat,
compatibilitatea cu versiunile anterioare fiind asigurat dup toate
aparenele pn la nivelul 8.0. Dac am optat pentru O r a c l e 8 i o r
l a t e r d a t a b a s e o r s e r v i c e (tiind c baza noastr de date este
9i), atunci n ecranul urmtor ni se va solicita numele acesteia aa
Figura 2.48. Specificarea TCP ca protocol al reelei

n pasul urmtor (n funcie de protocolul de reea ales), va fi


solicitat adresa mainii-server (adresa 1P sau numele DNS) pe care
se gsete serviciul L i s t e n e r i portul pe care ascult acesta
(implicit 1521):
Oracle. Ghidul dezvoltrii aplicaiilor profesionale 71

Oracle Net Configuration Assistant: Net Service Name Configuration, TCP/IP Pri

To communicate with the database using the TCP/IP ,


protocol, the database computer's host name is required.
Enterthe host name forthe computer where the database Is
located.

Hostname

ATCP/IP port number is also required, in most cases the


standard port number should be used.

Use the standard port number of 1521 c Use another port


number {i 521

Cancel

Figura 2.49. Specificarea adresei i a portului L is te ne r- nhi i

n fine, putem eventual testa mai nti conexiunea, iar la ultimul


pas ni se va cere un n u m e pentru descriptorul de serviciu creat,
care poate fi acelai cu numele bazei de date (se recomand) sau...
nu. Dac numele serviciului pe maina clientului va fi altul dect
numele bazei de date, atunci la h o s t n o m e vom specifica
ntotdeauna numele serviciului local ale crui detalii le-am precizat
Oracle Net Configuration Assistant: Net Service Name Configuration, Net Service Name

Choose a name for this net service name. The Oracle Net
Configuration Assistant has defaulted the net service name
to be the same as the service name you entered earlier,
but you can change it to be any name you choose.

Net Service Name

Cancel I

Figura 2.50. Specificarea numelui descriptorului de serviciu, care poate s fie


acelai cu
numele bazei de date sau nu
72 Serverul de baze de date

Dup parcurgerea acestui proces, aplicaiile instalate local vor


putea avea acces la baza de date folosind numele serviciului
O r a c l e , fr a avea astfel nevoie de detalii suplimentare despre
configurarea reelei.
Ca rezultat al secvenei de configurare anterioare, informaia
privitoare la conectarea clienilor este pstrat n %
O R AC L E _ H O M E % \ n e t w o r k \ a d m i n \ t n s n a m e s . o r a , n care vom

Figura 2.51. Fiierul de configurare tnsnames.ora, la nivelul clienilor


Capitolul 3

Interfaa (neprietenoas) cu serverul:

SQL*Plus

Orice server de baze de date, deci i Oracle, impune existena unei


aplicaii client prin intermediul creia utilizatorii s gestioneze obiectele
din baza de date n decursul timpului, o dat cu sporirea performanelor
noilor versiuni Oracle i a cotei de pia!^ a produsului, mai multe companii
au dezvoltat diverse utilitare software comerciale, ce ofer o interfa
grafic prietenoas pentru administrarea bazei de date. Chiar dac ultimile
versiuni Oracle furnizeaz i ele un asemenea utilitar, sub forma Enterprise
Manager Console, btrnul SQL*Plus rmne totui varianta de platform-
client utilizat de majoritatea dezvoltatorilor mptimii, pentru care nimic
nu se compar cu a scrie cod pentru orice operaie direct n linie de
comand.
SQL*Plus reprezint cea mai simpl form de aplicaie client pentru
serverul Oracle ce se instaleaz n mod implicit o dat cu instalarea
clientului Oracle. Orice operaie de administrare a bazei de date sau de
manipulare a obiectelor din schema proprie a utilizatorului presupune
scrierea explicit a unei comenzi SQL (uneori SQL*Plus) sau a unui bloc
PL/SQL.

3.1. Elemente generale

Pentru a lansa n execuie SQL*Plus, exist dou posibiliti:


pentru sistemul de operare Windows9X putem utiliza meniul de
start,
S t ar t-> Progr ams-^Oracle-OUI Home-> Application Development/SQI.
Plus
lansarea n execuie a fierului corespunztor ce se gsete pe
calea:
%ORACLE_HOME%\ora81\bin\SQLPLUSW.EXE1
nainte de a lansa n execuie acest utilitar, trebuie s ne asigurm c
serverul Oracle este pornit. Bineneles c primele informaii pe care

1. ORACLE I iOME = adresa pe disc a directorului rdcin n care s-a instalat serverul.

74 Interfaa (neprietenoas) cu serverul: SQL*Plus

Figura 3.1. Fereastra de Log On" a SQL*Plus

n fereastra de mai sus trebuie introduse:


numele de utilizator Oracle i parola pentru serverul la care
dorini s ne conectm;
n csua Host St ring: numele serviciului NET8 configurat
pentru un anumit server. Dac serverul Oracle este instalat
local i este pornit, putem ignora aceast csu, SQL*Plus
conectndu-se implicit la acesta.
Este important s nelegem faptul c n csua Host String
trebuie introdus numele serviciului definit pentru un anumit server
Oracle, i nu adresa IP a calculatorului-gazd. Numele tuturor
serviciilor definite pot fi gsite n fiierul
2
0RACLE_H0ME\ora81\network\ADMIN\Tnsnames. ora . Spre exemplu,
pentru un coninut precum cel din listingul 3.1 al acestui fiier, o
valoare valid pentru cmpul Host String ar fi: VINZARI
Listing 3.1. Exemplu de fiier tnsnames.ora
# TNSNAMES.ORA Network Configuration File: D:\oracle\ora81\network\admin\tnsnames.ora
# Generated by Oracle configuration tools.

VINZARI =
(DESCRIPTION =
(ADDRESSJ-IST =
(ADDRESS = (PROTOCOL = TCP)(HOST = xxx.xxx.xxx.xxx)(PORT = 1521))
)
(CONNECT_DATA =
(SID = orei)
)
)
BDSTUD=
(DESCRIPTION =
(ADDRESSJ-IST =
(ADDRESS = (PROTOCOL = TCP)(HOST = xxx.xxx.xxx.xxx)(PORT = 1521))
)
(CONNECT_DATA =
(SID = Oracle)
))
Dac nu introducem un nume valid de serviciu NET, serverul va

2. Trebuie acordat o atenie deosebit acestui fiier! Pentru mai multe


informaii n acest sens, vezi capitolul 2.
Oracle. Ghidul dezvoltrii aplicaiilor profesionale 75

ERROR:
ORA-12154: TNS:could not resolve service name n cazul n care
informaiile de conectare au fost specificate corect, iar SQL*Plus a
reuit s se conecteze la server, vom obine fereastra din figura 3.2.

Figura 3.2. Fereastra standard SQL*Plus dup dou ncercri de


conectare
(prima nereuit)
Acest utilitar nu ofer elemente de interfa GUI (Graphical User
Interface), ci doar un prompter la nivelul cruia pot fi introduse:
i n s t r u c i u n i S Q L (att din categoria Data Definition Language,
ct i Data Manipulation Language) i c o m e n z i s p e c i fi c e
S Q L * P l u s . Fiecare instruciune SQL va fi trimis serverului, acesta
o va executa i va trimite napoi un rspuns (rezultatul execuiei) ce
va fi afiat de SQL*Plus n fereastra curent de lucru.
Dup cum observai i n figura 3.2, prompterul este poziionat
imediat dup o directiv SQL> ateptnd introducerea de
instruciuni SQL sau comenzi specifice SQL*Plus.
Vom exemplifica maniera de lucru cu acest utilitar pornind de la
crearea unei tabele, Angajai, cu definiia din figura 3.3.
76 Interfaa (neprietenoas) cu serverul: SQL*Plus

Ele Edit Search Options | Help

SQL> create table Angajai (


2 narea Integer,
3 numePren warchar2(108),
it compartiment oarchar2(20)
5dataflngajare date,
6salorar nunber(12,2),
7sex char(1)
8 )
9 /
create table Angajai (

ERROR at line 1:
ORA-0O922: missing or inualid option

SQL>

Figura 3.3. Primul contact... prima eroare


Figura 3.3 demonstreaz cteva dintre e l e m e n t e l e e s e n i a l e
ce trebuie cunoscute atunci cnd lucrm cu SQL*Plus:
o instruciune standard SQL poate fi scris pe oricte rnduri
(sfritul de rnd se introduce prin intermediul tastei
E n t e r );
nu pot fi lsate rnduri libere n cadrul unei instruciuni
scrise pe mai multe rnduri;
o instruciune SQL se lanseaz n execuie prin una dintre
comenzile SQL*Plus: /(slash) sau; (punct-virgul);
putem utiliza comanda / pentru a lansa de mai multe ori n
execuie coninutul bufferului SQL*PIus (ultima instruciune
SQL sau ultimul bloc PL/ SQL);
un rnd, o dat editat, nu mai poate fi modificat n mod
direct, dect prin intermediul tastei B a c k S p a c e care terge
caracterele din stnga cursorului;
n cazul unei erori (n exemplul din fig. 3.3 lipsete virgula
dintre compartiment i dataAngajare) numrul liniei indicate
drept eronat nu este ntotdeauna corect.
O dat eroarea detectat, s-ar prea c ar trebui s rescriem
ntreaga fraz SQL. Exist ns o posibilitate de a modifica
instruciunea lansat ultima dat n execuie, dac apelm Ia
comanda SQL*Plus EDIT, care deschide un editor de texte (Notepad
n Windows) ce va conine bufferul SQL*Plus (ultima instruciune
SQL executat). O dat efectuate modificrile necesare, editorul se
nchide cu opiunea de salvare a modificrilor i se rescrie comanda
pentru lansare n execuie: / sau ;. n exemplul de mai sus, tastarea
comenzii EDIT pe linia prompterului SQL*PIus va deschide editorul
de text cu fraza SQL de creare a tabelei Angajai.
h l o t . Comanda / se scrie ntotdeuna pe o linie nou (care, de
altfel, va fi i ultima). Comanda ; (punct-virgul) poate fi scris la
sfritul ultimei linii ce constituie instruciunea SQL. De asemenea,
este important s reinem c actualizrile nregistrrilor din diverse
tabele ce au loc n urma unei instruciuni SQL trebuie
Oracle. Ghidul dezvoltrii aplicaiilor profesionale TI

Vizualizarea definiiei unui obiect din baza de date poate fi


realizat prin comanda DESCRIBE numeObiect (deexemplu, DESCRIBE
Angajai).

3.2. Scripturi SQL


Bufferul SQL*Plus poate conine la un moment dat doar o singur
instruciune SQL, aa c dezvoltatorii de aplicaii recurg, de cele mai
multe ori, la scripturi SQL. Acestea nu sunt altceva dect o niruire
de instruciuni SQL i/sau comenzi SQL*Plus scrise cu un editor de
texte oarecare i salvate ntr-un fiier cu extensia . sql. Extensia nu
este obligatorie (poate fi i . txt), ns fiierul va conine doar text
conform standardului ANSI (fr nici un element de formatare).
Figura 3.4 prezint un exemplu de asemenea fier ce poate fi
lansat n execuie din SQL*Plus.

Figura 3.4. Exemplu de script

Elementele eseniale ce trebuie avute n vedere la redactarea


unui script SQL sunt urmtoarele:
orice instruciune SQL trebuie finalizat cu una din comenzile
SQL*Plus pentru execuie (/ pe o linie nou sau ; pe aceeai
linie);
n cadrul unei instruciuni SQL nu pot exista linii libere,
aceast restricie nefiind valabil pentru instruciuni diferite;
pentru iruri de caractere se utilizeaz apostrof, nu
ghilimele (regul general valabil, de altfel, n Oracle);
comentariile se introduc n maniera text comentat -- (vezi n
acest sens i listingul 3.2) sau prin secvena de caractere */
la un capt i /* la sfrit;
nu trebuie uitat comiterea" eventualelor modificri, ca
rezultat al unor fraze SQL-DML (Data Manipulation Language)
prin intermediul instruciunii COMMIT.
78
Oracle. interfaa (neprietenoas) cu serverul:79
Ghidul dezvoltrii aplicaiilor profesionale SQL*Plus

se renun la marcaj n script, iar la execuie se specific


Comanda un SQL*Plus pentru ncadrat
ir de caractere lansareantre
n execuie a unui
apostrofuri (' script SQL
valoare');
este
dac: @fiser.ext [lista de
din script parametri]
lipsete instruciunea commit, pentru
Aa permanentizarea
cum observai i n figura 3.5, execuia
actualizrilor aceasta unui script executat
va trebui nseamn
execuia
dinfrazelor
SQL*PlusSQL dup
i a comenzilor
execuia SQL*Plus
scriptului nsau
ordinea
la un natural"
moment
n careulterior,
au fostneditate. Despre parametri
funcie de alte necesiti. vom discuta n cele ce
urmeaz.
Listing 3.2. Utilizarea variabilelor de substituie ntr-un script SQL
-- Comentariu: Vom utiliza variabile de substituie compart_ si salariu_Vitalie -- insert into Angajai
N o t . Pentru a lansa n execuie un script dintr-un alt script, se
values
va folosi comanda:
0@ numeSubScript (dublu at")
(11111 ,'Enea Silvestra', '&compart_', to_date(01/01/1978,,,dd/mm/yyyy'),15000000,'F'); insert into
E tirade MJl 'Mlu
O 6 Mt a* ; mp
Angajai values SQL> a d:/r<data/scriptbd.sql;

Oracle SQL*Plus
0b E<* Swch Options fcjolp
SQL> Q d:/oradata/script2.txt Enter 1 ro crcatvd 1
ualue for conpart_: Financiar
old 2: {11111 ro crootod 1 ,to_date('01/01/1978','dd/nm/yyyy').15080008.'H')
,Enea Silvestra' ,'fcconpart^
new 2: (11111 ,'Enea Silvestra','Financiar',to_date('01/01/1978','dd/nn/yyyy'),15088800,'M')
1 row created.
ro* crtoted 1
row created
Enter ualue for conpart_: 'Contabilitate'
Enter ualue for salariu_uitalie: |
Commit complete.
SL_______________________________________________________________________
S|L>

Figura 3.6.jJJ.
Execuia scriptului din listing 3.2
Figura 3.5. Execuia unui script SQL

Exist i posibilitatea utilizrii variabilelor de substituie n


3.2.1. Variabile de substituie i parametri n scripturile
combinaie
SQL cu instruciunea ACCEPT care d e fi n e t e o variabil i
solicit la momentul execuiei o valoare pentru aceasta, valoare ce
Variabilele
va fi apoi utilizatde substituieori de cte suntori utilizate pentru variabila
este ntlnit a furnizarespectiv
valori n
mod interactiv
pe parcursul la execuia
scriptului. unui comenzii
Sintaxa script SQL. ACCEPTVariabilele se declar n
este urmtoarea:
ACCEPT scriptului
interiorul [NUMBER|CHAR|DATE]
v a r i a i a astfel (vezi i listing [FORMAT 3.2): format]
Snumevariabila
[DEFAULT v a l l m p l i c i t a ] PROMPT t e x t D e A fi s a t |[NOPROMPTj
Un exemplu nexecuiei,
La momentul acest sens l constituie
SQL*Plus listingul
va solicita valori3.2 pentru
bis i figura
toate
3.6 bis unde
variabilele putem observa
declarate, va nlocui c, respectivele
la execuie, SQL*Plus verific dac
valori n instruciunea
se respect
SQL (n locul formatul specificat,
variabilelor), iar, n caz final, contrar afindu-se
va trimite fraza SQLun mesajspre
de eroare(figura
execuie i solicitndu-se
3.6). din nou o valoare valid.
Analiznd listingul 3.2 i figura 3.6, este important s reinem:
Listing 3.2 bis. Declararea unor variabile cu instruciunea ACCEPT
numele variabilelor nu trebuie obligatoriu s fie unic;
ACCEPT dataAng DATE FORMAT 'dd/mm/yyyy' DEFAULT '01/01/2003' PROMPT 'Introducei data angajarii
dac utilizm acelai nume de variabil de mai multe ori,
(format zz/ll/aaaa):1
SQL*Plus va solicita valori pentru fiecare declaraie, i nu
ACCEPT salpentru fiecare
NUMBER DEFAULT '0.00'nume unic de
PROMPT 'Introducei variabil
Salariul (exist
pentru Afloarei:' insert i o alt
posibilitate redat mai jos);
into Angajai values (11127 ,'Agafitei
n cazul variabilelor
Cristina','Contabilitate',to_date( ce substituie
'&dataAng,'dd/mm/yyyy' un ir de caractere, exist
),15000000,'F');
dou posibiliti de declarare a lor (vezi variabila compart_):
insert into Angajai
sevalues (11128,'Afloarei
ncadreaz Ionela','Financiar*,to_date(
declaraia variabilei '&dataAng','dd/mm/yyyy'),
ntre apostrofuri &sal,'M');
i, la
80 Oracle. Ghidul dezvoltrii aplicaiilor profesionale
Interfaa (neprietenoas) cu serverul: 81
SQL*PIus SQL*PIus
82 Interfaa (neprietenoas) cu serverul:
Dup cum se observ, spre deosebire de variabilele de
3.3.1. Principalele
substituie, un comenzi
parametru poate fi utilizatSQL*Plus
de mai multede
Ffc dt Search Options tjelp SQL> Pd :/oradata/script2.txt ori n cadrul
Introducei data angajarii (format zz/ll/aaaa): 12-ian--20U2
formatare
Oracle.
aceluiai
SP7-0ft8S: a rezultatului
The date Ghidul
script, avnd aceeai
"12-ian-2B82" interogrilor
dezvoltrii
is inualid or aplicaiilor
format mismatchedprofesionale
83"dd/ran/yyyy
Introducei data angajarii (format zz/ll/aaaa): 12/12/2082 Introducei Salariul pentru Afl oarei: old 1: insert
valoare furnizat la momentul execuiei.
intoAngajaioalues (11127
9* E<* 5earth Qpdons t* ,Agafi tei Cristina,'Contabilitate*,to_date('CdataAn
; .' " '
new 1: SQL>
insert
setinto Angajai ualues (11127/ ,Agafi tei Cristina',Contabilitate,to_date('12/12/21
FormatareaNSQL>
o tset rezultatului
linesize
. pagesize
Parametrii
61
121
ceunei interogri
corespund unor SQL
valori trebuie
de tip ir s dese caractere
realizeze
1 row created.
nainte
(&1 deColunn
n
SQL> execuia
exemplul de
conpartinentfrazei
mai
fornat SELECT.
sus) vor Ofi parte
SQL> coturni nunepren fornat 13 WORDWRAP
A16 ncadrai din ntre
comenzile SQL*Plus
apostrofuri, iar
old 1: SQl>
insert into sexAngajai
colunn fornat A3 ualues ( 11128,Afl oarei Ionela*,fi nanciar,to_date(bdataAng',dd
pentru
new formatare
1: SQL>
insert le
into conpartinent
Colunn Angajai regsim
ualues
fornat n tabelul
A1S( 11128,'Afl oarei 3.1.
Ionela*,Financiar',to_date(12/12/2O02*,
SQL> colunn salariu fornat 99,999.999.99
3.3.
SQL> colunnFormatarea
SQL> colunn nunepren heading *HUME |ANGAJAT'
1 row created.
dataangajare heading DATA (ANGAJARE* rezultatului interogrilor
SQL 3.1. Principalele comenzi de formatare a rezultatului interogrilor
SQL>_____________________________________________________________________________________________________________________________
SQL> select fron angajai;
Tabelul

Rezultatul frazelor Select SQL este afiat de SQL*Plus dup o


Figura 3.6 bis. Execuia scriptului 3.2 bis
schem de formatare predefinit care, de cele mai multe ori, nu
Se observ
ofer c, dei
un aspect variabila
tocmai dataAng
lizibil. Astfel, este declarat
dac analizm de tip Date,
figura 3.8,
aceasta este preluat de la prompter
observm cel puin cteva neajunsuri: sub form de ir de caractere,
fapt pentru care se recurge,
dimensiunea implicitna cadrul scriptului,
liniei este de 80 de la caractere,
o funcie de ceea
conversiece(TO_DATE ( ' text ' , ' format' )).
determin afiarea unei nregistrri pe mai multe linii;
Un script SQL poate
dimensiunea s conin
implicit declaraii
a paginii de parametri,
de afiare este de 14 valorile
rnduri,
actuale ale acestora fiind furnizate sub form de list
fapt ce are ca rezultat afiarea antetului (numele coloanelor)(separate prin
spaiu) nde
cadrul comenzii
mai multe ori de lansare fereastr
n aceeai n execuie (@ .
SQL*Plus; .
./numescript. ext paraml
n antetul param2 param3).
rezultatului, titlul coloanelor este acelai cu
Declararea parametrilor
numele coloanelorse realizeaz
tabelelor prinbaza
din aceeai comand &:
de ordine
date;
unde indexParametru reprezint numrul de al valorilor
spaiul alocat fiecrei coloane este
specificate n lista de parametri la execuia scriptului. egal cu lungimea maxim
a cmpurilor tabelelor ceea ce duce la utilizarea ineficient a
Listing 3.3. Scriptpe parametrizat
C o m aspaiului
nda disponibil un Ornd
bserv ia uneori
ii la afiarea
- utilizarea parametrilor-
SET LINESIZE n n=numrul caracterelor pe rnd
SET PAGESIZE n insert into Angajai values(11112n ,'Atudorei
= n u mVioleta,'&1',to_date('01/01/1978,'dd/mm/yyyy'),&2,'F');
rul liniilor pe pagin
model p oMaria','&1',to_date('01/01/1978',dd/mm/yyyy
a t e fi :
COLUMN numeco! FORMAT model ,
insert into Angajai values( 11113,'Creanga ),&3,,F');
A20 - f o r m a t A S C I I d e d i m e n s i u n e 20
commit;________________________________________________________________________________
9,999.99 - format numeric de
Ete notesul
E<*t Search QpUons Hrip
dimensiune 4 ntregi i 2
z eutilizarea
SQL> Q d:/oradata/script3.txt Sec?ia2 SfeBBOO 231)080
mld Figura
1: insert into3.9 ilustreaz
Angajai
c i m Uioleta',61',to_date(01/01/1978,*dd/mm/yy
ualues(11112 ,Atudorei
a l e (opiunilor
v a l o r i l e dema i m a r i pentru
formatare
new 1: insert into Angajai ualues(11112
a afia rezultatul interogrii d,Atudorei
e c tUioleta',Sectia2,to_date(01/01/1978',dd/
l u nfigura
din g i m e3.8.
a s p e c i fi c a t v o r
fi n l o c u i t e c u # )
1 row created.
P o a t e fi s p e c i fi c a t i m o d u l d e
old 1: insert into Angajai ualues( 11113,'Creanga Maria*,'81',to_date(81/01/1978,dd/nm/yyyy
new 1: insert into Angajai ualues( 11113,'Creangag e s t i o Maria,Sectia2,to_date(81/01/1978,dd/mm/
nare a valorilor de tip ir
1 row created.
de caractere ce depesc
lungimea s p e c i fi c a t la
Commit complete. formatare:
SQL> | Figura 3.8. WRezultatul
R A P - aneformatatfi e a z al p e m
unei a i m uSQL
interogri lte
jlU HEADING titlu'
COLUMN numecol S
r pnedc u i fi
r ic WO un RDt i_tWl uR A pP
e n-t raufi e a z
Ca urmare, este necesar c pregtirea terenului"
i vl d e anainte de
Mool d o iafinca r feosrpm eac tt u
ALTER SESSION SET NLS_DATE_FORMAT = DD-MM-YYYY;
Figura 3.7. Execuia scriptului din listingul 3.3 pe baza fi afurnizate
valorilor re al
realizarea unei interogri.
pentru datei calendaristice pentru
HAR HUNE DATA s e s iparametri u n e aSEc u r e n t S Q L * P l u s .
CA ANGAJAT CONPARTIN ANCAJA
ENT SALARIU
X
211 Petrol Conatblll RE
01- 10.880,88 F
11 Oxana tate R1- 8.80
311 Adascali Conducere 1-0S- 213.09H
11 tei 1998
*11 Hotei
Profitor Financiar 1-09- 6,000,000 F
11 u 1992 .00
Uasilica
211 Uartolon Contabili 1-01- S,600,000 H
11 el tate 1992 .00
Ultalle
111 Atudorel Sectla2 1-01- F
12 Violeta 1978
111 Creanga 01-01- 230,088.8
13 Naria Sectia2 1978 0F
Capitolul 4
Crearea tabelelor i definirea
restriciilor
4
Crearea structurilor fizice ale unei baze de date, asupra creia am zbovit
n capitolul 2, constituie etapa premergtoare implementrii tabelelor, tabele
ncadrabile n categoria structurilor logice. Aceast operaiune presupune nu
numai specificarea numelor tabelelor i ale atributelor care le compun, ci i
declararea restriciilor menite a asigura integritatea i coerena informaiilor
din baz. Este ceea ce propunem spre discuie n acest capitol.

4.1. Prezentarea schemei bazei de date folosite n


lucrare
6 rows selected.
Baza
sqL> de date n jurul creia vor gravita majoritatea exemplelor din
acest capitol i din cele urmtoare are o structur nu suprtor de
complex. Obiectivul principal
Figura l constituie
3.9. Rezultatul gestionarea
formatat informaiilor
al frazei SELECT
legateRezultatul unei interogri SQL poate fi salvat ntr-un fierdoar
de salarizare pentru o firm care i pltete angajaii ASCII
pepebaza orelor lucrate (n sensul c alte forme de
disc dac apelm la comanda SPOOL [ fi l e _ n a m e [ . ext] |salarizare,
precum
OFFIOUT]acordul
, unde direct,
opiuneaacordul global etc., spooug-uF,
OFF dezactiveaz nu sunt luate iar n
OUT
considerare).
trimite la imprimant rezultatul. Comanda trebuie executat
Cele ase
nainte tabele iniiale
de iniierea ale bazei sunt: PERSONAL, PONTAJE,
interogrii.
SPORURI, REINERI, SALARII i TRANE_SV, fiind reprezentate n
figura 4.1. Pe parcurs, local, vom folosi i alte tabele sau vom
modifica uor structura existent.

Tabela PERSONAL reprezint nomenclatorul angajailor firmei.


Atribute:
Marca este un numr unic, secvenial, atribuit la angajare fiecrui
om al muncii;
NumePren - numele i prenumele;
Compart - compartimentul cruia i este afiliat angajatul curent;
DataSV - data de la care se vor calcula anii de vechime, ani
necesari determinrii sporului de vechime; este, de multe
ori, data primei angajri, dar exist suficiente situaii n care
o persoan a plecat pentru cteva luni/ani la lucru la negru
prin rile UE sau alte spee n care DataSV (data pentru spor
86 Crearea tabelelor i definirea restriciilor

Colaborator - indic poziia de angajat curent sau temporar a


persoanei respective.
Fiecare linie corespunde unui angajat, aa c atributul Marca este
cheia primar a tabelei.

Figura 4.1. Cele ase tabele iniiale ale bazei


Tabela PONTAJE conine datele importante despre orele lucrate n
fiecare zi de ctre un angajat. Atribute:
Marca are aceeai semnificaie precum atributul PERSONAL. Marca;
Data este ziua pentru care se introduce pontajul;
OreLucrate - numrul de ore lucrate n ziua curent de angajatul cu marca
curent; valoarea implicit a acestui atribut este 8;
OreCO - are valoarea 0 dac persoana nu este n concediu n ziua
curent i 8 n caz contrar (i fericit);
OreNoapte - conine cte ore, dintre cele lucrate, sunt asimilate
activitilor de noapte i pltite corespunztor;
OreAbsNem - ore absene nemotivate, adic numrul orelor de chiul
fr avizul efului pentru ziua respectiv.
Fiecare linie corespunde unui angajat i unei zile lucrate, prin urmare cheia
primar este compus: (Marca, Data).

Tabela SPORURI centralizeaz sporurile lunare ale fiecrui angajat.


Atribute:
Marca are aceeai semnificaie precum atributul PERSONAL. Marca;
An este anul la care se refer sporurile de pe linia curent;
Luna este luna la care se refer sporurile de pe linia curent;
Tip Descriere Comentarii

88 Oracle. Ghidul dezvoltrii aplicaiilor profesionale 87


Crearea tabelelor i definirea restriciilor

Fiecare linie corespunde


SpVech - sporul deunui angajat
vechime i unei luniangajatului
corespunztor (i an), cheia
pentru
primar fiind
anulcombinaia:
i luna de (Marca, An, curent;
pe linia Luna). se calculeaz nmulind
venitul de baz cu procentul de spor de vechime, procent
Tabela obinut
TRANSE_SV este TRANE_SV
din tabela izolat, rolul su numrului
pe baza fiind decisiv n de
de ani
calculareavechime
procentului sporuluicurent;
ai angajatului de vechime
venitul deacordat
baz estefiecrui
descris la
angajat. Procentul depinde
tabela SALARII; de trana de ani de vechime n care se
ncadreaz angajatul -n
OreNoapte prima zi a lunii
centralizeaz orelede referin.
lucrate De exemplu,
n regim de noapte de
ntre 0 i trei ani de vechime,
un angajat pentru lunaprocentul
curent;este zero, ntre trei i ase
ani este 5% (probabil). Atributele
SpNoapte - sporul de noapte, calculat prinAni_Liraita_Sup
Ani_Limita_Inf, i
nmulirea salariului
conin
Procent_SVorar cu cele trei elemente
numrul orelor deale fiecreiprodus
noapte, trane.ponderat cu 15%
(att acord firma n plus pentru orele lucrate noaptea);
4.2. Principalele tipuri de date Oracle
AlteSp - alte sporuri (stres, toxicitate, ruine, condiii
deosebite etc.).
Ca o condiie prealabil a crerii unei baze de date, este mai mult
Fiecare linie corespunde unui angajat i unei luni (i an), cheia
dect necesar s se cunoasc ce tipuri de date pot fi gestionate
primar fiind
prin SGBD-uI folosit. n orice server de baze de date, pentru a crea
c o m b i n a i a : (Marca, An, Luna).
o tabel trebuie specificate tipurile de date folosite la stocarea
fiecrui cmp.REINERI
Tabela De obicei,centralizeaz
n Oracle tipurile de date
reinerile sunt mprite
lunare ale fiecrui
astfel:
angajat. Atribute:
Tipuri predefinite:
Marca are aceeai semnificaie precum atributul PERSONAL.
o
Marca;
scalare;
An este anul la care se refer reinerile de pe linia curent;
o
Luna este luna la care se refer reinerile de pe linia curent;
colecii;
Pr opriri, CAR, Al te Ret (alte reineri) - diverse forme de
o
reineri de pe statul de plat n contul unor debite, obligaii
referine
etc.;
;
TipuriFiecare
definiteliniede
corespunde
utilizator. unui angajat i unei luni (i an), cheia
primar fiind combinaia: (Marca, An, Luna).
Tabelul 4.1. Principalele tipuri scalare de date n Oracle
Tabela SALARII este cea care culege" informaii din PONTAJE,
SPORURI i REINERI, fiecare linie fiind o sintez a drepturilor i
reinerilor unui angajat i lun-an date. Atributele sale sunt:
Marca are aceeai semnificaie precum atributul PERSONAL.
Marca;
An i Luna reprezint. Juna pentru care se centralizeaz
datele privind salarizarea;
OreLucrate se determin prin nsumarea orelor lucrate de
angajatul curent n luna de referin (pe baza OreLucrate din
PONTAJE);
OreCO - suma orelor n care, pe luna curent, angajatul a fost
n concediu de odihn;
Venit Baz - venitul de baz se determin prin nsumarea
produsului
SALARII.OreLucrate * PERSONAL.SalOrar c u SALARII.OreCO *
PERSONAL.SalOrarCO;
Oracle. Ghidul dezvoltrii aplicaiilor profesionale 89
CHAR (n) ir de caractere cu Lungimea fix presupune completarea
lungime fix egal automat cu spaii a valorilor cu lungime
cu n octei (bytes) mai mic; lungimea maxim admis este
de 2000 bytes. nainte de specificarea
lungimii trebuie avut n vedere setul de
caractere utilizat (cu reprezentare pe un
byte sau multibyte).
VARCHAR2
O valoare de lungime mai mic a
(n) ir de caractere cu
atributului la un moment dat nu va fi
lungime variabil
completat cu spaii adiionale. Lungimea
(maxim n bytes)
maxim este de 4000 bytes.
Date numerice de p=precizia (lungimea maxim a
NUMBER
lungime variabil numrului), iar s=scala (numrul de poziii
! ( P, S )
| zecimale rezervate, incluse n lungimea
maxim). Spre exemplu, pentru coloana
! Salariu Number(5,2), valoarea 100,55 este
valid n timp ce 1000.5 sau 1.222 este
i
invalid. Precizia poate fi de maxim 38
j
cifre.
DATE
Date calendaristice Lungime fix de 7 bytes (vezi i
i temporale comentariile ce urmeaz acestui tabel).

CLOB Character Large Poate stoca iruri de caractere pn la 4


Object gigabytes. Un atribut de acest tip nu
poate fi folosit n subinterogri, funcii
sau clauza WHERE a unei fraze SELECT
SQL.
I LONG Date de tip ir de Poate stoca iruri de caractere pn Ia 2
| caractere de gigabytes. Aceleai restricii ca i n cazul
I
1 lungime variabil tipului CLOB. Documentaia Oracle
1 recomand destul de insistent renunarea
i
i la acest tip n favoarea CLOB.
!
BLOB
i Date binare
Maxim 4 gigabytes.
1 nestructurate
i
!
iBFILE Date binare
Pointer spre un fier de pe disc cu
| stocate ntr-un
i dimensiunea maxim 4 gigabytes.
fier extern
i ............... . . Acest tip este specifi c pseudocoloanei
!ROWID Date n format ROWID ce este asociat n mod implicit
binar reprezentnd fiecrei tabele a bazei de date. Valorile
i
adresa fizic pe identific n mod unic fiecare nregistrare
disc a nregistrrii n baza de date Oracle.

90 Crearea tabelelor i definirea restriciilor

De cele mai multe ori ns se recurge la funcii de conversie:

INSERT INTO test VALUES (T0_DATE (' 12/02/1998' , '


DD/HM/YYYY' ))

Pentru detalii legate de funciile de conversie i alte funcii de


lucru cu date numerice, iruri de caractere i calendaristice, vezi

4,2.2. Tipuri abstracte definite de utilizator


Oracle ofer i suport pentru definirea unor tipuri abstracte de
date, ca extensie spre modelul obiectual. Astfel de tipuri se declar
de maniera urmtoare:

CREATE TYPE dentip AS


OBJECT (atrib_l Tip, atrib_2 Tip ...)

Tipurile abstracte pot fi apoi utilizate ca tipuri ale atributelor din


tabele. Astfel, vom crea tipul Adresa TY pentru a defini adresa
complet a persoanelor ce locuiesc ntr-o anumit localitate.
Definim apoi o tabel LOCUITORI ce va conine persoanele care
domiciliaz ntr-o localitate, adresa lor fiind specificat prin
intermediul tipului nou-creat.

CREATE TYPE AdresaJTY AS OBJECT {


Strada VARCHAR2 (30) ,
Numr VARCHAR2 (10),
Bloc VARCHAR2 (10) ,
Ap INTEGER ) ;

CREATE TABLE Locuitori (


Cnp INTEGER,
Nume VARCHAR2 (30) ,
La inserarea nregistrrilor n aceast tabel, pentru atributul
Adresa vom utiliza comanda INSERT n urmtorul format (valorile
fiecruiAr mai trebui
atribut adugateal
component cteva chestiuni
tipului legate
se scriu ntredeparanteze):
tipurile scalare, i
anume:
specificatorul pentru o constant de tip ir de caractere este
INSERT INTO locuitori VALUES (11111, 'FaneC.',
apostroful, i nu
ADRESA_TY(CUG', ghilimele;
*22 BIS*, 'A5', 13) ) ;
pentru datele calendaristice formatul implicit Oracle este DD-MON-RR.
INSERT INTO locuitori VALUES (11112, 'MandacheV.* ,
ADRESA_TY('CUG', '22 BIS , lA5, 13) ) ;
Spre
INSERT exemplu,
INTO pornind
locuitori de la o
VALUES definiieCroitoruP.'
(11113, a unei tabele de
, maniera
urmtoare:
ADRESA_TY('AL. T. Neculai ' , '112','Bl', 13) ) ;
CREATE TABLE test (tdata DATE) ;
Extragerea de informaii din tabele ce folosesc un tip, precum i
o instruciune
modificarea INSERT
valorilor SQL validfurnizarea
presupun ar fi (observai utilizarea
adresei apostrofurilor
complete,
chiar dac
conform tipul este DATE):
schemei/ierarhiei (vezi figura4.2): AliasTabel.
AtributTabel. AtributTip
INSERT INTO test VALUES ( ' 12-FEB-98 );
92 Oracle. Ghidul dezvoltrii aplicaiilor profesionale
Crearea tabelelor i definirea restriciilor91

unde TipElemente poate


SQL> SELECT fi L.Adresa.Strada
nune, scalar sau tip abstract.
FROM Ulterior,
locuitori L WHERE tipul HUME
cnp=11111;
astfel declarat poate fi utilizat la declararea atributelor unei tabele.
Vom considera o tabel SALARIAI al ADRESA.STRADA
crei atribut ZileLucr^g va
stoca n fiecare nregistrare un vector
Fane C. CUG de 12 elemente pentru
numrul zilelor lucrate
DATA_T VP E de salariatul respectiv
DATA_L EN GT DATA_PRE n fiecare lun CA
CISI DATA_S a unui
an. A H 0 N L Etip-utilizator
M ARC N UMFigura
BER 4.2. Interogarea atributelor
22 definite pe baza unui0
N UM EPRE Atributele
Listing 4.1. UAR CHunui
Crearea definite
AR2 n tipul
vector cu mrime abstract pot lui
U0i utilizarea
variabil fi ntr-o
incluse i n clauza
tabel WHERE
N M PART a unei
C0 UAR CH AR2 5
fraze SELECT SQL (figura 4.3).
DATASU DATE TYPE Zile_TY AS VARRAY(12) OF INTEGER
CREATE OR REPLACE 7
SALOR/ AR N UM BER 22 16 2
SALOR ARC SQL>
CREATE TABLE N UM BER
salariai ( 22
SELECT nune FROM locuitori L WHERE L.Adresa.Strada-'CUG' ; 16 2
O
COL A BOR CH AR
Nume VARCHAR2(50), 1
ATOR zilelucr ZILE_TY);
NUME

Fane C.
INSERT INTO salariai VALUES ('Atomei Maria', Zile_TY(22.21,20,22,23));
Handache U.
Extragerea datelor
SQL> UPDATE locuitori L SETntr-o form lizibil
L.Adresa.Strada-'G.Enescu* necesit utilizarea
WHERE L.Adresa.Strada-CUC 2 rows updated.
funciei TABLE () ce preia ca argument atributul de tip vector i
SQL> SELECT FROM locuitori;
genereaz, ca rezultat al interogrii, cte o nou linie pentru
CMP HUME
fiecare element cruia i s-a atribuit o valoare (chiar i NULL).
Elementele neiniializate
ADRESA(STRAOA, NUMR, BLOC, OP) sunt ignorate. Figura 4.4 prezint
interogarea
11111 tabelei,
Fane C. mai nti dup formatul standard, apoi
ADRESAJTVCG.
SQL> SELECT Enescu', '22 data_type,
column_nawe, BIS'. 'A5', 13) datalength, dataprecision, datascale
2 FROM user_tab_columns
11112 Handache U.
3 WHERE ADRESA_TV('G.
table_naneEnescu, '22 BIS', 'AS', 13)
= 'PERSONAL'
4 / 11113 Croitoru P.
AORESA_TV('AL. T. Neculai', '112', B1', 13)

Figura 4.3. Modificarea valorilor stocate n atributele tipurilor abstracte i


interogri
pe baza acestora
Comanda dedicat tergerii unui tip este DROP TYPE DenumireTip,
iar cea de modificare: ALTER TYPE DenumireTip.
Atenie! Este obligatorie utilizarea unui alias (sinonim) pentru
reuita interogrii i actualizrii atributelor definite n tipul
abstract de date; n caz contrar, vom obine un mesaj de
eroare ORA-00 904: invalid column nane. U n t i p u t i l i z a t d e
o t a b e l n u p o a t e fi t e r s '

4.2.3. Colecii
Coleciile sunt seturi de date ce pot fi tratate ca parte a unei singure
nregistrri dintr-o tabel. Exist dou astfel de tipuri de date:
vectori cu mrime variabil '(varying arrays) i tabele ncapsulate
(nested tables). Un vector cu mrime variabil se declar astfel:
CREATE OR REPLACE TYPE <Tip> AS VARRAY ( 12 ) of <TipElemente>
94 Crearea tabelelor i definirea restriciilor
Oracle. Ghidul dezvoltrii aplicaiilor profesionale 93

UPDATE salariai
Adugarea unor nregistrri
SET zilelucr noi n tabela
= Zile_TY(20,22, Compartiment se realizeaz
18,22,20,22,20,22,20,21,22,22)
folosind notaia:
WHERE nume = ' Atomei Maria' ;
NumeTipTabelalncapsulata (NumeTipElement (valAtribl, ....))
Tablourile (Tabelele) ncapsulate reprezint un alt tip de colecie
Ca urmare,
care, spre adugarea
deosebire compartimentului
de vectori, poate Financiar
stoca uncu doi nelimitat de
numr
salariai se va realiza
elemente i ofer astfel:
posibilitatea actualizrii directe a unui anumit
element. Aa cum sugereaz i numele, un tablou ncapsulat
INSERT INTO compartiment VALUES ( 'Financiar',
presupune existena unei tabele sub forma unui atribut al altei
SALARIATI_NT (
tabele. Colecia se declar
SALARIAT_TY('PredaT. astfel: ,
', 2000000)
SALARIAT_TY('Nistor
CREATE OR REPLACE TYPE A. <tip>
' , 2300000)
AS TABLE OF <T-ipElemente>
)
Exemplificm ) ; utiliznd un tip abstract de date, i anume
Salariat_TY, care pstreaz informaii despre un angajat. De
Extragerea datelor presupune utilizarea funciei THE cu formatul:
asemenea, vom defini n tabela COMPARTIMENT un atribut de tip
tablou ncapsulat care va stoca elemente de tip angajat (Salariat
THETY) pentru
(Select fiecare compartiment
<atributTipTabela> fromn<tabelaParinte>)
parte.
ce are rolul Listing 4.2. Tabelnregistrrile
de a aplatiza" ncapsulat definit din tabela pe ncapsulat
baza unui tip iabstract
Null? Type
de a le prezenta
CREATE TYPE sub form
Salariat_TY ASde linii( ca rezultat al interogrii tabelei
OBJECT
OWNERprinte (vezi Nume VARCHAR2(30),
figura 4.7). NOT NULL UARCHAR2(30)
Salariu NUMBER(16,2)
CONSTRAINT
SQL> dese NAME )userconstraints NOT NULL UARCHAR2(30)
CONSTRAINT TVPE / UARCHAR2(1)
TABLE NAME CREATE TYPE SalariatLNT AS TABLE OF SalariatJTY NOT/ NULL UARCHAR2(30)
SEARCH CONDITION CREATE TABLE compartiment ( LONG
R OWNER DenComp VARCHAR2(30), UARCHAR2(30
R CONSTRAINT Salariai
NAME SALARIATI_NT )
UARCHAR2(30
) NESTED TABLE Salariai STQRE AS salariatLnt_tab;____________________________________________
DELETE RULE )
UARCHAR2(9)
STATUS UARCHAR2(8)
DEFERRABLE n listingul de mai sus, la definirea tabelei COMPARTIMENT vom
UARCHAR2(1*
DEFERRED observa o extensie a instruciunii CREATE TABLE, 0 i anume :
UARCHAR2(9)
UALIDATED UARCHAR2(13
GENERATED NESTED TABLE <NumeAtribut> STORE AS <NumeTabelaDeStocare>
)
UARCHAR2( 1
BAD **)
UARCHAR2(3)
RELV Aceast extensie
Figura 4.4. Utilizarea se TABLE
funciei datoreaz() pentrufaptului
interogarea c elementele atributului
coleciilor
UARCHAR2(4)
LAST CHANGE Salariai sunt stocate sub forma unei tabele DATE clasice (vezi figura
INDEXDei
OWNER un
4.6), piccomplet
mai complicat,
separat, un cu vectornumelepoate fi interogat
UARCHAR2(30
precizat numai
n clauza STORE AS.
dup anumite valori (apelm la o subinterogare
INDEX NAME Aceast tabel nu poate fi accesat direct. UARCHAR2(30 n
) clauza FROM,
dup cum urmeaz - vezi figura 4.5);
INUALID )
UARCHAR2(7)
UIEW RELATED SQL> / UARCHAR2(1U
INSERT
MARCA |NUMEPREN INTO |DATAS___________
CQMPART personal (numepren) SALORAR jSALORARCO )fl2')
UflLUES |(COLABORATOR
, j
101 Al * ' PROD 1/24/2003 12:35:57PM 45000 40000 N
ERROR at line 1:
ORA-01400: cannot insert NULL into
(,,F0TflCHEM . Interogare
,, ,,
Figura 4.5. PERS0NflL dup,Vun
,
l1flRCA ,
) al vectorului
anumit element

O limit a acestuiFigura
tip de colecie ine
4.6. Modul dede imposibilitatea
stocare adugrii
al valorilor unei tabele
1
ncapsulate
sau actualizrii valorilor din vector altfel dect prin nlocuirea
ntregului vector cu altul nou:
1. Preluat din documentaia Oracle.
Oracle. Ghidul dezvoltrii aplicaiilor profesionale 95

n final, figura 4.8 prezint un exemplu de interogare dup


valorile atributelor tipului abstract (Salariat TY) stocat n tabela
ncapsulat i un exemplu de actualizare a liniilor din tabela
ncapsulat.
SQL> dese uset'_cons_colunns
Kme Null? Type

OWNER NOT NULL


CONSTRAINT_NAM UARCHAR2(30)
E TABLE_NAME NOT NULL
COLUMN_NAME UARCHAR2(30)
POSITION NOT NULL
UARCHAR2(30)
Figura 4.8. Interogarea i actualizarea tabelelor ncapsulate

Pentru a aduga o nou nregistrare n tabela ncapsulat


utilizm aceeai funcie THE (), astfel:

INSERT INTO
THE (SELECT salariai
FROM compartiment WHERE dencomp=' Financiar' )
NT VALUES(SALARIAT TY(Amariei V. ,2000000));

4.3. Formatul simplu al comenzii SQL CREATE


TABLE. Valori implicite
Pentru crearea unei tabele i declararea atributelor acesteia, fr
nici o referire la restricii i valori implicite, comanda CREATE TABLE
are, n cazul tabelei PERSONAL, urmtoarea form:
CREATE TABLE personal
( marca INTEGER ,
numepren VARCHAR2 (40)
, compart VARCHAR2 (5)
, dataSV DATE , salorar
NUMBER(16, 2)
, salorarco NUMBER(16,2)
, colaborator CHAR(l)
);
Dat fiind c marca este un numr atribuit secvenial la angajarea
fiecrui om al muncii, pentru atributul Marca s-a ales tipul INTEGER.
Salariile orare curente i pentru calculul indemnizaiei pentru
concediul de odihn ar fi trebuit s fie tot ntregi. Cum ns discuiile
despre leul greu revin periodic n actualitate, ne-am gndit c, prin
tierea celor
Figura 4.7. patru
Interogarea de zero,
tabelelor ce coninoatribute
s fie nevoie
de tip i de zecimale, iar
tabela ncapsulat
expresia De doi bani" nu o s mai aib conotaii att de derizorii.
Este motivul principal pentru care tipul celor dou atribute, SalOrar
i SalOrarCO, a fost ales NUMBER.
96 Crearea tabelelor i definirea restriciilor

CONSTRAINT NAME COLUMN NAME POSITION

NN_PERS0NAL_C0LAB0RAT0R COLABORATOR
NNPERSONALDAT ASU COMPART
NNPERSONALMARCA MARCA
NNPERSONALNUMEPREN NUMEPREN
PK_PERSONAL MARCA 1
UN PERSONAL NUEMPREN NUMEPREN 1

Figura 4.9. Informaii (prea) generoase despre tabelele bazei

Tipul DATE este inevitabil n cazul atributului folosit pentru a


determina anii de vechime (n munc) ai angajatului, ns pentru
colaborator ar fi fost mai normal s alegem un tip LOGICAL sau
BOOLEAN. Curios, Oracle nu poate gestiona n tabele acest gen de
date, aa c am recurs la tipul caracter - CHAR(l). NumePren i
Compart prezint variaii mari de lungime, de la angajat la angajat,
aa c au fost declarate VARCHAR2.
n dicionarul de date Oracle, o parte dintre informaii se gsesc
n tabela sistem USER_TABLES, cu structura din figura 4.9, obinut
n SQL*Plus prin comanda DESCRIBE. Pentru moment, singura
informaie care ne va interesa este numele tabelei. Restul - dup ce
vom ti ceva mai multe despre administrarea bazelor de date.
Putem afla numele tuturor tabelelor din baz prin interogarea:

SELECT table_name
FROM user_tables ;

O alt tabel virtual a dicionarului din care pot fi extrase


numele tabelelor este USER_OBJECTS:

SELECT object_name
FROM user_objects
WHERE object_type = 'TABLE' ;

Pentru a afla detalii despre atributele unei tabele, este necesar


consultarea unei alte tabele a dicionarului de date - USER_TAB
SQL> INSERT INTO personal (marca, numepren) UALUES (161, 'A1') ;

1 row created.
SQL> INSERT INTO personal (marca, numepren) UALUES (101, *A2') ;
INSERT INTO personal (marca, numepren) UALUES (101, A2a)
*
ERROR at line 1:
ORA-OO0Q1: unique constraint (F0TACHEM.PK_PERS0NAL) violated

Figura 4.10. Detalii despre atributele tabelelor


-I

Oracle. Ghidul dezvoltrii aplicaiilor profesionale 97

i n acest caz datele furnizate sunt cu mult peste ceea ce putem gestiona
n acest moment. Cel mai frecvent ne intereseaz numele, tipul, lungimea,
precizia (pentru atribute numerice) i numrul de poziii fracionare (pentru
atributele numerice) ale cmpurilor, ceea ce, n cazul tabelei PERSONAL,
presupune execuia unei frazei SELECT i afiarea unui rezultat ca n figura
4.11.
CONSTRAINT NAHE TABLE NAHE SEARCH CONDITION

NHPERSONALHARCA PERSONAL "HARCA" IS HOT NULL


t4_PERS0NAL_NUHEPREN PERSONAL "NUHEPREN' IS NOT NULL
NN_PERSONAL_DAT ASO PERSONAL "DATASU" IS NOT NULL
NN_PERSOHAL_COLABORATOR PERSONAL "COLABORATOR IS NOT NULL
CK_PERSONAL_HARCA PERSONAL narca > 180
CK_PERSONAL_HUHEPREN PERSONAL nunepren-LTRIN(INITCAP(nunepren))
CK_PERSONAL_COHPART PERSONAL conpart in ( *C0NTA*. *FIN*. *PERS*, HARK,PROD', 'IT* )
CK_PERSONAL_COLABORATOR PERSONAL colaborator IN ('D'.'N')
HN_PONTAJE_HARCA PONTAJE "HARCA" IS NOT NULL
NN PONTAJEDATA PONTAJE "DATA" IS NOT NULL
CK~POHTAJE_DATA PONTAJE TO_CHAR(data,' VVVV' ) BETWEEN *2003' ANO *2010*
CK_PONTAJE_ORELUCRATE PONTAJE orelucrate BETWEEN B AND 12
CK_P0NTAJE_0REC0 PONTAJE oreco BETWEEN 0 AND 8
CK_P0NTAJE1
CK_P0NTAJE2
PONTAJE
PONTAJE
(orelucrate * 0 AND oreco >=0) OR (orelucrate >=i AND oreco
orelucrate >* orenoapte
0)
CK PONTAJE3 PONTAJE orelucrate > oreabsnen

Figura 4.11. Obinerea de informaii despre atributele tabelei


PERSONAL
n conformitate cu standardele SQL, declararea valorilor implicite pe care
le poate lua un atribut atunci cnd, la inserarea unei linii, nu se specific
valoarea atributului respectiv presupune utilizarea clauzei DEFAULT.

CREATE TABLE personal


( marca NUMBER(5)
, numepren VARCHAR2 ( 4 0 )
, compart VARCHAR2 (5) DEFAULT PROD '
, dataSV DATE DEFAULT SYSDATE , salorar
NUMBER ( 1 6 , 2 ) DEFAULT 45000 , salorarco
NUMBER ( 1 6 , 2 ) DEFAULT 40000 ,
colaborator CHAR(l) DEFAULT 'N'

);
" I
4 Executat dup comanda de mai sus, comanda INSERT urmtoare;

INSERT INTO personal (marca, numepren) VALUES ( 1 0 1 , ' A l ' ) ;


va aduga n tabel nregistrarea din figura 4.12.

C0NSTRAINT_NAME TABLENAME R_C0NSTRAINT JJAME


FKP0NTAJEPERS0NAL P0NTAJE PKPERS0NAL
Figura 4.12. nregistrare cu (multe) valori implicite
Spre deosebire de versiunile precedente, Oracle 9i permite
declararea datei i a orei curente drept valoare implicit. Nu pot fi
ns declarate n clauza DEFAULT
98 Crearea tabelelor i definirea restriciilor

nume de funcii stocate (facilitate existent, spre exemplu, n


Visual FoxPro) sau fraze SELECT, Atunci cnd valorile implicite
trebuie calculate prin expresii mai complexe, se folosesc
declanatoarele (de tip AFTER INSERT ROW), dup cum vom vedea
intr-un alt capitol.

Se mai cuvine amintit, n treact, o alt comand, cel puin la


fel de ndrgit precum CREATE TABLE, i anume DROP TABLE. Dup
cum bine i zice numele, DROP TABLE terge o tabel din baza de
date. Paragrafele urmtoare vor fi presrate cu multe comenzi de
tergere, n vederea re-crerii tabelelor.
De asemenea, o tabel Oracle poate fi creat i pe baza unei
interogri SQL. Pentru exemplificare, crem o copie a tabelei
personal cu un nume destul de sugestiv - COPIE.PERSONAL:
CREATE TABLE copie_personal AS
SELECT * FROM personal

Noua tabel va prelua toate atributele din PERSONAL, nu ns i


restriciile (cu excepia valorilor nenule).
Dei nu se leag neaprat de subiectul crerii de tabele, merit
amintit c n Oracle 9i o tabel poate fi redenumit. Astfel, dac
vrem s schimbm numele proaspetei tabele din COPIE_PERSONAL
n PERSONAL_IAN2003, putem lansa comanda RENAME astfel:

RENAME copie_personal TO personal_ian2003

Tot n categoria comezilor DDL (Data Definition Language) se


ncadreaz i TRUCATE TABLE. La prima vedere este curioas
ncadrarea acestei comenzi n categoria DDL, ct vreme principala
sarcin a sa este tergerea tuturor liniilor (din acest punct de
vedere, DELETE FROM tabel are acelai efect). Spre deosebire de
DELETE FROM, TRUNCATE elibereaz i spaiul ocupat de nregistrrile
terse. Sporul de productivitate are i un pre: TRUNCATE nu poate fi
folosit ntr-o tranzacie, aa nct sunt cu neputin de recuperat

4.4. Valori nenule: clauza NOT NULL


ncepem detalierea restriciilor definibile n Oracle cu una dintre
cele mai simple clauze, NOT NULL. Pentru unele atribute se poate
institui obligativitatea precizrii unei valori, att la inserare, ct i
la modificare. Conform teoriei relaionale, cmpurile ce alctuiesc
cheia primar nu trebuie s prezinte valori nule. Pentru aceasta, la
crearea tabelei sau la modificarea structurii sale, se folosete
opiunea NOT NULL pentru atributul respectiv.
Rescriem comanda de creare a tabelei PERSONAL, interzicnd
apariia de valori nule pentru atributele Marca, Numepren, Compart i
Oracle. Ghidul dezvoltrii aplicaiilor profesionale 99

CREATE TABLE personal (


marca NUMBER {5) NOT NULL , numepren VARCHAR2
( 4 0 ) NOT NULL , compart VARCHAR2 (5) DEFAULT
'PROD' NOT NULL , dataSV DATE DEFAULT SYSDATE ,
salorar NUMBER ( 1 6 , 2 ) DEFAULT 4 5000 , salorarco
NUMBER ( 1 6 , 2 ) DEFAULT 4 0000 , colaborator
CHAR(l) DEFAULT 'N' NOT NULL ) ;

Inserarea unei linii n care nu se precizeaz valorile atributelor


nenule se soldeaz cu un mesaj de eroare de genul celui din figura
4.13.

SQL> ALTER TABLE pontaje DR0P C0LUMN orelucrate ;


ALTER TABLE pontaje DR0P C0LUMN orelucrate
*
ERR0R at line 1:
ORA-12991: colunn is referenced in a multi-column constraint

Figura 4.13. nclcarea restriciei de nenulitate

Aflarea posibilitii sau imposibilitii primirii de valori nule


pentru fiecare atribut al tabelei PERSONAL presupune execuia
interogrii:

SELECT column_name, nullable


FROM user_tab_columns
WHERE table_name = 'PERSONAL' ;

4.5. Chei primare i alternative: clauzele


PRMARY KEY i UNIQUE
Cheia primar a unei relaii, cea care identific fr ambiguitate
oricare linie a tabelei, este declarat prin clauza PRIMARY KEY,
plasat fie imediat, dup atributul cheie, fie dup descrierea
ultimului atribut al tabelei. A doua variant este ntrebuinat cu
precdere atunci cnd cheia primar a tabelei este compus. Pentru
atributele de tip cheie candidat se poate folosi clauza UNIQUE, care
va asigura respectarea unicitii valorilor. Scriptul din listing 4.3 re-
creeaz tabelele PERSONAL i PONTAJE. Tabela PERSONAL are drept
cheie primar atributul Marca, n timp ce cheia primar a tabelei
PONTAJE este una compus: (Marca, Data).
100 Crearea tabelelor i definirea restriciilor

Listing 4.3. Declararea cheilor primare i alternative

DROP TABLE pontaje ;


DROP TABLE personal ;

CREATE TABLE personal (


marca INTEGER NOT NULL PRIMARY KEY . numepren
VARCHAR2(40) NOT NULL UNIQUE , compart
VARCHAR2(5) DEFAULT 'PROD' NOT NULL , dataSV DATE
DEFAULT SYSDATE , salorar NUMBER(16,2) DEFAULT
45000 , salorarco NUMBER(16,2) DEFAULT 40000 ,
colaborator CHAR(1) DEFAULT N' NOT NULL );

CREATE TABLE pontaje (


marca INTEGER NOT NULL , data DATE
DEFAULT SYSDATE NOT NULL , orelucrate
NUMBER(2) DEFAULT 8 , oreco NUMBER(2)
DEFAULT 0 , orenoapte NUMBER(2) DEFAULT 0
, oreabsnem NUMBER(2) DEFAULT 0 , PRIMARY
KEY (marca,data)
):
__________________________________________________

Ca i cheia primar, o cheie alternativ poate identifica o linie a


tabelei din care face parte, altfel spus nu exist dou nregistrri n
tabel n care valoarea atributului (atributelor) care o alctuiete
(alctuiesc) s se repete. De multe ori, o tabel poate avea mai
multe chei candidate. Administratorul bazei alege numai una drept
cheie primar, celelalte devenind chei alternative. Alegerea se
bazeaz pe criterii precum: compoziie minimal, uurin n
folosire, lungime, stabilitate n timp, n vreme ce altele, precum
pile, relaii, trafic de influen sunt mult mai puin frecvente dect
n viaa de zi cu zi. Rolul de cheie alternativ l are, cel puin
deocamdat, atributul NumePren n PERSONAL.
Dicionarul bazei pstreaz informaii despre restricii ntr-o
tabel virtual special numit USER_CONSTRAINTS a crei
C0NSTRAINT_NANE TABLENAME SEARCHCONDITION

CKP0NTAJE ORELUCRATE PONTAJE orelucrate BETWEEN 0 AND 12


CK_P0NTAJE1 PONTAJE (orelucrate 0 AND oreco >-0) OR (orelucrate >-fl AND oreco - 0)
CK_P0NTAJE2 PONTAJE orelucrate >- orenoapte
CK_P0NTAJE3 PONTAJE orelucrate >- oreabsnem

Figura 4.14. Detalii despre restricii

Pentru a afla dac o tabel are declarat cheia primar i/sau


chei alternative, se poate recurge la atributul constraint_type care,
pentru chei primare, are valoarea T', iar pentru chei alternative
(unice) 'U'. Pentru a ne referi la o restricie anume, ar trebui s-i
tim numele (constraint name). Folosind scriptul de mai sus, fiecare
restricie are un nume sistem, generat automat, cum ar fi
SYS_C003200. La un numr mai mare de tabele, atribute i
Oracle. Ghidul dezvoltrii aplicaiilor profesionale 101

aceste nume criptice, aa c muli profesioniti folosesc clauza


CONSTRAINT pentru a atribui un nume explicit fiecrei restricii.
Pentru exemplificare, listingul 4.4 este o nou prezentare a
precedentului, dar cu nume sugestive pentru fiecare restricie.
Listing 4.4. Botezarea" restriciilor
DROP TABLE pontaje ;
DROP TABLE personal ;

CREATE TABLE
personal ( marca
INTEGER
CONSTRAINT pk_personal PRIMARY KEY
CONSTRAINT nn_personal_marca NOT
NULL , numepren VARCHAR2(40)
CONSTRAINT nn_personal_numeoren NOT
NULL CONSTRAINT un_personal_nuempren
UNIQUE . compart VARCHAR2(5) DEFAULT 'PROD'
, dataSV DATE DEFAULT SYSDATE
CONSTRAINT nn_personal_datasv NOT NULL ,
salorar NUMBER(16,2) DEFAULT 45000 ,
salorarco NUMBER(16,2) DEFAULT 40000 ,
colaborator CHAR(1) DEFAULT N'
CONSTRAINT nn_personal_colaborator NOT
NULL );

CREATE TABLE pontaje ( marca INTEGER


CONSTRAINT nn_pontaje_marca NOT NULL ,
data DATE DEFAULT SYSDATE
CONSTRAINT nn_pontaje_data NOT NULL ,
orelucrate NUMBER(2) DEFAULT 8 . oreco
NUMBER(2) DEFAULT 0 . orenoapte NUMBER(2)
DEFAULT 0 , oreabsnem NUMBER(2) DEFAULT 0 ,
CONSTRAINT pk_pontaje PRIMARY KEY
(marca,data) );___________________

Ne uurm lucrul folosind o notaie pseudo-ungureasc" (dup


modelul programrii vizuale), adic prefixnd numele fiecrei
restricii cu:
pk_ (PRIMARY KEY) pentru cheile primare;
un_ (UNIQUE) pentru cheile alternative;
nn_ (NOT NULL) pentru atributele obligatorii (ce nu pot avea valori
nule);
ck_ (CHECK) pentru reguli de validare la nivel de atribut sau
nregistrare;
f k_ (FOREIGN KEY) pentru cheile strine.

Revenind la dicionarul de date, tabela USER_CONSTRAINTS


ofer informaii cuprinztoare cu privire la restriciile definite pe
fiecare tabel din baz. Pentru a afla atributele ce fac parte din
102 Oracle. Ghidul dezvoltrii aplicaiilorCrearea
profesionale 103
tabelelor i definirea restriciilor

SQL> ALTER TABLE personal MODIFY compart UARCHAR2(2)


2 /
ALTER TABLE personal MODIFY compart UARCHAR2(2)

ERROR at line 1:
OR A-01441: cannot decrease column length because some value is
too big
Figura 4.15, Atributele incluse n restricii
Oprindu-ne la tabela PERSONAL, aflarea atributelor declarate n
toate restriciile este posibil prin fraza SELECT:

SELECT constraint_name, column_name, position


FROM user_cons_columns WHERE table_name = '
PERSONAL'

rezultatul (n SQL*Plus) fiind cel din figura 4.16. Coloana Position


prezint interes la restriciile de unicitate care au cheia compus i
indic poziia fiecrui atribut n cadrul cheii (indexului).

SQL> ALTER TABLE personal DROP PRIMARY KEY


2 /
ALTER TABLE personal DROP PRIMARY
KEY *
ERROR at line 1:
ORA-02273: this unique/primary key is referenced by some Foreign
keys
Figura 4.16. Restricii i atribute pentru tabela
PERSONAL
Astfel, dac dorim s aflm componena cheii primare a tabelei
PONTAJE, al crei nume l cunoatem - PK PONTAJE putem recurge la
interogarea urmtoare, al crei rezultat este cel din figura 4.17:

SELECT constraint_name, column_name, position


FROM user_cons_columns
WHERE constraint__name = ' PK_PONTAJE'

C re_creare_tabele - Notepad
CONSTRAINT NANE COLUMN NAME POSITION
I Frie dit Format View Help
PK_P0NTAJE MARCA 1
1 PK_P0NTAJE C2DATA 2 a
ci

CREATE TABLE PERSONAL ( Figura 4.17. Componena


--PERSONAL cheii primare a tabelei
MARCA NUMBER ( 5) PONTAJE PERSONAL i
.NUMEPREN VARCHAR2 ( 40) --PERSONAL 2
,COMPART VARCHAR2 ( 5) --PERSONAL
,DATASV DATE (7) La ncalcrea restriciilor de cheie primar i de unicitate,
--PERSONAL
3
4
se
,SALORAR NUMBER (16. 2)
declaneaz o eroare de genul celei din figura 4.18.
,SALORARCO NUMBER ( 16, 2)
--PERSONAL
--PERSONAL
5
6
.COLABORATOR CHAR (1) PERSONAL 7
); --PERSONAL {
CREATE TABLE PONTATE ( --PONTAJE
MARCA NUMBER ( 5) --PONTAJE 1
,DATA DATE (7) --PONTAJE 2
ORELUCRATE NUMBER ( 2) --PONTAJE 3
,ORECO NUMBER ( 2) --PONTAJE 4
.ORENOAPTE NUMBER ( 2) --PONTAJE 5
,OREABSNEM NUMBER ( 2) --PONTAJE 6
); --PONTAJE {V>

<
104 Oracle. Ghidul dezvoltrii aplicaiilor Crearea tabelelor i definirea restriciilor
profesionale 105

Spre deosebire
. CONSTRAINTdepk^oontaie
restriciile
PRIMARYlaKEYnivel de cmp, cele la nivel de
(marca,data)
nregistrare privescck_pontaje1
, CONSTRAINT simultan dou
CHECK sau mai
((orelucrate = 0 multe atribute.
AND oreco >=0) OR n plus,
(orelucrate >=0 AND oreco = 0))
momentul verificrii lor succed verificrii regulilor la nivel de
, CONSTRAINT ck_pontaje2 CHECK (orelucrate >= orenoapte)
atribut. Tabela PONTAJE prezint trei
, CONSTRAINT ck_pontaje3 CHECK (orelucrate >= oreabsnem)
asemenea restricii:
);
/
_________________________________________________________________
C K P O N TA J E 1 , potrivit creia un angajat este ori n concediu
Aflarea regulilor de validare la nivel de atribut i nregistrare din
(orelucrate = 0 AND oreco >=0), ori la lucru (orelucrate >=0 AND
tabelele PERSONAL i PONTAJE presupune folosirea consultrii:
oreco = 0 ) ;
CKSELECT
PONTAJE2, dup care untable_name,
constraint_name, angajat nu search_condition
poate avea numrul deuser_constraints
FROM ore de
noapte
WHEREsuperior numrului
table__name IN (orelor totale lucrate
' PERSONAL' n ziua
, ' PONTAJE' ) respectiv
(orelucrate >= orenoapte);
AND constraint_type = 'C'
CK PONTAJE3, prin care se evit eroarea de a avea mai multe ore de absene
Rezultatul n SQL*Plus este cel din figura 4.19.
TABLE_HAME SEARCHC0N0ITI0N

HH PERSONAL MARCA Listingul 4.5 conine


PERSONAL clauzele definirii acestor noi restricii.
"MARCA" IS NOT NULL

NN PERSONAL NUMEPREN PERSONAL "NUMEPREN" IS NOT NULL


NN PERSONAL DATASU Listing 4.5.
PERSONAL "DATASU"Reguli
IS HOT NULL de validare la nivel de atribut i nregistrare
NN PERSONAL COLABORATOR PERSONAL Figura 4.18.
"COLABORATOR" IS NOT NULLnclcarea restriciei (cheie primar) PKJPERSONAL
CK PERSONAL MARCA PERSONAL narea >100
DROP TABLE
CK PERSONAL NUMEPREN
pontaje ; nunepren-LTRIM(I NITCAP(nunepren))
PERSOHAL
CK PERSONAL COMPORT De
DROP TABLE remarcat
personal
PERSONAL
; i faptul
conpart in ( CONTA 1 c,
, 'FIN-. 'PERS', * MARK la 'IT'declararea
restriciilor de tip cheie
*,PROD, )
CK PERSONAL COLABORATOR PERSONAL colaborator IN ('D'.N")
NN PONTAJE MARCA primar/unicitate,
CREATE TABLE
PONTAJEpersonal ( marca
"MARCA Oracle creeaz automat indeci corespunztori.
INTEGER
IS NOT MULL
NN PONTAJE DATA
CONSTRAINT
PONTAJE
pk_personal PRIMARY KEY CONSTRAINT nn_personal_marca
"DATA" IS NOT NULL
-
CK PONTAJE DATA PONTAJE TO CHAR(data,' VYYV ) BETWEEN ZOOS AND 2010
NOT
CK PONTAJE ORELUCRATE
NULL CONSTRAINT
PONTAJE
ck_personal_marea CHECK ( marca >= 100 )
orelucrate BETWEEN 0 AND 12
CK PONTAJE ORECO
CK P0HTAJE1 4.6. Reguli de validare la nivel de atribut i
, numepren
PONTAJEVARCHAR2(40)

CONSTRAINT
PONTAJE
oreco BETWEEN 0 AND 8

nn_persQnal
(orelucrate numepren
- 0 AND oreco NOT
>-) OR (orelucrate NULL
>=0 AND oreco CONSTRAINT
0)

nregistrare: clauza CHECK


CK P0NTAJE2 PONTAJE orelucrate > orenoapte
CK P0NIAJE3
un_personal_nuempren
PONTAJE
UNIQUE CONSTRAINT
orelucrate >- oreabsnen
ck_personal_numepren
CHECK (numepren=LTRIM(INITCAP(numepren)))
, compart VARCHAR2(5) DEFAULT 'PROD'
Restriciile-utilizator,
CONSTRAINT ck_personal_compart denumite i restricii de comportament, sunt
implementate CHECK (compart subin ('CONTA\forma 'FIN', PERS, 'MARK'/PROD*,
regulilor de validare TT )) , dataSV
la nivel de cmp
DATE DEFAULT SYSDATE
( fiCONSTRAINT
e l d v ann_personal_datasv
lidation ru NOT l eNULL
) , ,la nivel
salorar de nregistrare ( r e c o r d
NUMBER(16,2)
v a l i d45000
DEFAULT a t i o, salorarco
n r u l NUMBER(16,2)
e ) sau, dac DEFAULT sunt
40000 ,mai complexe, sunt incluse n
colaborator
CHAR(1) DEFAULT *N'
declanatoare (t r i g g e r e ).
CONSTRAINT nn_personal_colaborator NOT NULL
CONSTRAINT ck_persona!_colaborator CHECK (colaborator IN ('D'/N'))
); Pentru tabela PERSONAL, instituim urmtoarele restricii la nivel
de atribut:
CREATE TABLE pontaje ( marca INTEGER
CONSTRAINT
atributul Marca nu poate
nn_pontaje_marca avea
NOT NULL valori
, data DATE mai mici de 100;
DEFAULT
pentru nume i prenume, prima liter din fiecare cuvnt
SYSDATE CONSTRAINT nn_pontaje_data NOT NULL CONSTRAINT ck_pontaje_data
CHECK (TO_CHAR(data,'YYYY') BETWEEN ^OOS'
(nume, iniiala AND 201
tatlui, O)
prenume) este majuscul; restul,
. orelucrate NUMBER(2) DEFAULT 8
obligatoriu, litere mici;
CONSTRAINT ck_pontaje_orelucrate CHECK (orelucrate BETWEEN 0 AND 12)
firmaDEFAULT
, oreco NUMBER(2) are numai
0 ase compartimente: CONTA (contabilitate),
CONSTRAINT ck_pontaje_oreco
FIN (financiar), BETWEEN
CHECK (oreco PERS0 AND (personal-salarizare),
8) MARK
, orenoapte NUMBER(2) DEFAULT 0
(marketing), PROD (producie), IT (sau
, oreabsnem NUMBER(2) DEFAULT 0___________________________________________
sisteme
informaionale).
atributul Colaborator poate avea doar dou valori, 'N' (Nu,
adic nu e colaborator, ci angajat cu carte de munc) i 'D'.

Pentru tabela PONTAJE, regulile de validare la nivel de cmp


sunt:
atributul Data s fie cuprins ntre 1 ianuarie 2003 i 31
106 Crearea tabelelor i definirea restriciilor

se va institui o restricie referenial ntre PONTAJE (tabel copil) i


PERSONAL (tabel printe), n virtutea creia Oracle va veghea
neabtut" ca:
s nu se tearg vreo nregistrare n PERSONAL (printe),
dac acel angajat are minimum un pontaj (o nregistrare
copil n PONTAJE);
n PONTAJE s nu apar vreo marc (fie printr-o inserare, fie
printr-o modificare) ce nu se regsete n PERSONAL.

Mai mult, se poate institui i regula tergerii n cascad (ON


DELETE CASCADE): la tergerea unui printe, se terg automat toi
copiii si (fr sentimentalisme, v rugm 1).

CREATE TABLE pontaj e


( marca INTEGER
CONSTRAINT nn_pontaje_marca NOT NULL
CONSTRAINT f k_pontaje_personal
REFERENCES personal (marca)
ON DELETE CASCADE

Sau, tot pentru a nu nclca restricia referenial, la tergerea unei


nregistrri printe, toate valorile copil pot fi trecute" pe NULL (ON
DELETE SET NULL):

CREATE TABLE pontaj e


( marca INTEGER
CONSTRAINT nn_ponta j e_marca NOT NULL
CONSTRAINT
Figura fk_jpontaje_personal
4.19. Restricii de tip CHECK pentru tabele PERSONAL i PONTAJE
REFERENCES personal (marca)
ON DELETE SET NULL
, data DATE DEFAULT SYSDATE
4.7. Restricii refereniale
Cea mai rezonabil// opiune este cea implicit, care interzice
tergerea unei nregistrri printe, att timp ct exist mcar un
Restriciile refereniale constituie, probabil, categoria care d cele
copil (un soi de ON DELETE RESTRICT).
mai mari bti de cap SGBD-urilor, din zorii bazelor de date
Din pcate, nici n Oracle 9i nu apare clauza ON UPDATE CASCADE.
relaionale pn n prezent. Oracle ns se comport onorabil,
Astfel nct, la modificarea valorii unei chei primare, aceasta
deoarece, folosind clauzele REFERENCES / FOREIGN KEY, se rezolv
trebuie modificat prin declanatoare n toate nregistrrile copil.
majoritatea problemelor refereniale. Astfel, dac formatul comenzii
Implicit, dup instituirea restriciei refereniale, n tabela printe
CREATE TABLE pentru PONTAJE este:
regula de modificare a cheii primare este ON UPDATE RESTRICT
(modificarea este interzis dac exist
CREATE mcar
TABLE pontaojenregistrare
( copil
pentru vechea valoare). marcaINTEGER
CONSTRAINT nn_ponta j e_marca NOT NULL
n dicionarul de CONSTRAINT
date, informaiile
fk_pontajdespre restriciile refereniale
e_personal
sunt pstrate tot n tabelele
REFERENCES USER_CONSTRAINTS
personal (marca) i
USER_CONS_COLUMNS. Fraza SELECT urmtoare afieaz coninutul
din figura 4.20.
Oracie. Ghidul dezvoltrii aplicaiilor profesionale 107

FROM user_constraints WHERE constraint_type = 'R1

CONSTRAINT NANE TABLE NANE R CONSTRAINT NANE

FK PONTAJE PERSONAL PONTAJE PK PERSONAL

Figura 4.20. Date despre restricia referential

Extragerea corespondenelor dintre atributele copil i cele


printe este o sarcin mai dificil i presupune execuia unei
fraze SELECT mult mai elaborate:

SELECT uc. constraint_name AS restrictie_copil, uccl.table_name


AS tabela_copil, uccl.column_name AS atribut_copil,
r_constraint_name AS restrictie_parinte, ucc2.table_name AS
tabela_parinte, ucc2.column_name AS atribut_parinte
FROM user_constraints uc, user_cons_columns uccl,
user_cons_columns ucc2
WHERE uc. constraint_name = uccl. constraint_name AND uc.
r_constraint_name = ucc2.con5traint_name AND uccl .position
= ucc2 .position AND uc.constraint_type= 'R'
ORDERBY uc.constraint_name, uccl.position

V invitm s o verificai, att acum, ct i dup lansarea


scriptului urmtor.

4.8. Scriptul de creare a tabelelor i declararea


restriciilor
Listingul 4.6 conine comenzile i clauzele necesare crerii
tabelelor i declarrii restriciilor pentru baza de date pe care
o vom utiliza n continuare. n afara observaiei c tabelele
SPORURI, REINERI i SALARII au chei primare compuse din
atributele Marca, An i Luna, credem c orice alt comentariu
este de prisos.
Listing 4.6. Definirea tabelelor/restriciilor
DROP TABLE transe_sv ;
DROP TABLE salarii ;
DROP TABLE reineri ;
DROP TABLE sporuri ;
DROP TABLE pontaje ;
DROP TABLE personal ;

CREATE TABLE personal (


marca INTEGER
CONSTRAINT pk_personal PRIMARY KEY CONSTRAINT
nn_personal_marca NOT NULL CONSTRAINT
ck_personal_marca CHECK ( marca > 100 )
, numepren VARCHAR2(40)
108 Crearea tabelelor i definirea restriciilor

CONSTRAINT un_persona(_numepren UNIQUE CONSTRAINT


ck_personal_numepren CHECK (numepren=LTRIM(INITCAP(numepren)))
, compart VARCHAR2(5) DEFAULT 'PROD'
CONSTRAINT ck_personal_compart CHECK
(compart in ('CONTA', 'FIN', 'PERS', 'MARK'/PROD', 'IT ))
, dataSV DATE DEFAULT SYSDATE
CONSTRAINT nn_personal_datasv NOT NULL , salorar NUMBER(16,2) DEFAULT
45000 , salorarco NUMBER(16,2) DEFAULT 40000 , colaborator CHAR(1) DEFAULT N'
CONSTRAINT nn_personal_colaborator NOT NULL
CONSTRAINT ck_personal_colaborator CHECK (colaborator IN ('D'.N'))
);
CREATE TABLE pontaje (
marca INTEGER
CONSTRAINT nn_pontaje_marca NOT NULL
CONSTRAINT fk_pontajepersonal REFERENCES personal (marca)
, data DATE DEFAULT SYSDATE
CONSTRAINT nn_pontaje_data NOT NULL CONSTRAINT ck_pontaje_data CHECK
(TO_CHAR(data,'YYYY ) BETWEEN 2003' AND '2010')
, orelucrate NUMBER(2) DEFAULT 8
CONSTRAINT ck_pontaje_orelucrate CHECK (orelucrate BETWEEN 0 AND 12)
, oreco NUMBER(2) DEFAULT 0
CONSTRAINT ck_pontaje_oreco CHECK (oreco BETWEEN 0 AND 8)
, orenoapte NUMBER(2) DEFAULT 0 , oreabsnem NUMBER(2)
DEFAULT 0 , CONSTRAINT pk_pontaje PRIMARY KEY (marca.data)
, CONSTRAINT ck_pontaje1 CHECK ((orelucrate = 0 AND oreco >=0) OR (orelucrate >=0 AND
oreco = 0))
, CONSTRAINT ck_pontaje2 CHECK (orelucrate >= orenoapte)
, CONSTRAINT ck_pontaje3 CHECK (orelucrate >= oreabsnem)
);
CREATE TABLE sporuri (
marca INTEGER
CONSTRAINT nn_sporuri_marca NOT NULL
CONSTRAINT fk_sporuri_personal REFERENCES personal (marca)
, an NUMBER(4)
CONSTRAINT nn_sporuri_an NOT NULL
CONSTRAINT ck_sporuri_an CHECK ( an BETWEEN 2003 AND 2010 )
, luna NUMBER(2)
CONSTRAINT nn_sporuriJuna NOT NULL
CONSTRAINT ck_sporuri_luna CHECK (luna BETWEEN 1 AND 12)
, spvech NUMBER(16,2)
, orenoapte NUMBER (3)
, spnoapte NUMBER (16,2)
, altesp NUMBER (16,2)
, CONSTRAINT pk_sporuri PRIMARY KEY (marca, an, luna)
);
CREATE TABLE retineri (
marca INTEGER
CONSTRAINT nn_retineri_marca NOT NULL
CONSTRAINT fk_retineri_marca REFERENCES personal (marca)
,an NUMBER (4)
CONSTRAINT nn retineri an NOT NULL _________ _______________
CONSTRAINT_NANE TABLENAHE SEARCH_C0NDITION

CK PONTAJE ORELUCRATE PONTAJE orelucrate BETWEEN 0 AND 12


CK PONTAJES PONTAJE (orelucrate - 0 ANO oreco >-) OR (orelucrate >-l! ANO oreco - 0)
GK PONTAJES PONTAJE orelucrate >- orenuapte
CK PONTAJES110
Oracle. Ghidul
PONTAJE
dezvoltrii aplicaiilor profesionale
orelucrate >- oreabsnen Crearea tabelelor i definirea restriciilor

CONSTRAINT ck_retineruan CHECK ( an BETWEEN 2001 AND 2012 J , luna


tergerea nu (2)
NUMBER era permis. Atributul pe care tocmai l-am adugat
poate fi ters astfel:nn_retinerijuna NOT NULL
CONSTRAINT
CONSTRAINT ck_retinerijuna CHECK (luna BETWEEN 1 AND 12)
ALTER, popriri
TABLE copie_personal
NUMBER (16,2) DROP COLUMN datanast
, CAR NUMBER (16,2)
, alteret NUMBER (16,2)
tergerea atributului Compart atrage dup
sine, cum este i
, CONSTRAINT pk_retineri PRIMARY KEY (marca, an, luna)
normal, );
tergerea restriciilor definite pentru acesta:
CREATE TABLE
ALTER TABLE copie_personal DROPsalarii (
COLUMN compart
marca INTEGER
CONSTRAINT nn_salarii_marca NOT NULL
Dac ns vomfk_sa!arii_personal
CONSTRAINT dori s eliminm atributul
REFERENCES personal (marca) OreLucrate din
PONTAJE, ,anavem
NUMBERtoate
(4) ansele s primim mesajul de eroare din figura
CONSTRAINT nn_salarii_an NOT NULL V
4.21.
CONSTRAINT ck_salarii_an CHECK ( an BETWEEN 2001 AND 2012 )
.
, luna NUMBER (2)
SQL>CONSTRAINT
ALTER nn_sa!arii_!una
TABLE pontaje NOT DROP
NULL COLUHN orelucrate ;
CONSTRAINT ck_salarii_luna
ALTER TABLE pontaje DROP COLUHN CHECK (luna BETWEEN 1 AND 12)
orelucrate
, orelucrate NUMBER (3)
, oreco
ERROR NUMBER (3) 1:
at line
ORA-12991:
, venitbaza NUMBER column
(16,2) is referenced in a multi-column constraint
.sporuri NUMBER (16,2)
, impozit NUMBER (16,2)
Figura 4.21.
, retineriTentativ de tergere a unui cmp ce apare ntr-o regul
NUMBER (16,2)
la nivel de nregistrare
, CONSTRAINT pk_sa!arii PRIMARY KEY (marca, an, luna)
Mesajul ); este limpede: nu putem terge n acest fel atributul
deoarece
CREATE apare ntr-o regul de validare la nivel de nregistrare.
TABLE transe_sv
( anijimitajnf INTEGER
Aflarea tuturor restriciile n care este implicat atributul OreLucrate
,ani_limita_sup INTEGER ,
e o operaiune destul de simpl:
procent_sv NUMBER (4,2)
*'?* "
_L____________________________________________
SELECT rl. constraint_name, rl.table_name,
search_condition FROM USER_CONF ZQLUMNS rl,
USER_CONSTRAINTS r2 WHERE rl. constraint_name = r2 .
4.9. constraint_name
Modificarea AND structru tabelelor:
column_name com
= ORELUCRATE'
fe?.
Schema reprezint aspectul constant, invariabil sau, mai bine zis,
putu timp al unei baze de date. Cu toate acestea, apariia unui
atribut nou, modil lungimii unui atribut sunt probleme de care orice
administrator/dezvoltator de aplicaii se ciocnete destui de
frecvent. Comanda SQL dedicat modificrii structurii bazei de date
este ALTER TABLE.
4.9.1. Adugri/Modificri/tergeri de atribute

Adugarea atributului DataNast (data naterii) n tabela COPIE.PERS


'JNAI, se realizeaz astfel:

ALTER TABLE copie_personal ADD datanast DATE

La prima vedere, tergerea unui cmp (posibil ncepnd cu


versiunea 8i) e la fel de simpl ca i adugarea. Aceasta n Oracle 9i,
deoarece n versiuni mai vechi
Oracle. Ghidul dezvoltrii aplicaiilor profesionale 111

De la Oracle 8i apare i o facilitate ce pare, la prima vedere, mai


exotic: declararea unei coloane (atribut) ca... nefolositoare. Cei de
la firma productoare s-au gndit probabil c, ntruct tergerea
unei coloane n condiiile existenei unui mare numr de utilizatori
ce lucreaz simultan cu tabela genereaz serioase blocaje, ar fi de
dorit ca, mai nti, coloana/coloanele s fie marcate ca inutilizabile,
iar apoi, ntr-un moment de respiro" al bazei, s se procedeze la
tergerea definitiv.

ALTER TABLE personal SET UNUSED (salorarco)


sau
ALTER TABLE personal SET UNUSED COLUMN salorarco

Din momentul declaraiei, atributul respectiv este ca i


inexistent, nemaiputnd fi invocat. Astfel, comanda:

INSERT INTO personal (marca, numepren, salorarco)


VALUES (102, 'A2', 45000)

va genera eroare. Eliminarea definitiv a tuturor atributelor


marcate" ca inutilizabile se realizeaz prin:
s.'

ALTER TABLE personal DROP UNUSED COLUMNS

Cum, dup marcare, nu exist nici un mod de a vizualiza/accesa


atributul respectiv n tabel, singura informaie pe care o avem n
dicionar este numrul total de atribute marcate n fiecare tabel,
afiabil prin interogarea:

SELECT * FROM USER_UNUSED_COL_TABS


4
* V~ v *"* * ;
* * * 14

Creterea numrului de caractere pentru un cmp nu e nici o


problem:

ALTER TABLE personal MODIFY compart VARCHAR2 (15.)

SQL> ALTERFigura 4.22. Restriciile


TABLE personal n careUARCHAR2(2)
NODIFV compart apare atributul OreLucrate
2/
Aadar, o prim
ALTER TABLE personalvariant ar fi UARCHAR2(2)
HODIFV compart s tergem mai nti toate
restriciile (ultimele trei cu * deosebire) i apoi s rencercm s
ERROR at line 1:
lansm comanda ALTER TABLE n formatul de mai sus. Se poate ns
ORA-61441: cannot decrease column length because some value is too big
i mai simplu, prin folosirea clauzei CASCADE CONSTRAINTS:
Figura
ALTER 4.23.
TABLETentativ de reducere
pontaje DROP COLUMN a lungimii atributului Compart
orelucrate CASCADE CONSTRAINTS
n Oracle, modificarea tipului unui atribut se poate face astfel:
Cu aceast
din CHAR nou clauz
n VARCHAR2 sau se poate terge
VARCHAR; orice atribut
din VARCHAR2 din orice
sau VARCHAR
tabel.
n CHAR,Efectul
dar numaipoate
dacfi,respectivul
pe alocuri, devastator,
atribut aa c nu
conine valoarea NULLe
recomandat
n toate liniileuitucilor cardiaci.
tabelei sau
112 Crearea tabelelor i definirea restriciilor

dac nu se modific i lungimea atributului. Pentru exemplificare,


transformm tipul atributului Compart din VARCHAR2(5) n CHAR(5):

ALTER TABLE personal MODIFY compart CHAR ( 5)

Pentru modificarea valorii implicite a unui atribut, n cazul nostru


Compart (din 'PROD' n 'IT'), formatul comenzii este:

ALTER TABLE personal MODIFY compart DEFAULT IT 1

Oracle 9i permite i redenumirea unui atribut:

ALTER TABLE personal RENAME COLUMN compart TO compartiment

4.9.2. Adugri/tergeri de restricii


Interzicerea valorilor nule pentru atributul SalOrar se realizeaz
astfel:

ALTER TABLE personal MODIFY salorar NOT NULL Invers, spre a

permite valori NULL pentru acelai atribut:


ALER TABLE personal MODIFY salorar NULL

Toate restriciile, adic valori nenule, cheie primar, unicitate,


reguli de validare, restricii refereniale, pot fi declarate i ulterior
crerii tabelelor i, bineneles, terse la un moment dat. n scriptul
de creare a tabelelor din baz, TRANSE_SV nu are mei o restricie.
Ceea ce nu nseamn c este prea trziu. Mai nti, instituim o
regul de validare la nivel de nregistrare, CK TRANSE SVl, care s
verifice c limita inferioar a tranei este strict mai mic dect
limita superioar:

ALTER TABLE transe_sv ADD CONSTRAINT ck_transe_svl CHECK


(ani_limita_inf < ani_limita_sup)

Iar dac vrem s facem atributul Ani_Limita_Inf cheie primar, nu ne


rmne dect s lansm n execuie:

ALTER TABLE transe_sv


ADD CONSTRAINT pk_transe__sv
PRIMARY KEY (ani_limita_inf)

Cunoscnd numele restriciei ce se dorete a fi tears, cum ar fi: CK


PER- SONAL_COLABORATOR, tergerea sa se poate realiza astfel:

ALTER TABLE personal


DROP CONSTRAINT ck_personal_eolaborator
Oracle. Ghidul dezvoltrii aplicaiilor profesionale 113

Ca i n cazul tergerii atributelor, nu n toate cazurile lucrurile


stau aa de simplu. Astfel, dac se dorete tergerea cheii primare a
tabelei PERSONAL, apare o opoziie din partea serverului, deoarece
atributul Marca apare ntr-o serie de restricii refereniale. Este
motivul pentru care se afieaz mesajul din figura 4.24.
SQL> ALTER TABLE personal DROP PRIMARY KEY
2/
ALTER TABLE personal DROP
PRIMARY KEY *
ERROR at line 1:
0RA-Q2273: this unique/primary key is referenced by some
foreign keys
Figura 4.24. Tentativ de tergere a cheii primare din PERSONAL

Dac am fi vrut s eliminm restricia de cheie primar a tabelei


SALARII, prin lansarea comenzii:

ALTER TABLE salarii DROP PRIMARY KEY


sau
ALTER TABLE salarii DROP CONSTRAINT p k s a l a r i i

nu am fi ntmpinat prea mare rezisten. Oracle nu se mpotrivete


tergerii restriciei PK PERSONAL, indiferent de cte alte restricii
refereniale depind de aceasta, dac folosim clauza CASCADE, prin
care se terg i toate restriciile ce depind de cea tears:

ALTER TABLE personal DROP PRIMARY KEY CASCADE

4.10. Restricii dezactivate, reactivate,


amnate, imediate
O serie de situaii, precum importul datelor din SGBD-uri mai simple,
ce nu prezint mecanisme de declarare a restriciilor de cheie
primar/unicitate, reguli de validare sau refereniale (ex. FoxPro
2.x), reclam dezactivarea temporar a unor restricii, efectuarea
importului (sau a altor operaiuni), verificarea consistenei i
integritii datelor, i numai dup aceea reactivarea restriciilor.
Varianta tergerii i re-crerii restriciilor nseamn un efort mult
mai mare din partea dezvoltatorilor de aplicaii sau administratorilor
bazei de date i, n plus, consum serioase resurse ale SGBD-ului,
lucru cu att mai evident cu ct tabelele simt mai stufoase.
Dezactivarea restriciei CK PONTAJEl asociat tabelei PONTAJE se
realizeaz folosind tot comanda ALTER TABLE n formatul:

Ulterior, reactivarea presupune execuia comenzii:


114 Oracle. Ghidul dezvoltrii aplicaiilor profesionale
Crearea tabelelor i definirea restriciilor
115

e ENABLE CONSTRAINT ckjpontaj el ;


ALTER TABLE pontaj
SQL> SELECT * FROM pontaje;
Analog tergerii de atribute i de restricii, dezactivarea simpl"
este ntmpinat cu ostilitate de Oracle dac de restricia
dezactivat depind alte restricii. Firete, cel mai la ndemn
exemplu este tot PK_PERSONAL:

ALTER TABLE personal DISABLE CONSTRAINT pk_personal

se soldeaz cu un mesaj de eroare (ORA-02297: cannot disable constraint


(PERSONAL. PK_PERSONAL) - dependencies exist). Soluia ine de folosirea
clauzei CASCADE.

Mai trebuie amintit faptul c activarea obinuit a unei restricii


implic verificarea tuturor nregistrrilor existente deja n tabela
respectiv. Cazul luat drept exemplu este cel n care dup crearea
tabelei i popularea sa cu numeroase nregistrri intervine o
modificare asupra definiiei iniiale, cum ar fi adugarea unei noi
restricii sau modificarea uneia existente. Dac administratorul
bazei de date nu are rbdare s modifice datele existente pentru a
corespunde noilor condiii, dar nu dorete nici ca s-i complice
viaa cu noi nregistrri inconsistente, atunci poate activa restriciile
cu pricina fr v a l i d a r e a nregistrrilor prezente. Acest mod de
activare nseamn c doar noile nregistrri vor fi supuse controlului
conformitii cu aceste restricii.
S lum ca exemplu cazul n care ntreprinderea i modific
politica n ceea ce privete programul de lucru, reducndu-1 la
maximum 10 ore. n baza de date problema se reduce la modificarea
restriciei CK PONTAJE ORELUCRATE din tabela PONTAJE.
Zis i fcut:

ALTER TABLE ponta je DROP CONSTRAINT ck_pontaje_orelucrate;


ALTER TABLE ponta je ADD CONSTRAINT ck_ponta j e_orelucrate
CHECK (orelucrate BETWEEN 0 AND 10) ;
MARCADATA ORELUCRATE 0REC0 0REN0APTE 0REABSNEM
2081O7-FEB-03 6 ck_pontaje_orelucrate
SQL> ALTER TABLE pontaje ADD CONSTRAINT 0 2 CHECK 0 0
(orelucrate BETWEEN 0 AND 10);
200207-FEB-03 6 0
ALTER TABLE pontaje ADD CONSTRAINT ck_pontaje_orelucrate 0 8
200307-FEB-03
i 6 * 0 0 0
ERROR at line 1:
200**07-FEB-03 6 0 0 0
ORA-02293: cannot validate (PERSONAL.CK PONTAJE ORELUCRATE) - check constraint violated
200507-FEB-03 6 0 0 0
2002 10-FEB-03 10 0 2 0
200110-FEB-03
Figura 4.25. Imposibilitatea12 validrii0restriciei ck_pontaje_orelucrate
2 bhi
200**11-FEB-03 ** 0 * e
innd
200111-FEB-03 cont de faptul c
** nu este implicat
0 nici o fraz
* INSERT, 0nenorocirea
provine de la eventualele pontaje existente (ar putea exista un salariat att
de harnic nct s fi lucrat peste 10 ore):
116 Crearea tabelelor i definirea restriciilor

S Q L > UPDATE personal SET narea = 1081 UHERE narea = 2001;


UFDATE personal SET narea = 1001 tIHERE narea - 2081 *
ERROR at line 1:
ORfi-82292: integrity constralnt (PERSONAL.FK_PONTAJE_PERSONAL) violated - child record found

Figura 4.27. Modificarea valorilor atributelor din cheia primar (tabela printe)
este aparent imposibil
Singura modalitate de a evita mesajul anterior const n
actualizarea prealabil a tabelei copil i apoi a celei printe. S
presupunem ns c avem de-a face cu un administrator
ncpnat, care dorete actualizarea n succesiunea PERSONAL -
PONTAJE. Implicit, la creare, restriciile sunt n e a m n b i l e . Pentru
a declara restricia de integritate referenial a tabelei PONTAJE ca
amnabil, se poate proceda n felul urmtor:

ALTER TABLE pontaje DROP CONSTRAINT f k_pontaj e_personal;


ALTER TABLE Figuraponta
4.26. Exist
je un salariat prea" harnic care nu respect restricia pe care am dorit
ADD
s o impunem
CONSTRAINT f k_pontaje_personal FOREIGN KEY (marca)
REFERENCES personal (marca)
Cum, n cazul de fa,
DEFERRABLE pontajul
INITIALLY angajatului nu poate fi modificat,
IMMEDIATE;
fiind implicat n calculul drepturilor pe luna februarie, singura
soluie pentru a tia elanul altor salariai vrednici (de acum nainte)
Restricia FK_PONTAJE_PERSONAL va fi a m n a b i l , ns clauza
este:
INITIALLY IMMEDIATE determin deocamdat verificarea acesteia la
ALTER TABLE pontaje ADD CONSTRAINT ck_pontaje_orelucrate
fiecare comand SQL (la fel
CHECK (orelucrate ca n 0cazul
BETWEEN AND 10)restriciilor neamnabile
ENABLE NOVALIDATE;
obinuite).
sau: Trecerea din starea a m n a b i l i m ediat n
a m n a b i l a m n a t presupune lansarea comenzii:
ALTER TABLE pontaje ADD CONSTRAINT ck_jpontaje_orelucrate CHECK
SET CONSTRAINT f k_pontaje_personal DEFERRED;
(orelucrate BETWEEN 0 AND 10) DISABLE;
ALTER TABLE ponta j e ENABLE NOVALIDATE
De acum nainte n sesiunea curent vom putea executa fr team
CONSTRAINT ck_pontaj e_orelucrate;
comenzi violatoare" n prima faz a restriciilor refereniale:

UPDATE Dac opiunile


personal SETdemarcadezactivare/reactivare
= 1001 WHERE marcaa =restriciilor 2001; fac parte
de o bun bucat de vreme din arsenalul Oracle, din versiunea 8 a
Dac vom ncerca
fost introdus s comitem"
i posibilitatea demodificrile,
a amna momentul atunci vom vedeaunei
verificrii
c mecanismul
restricii. Cele de asigurare
declaratea amnabile
restriciilor i nu activate
poate fi pclit att
n acest feldesunt
simplu: verificate abia la sfritul tranzaciei (COMMIT), iar cele neamnabile,
sau amnabile, dar configurate ca i m e d i a t e , sunt verificate la
SQL> SET CONSTRAINT fk_pontaje_personal DEFERRED;
fiecare instruciune DML (INSERT/UPDATE/DELETE). Aceast
Constralnt set.
caracteristic permite (evident, fornd un pic nota) chiar
propagarea
SQL> UPDATE personal SET marca n= 1801
cascad
UHERE marcaa modificrilor dintr-o tabel printe n
- 2001;

tabelele copil fr a crea declanatoarele care s execute


1 roi* updated.

actualizarea cheilor strine din tabelele copil la modificrile cheilor


SQL> COMMIT;
C0NMITprimare din tabelele printe (UPDATE CASCADE).

ERROEt at lineDe1: exemplu, conducerea firmei emite o not intern prin care
QRA-82891: transaction rolled back
modul
ORA-02292: integrityde generare
constraint a mrcilor angajailor
(PERSONAL.FK_P0NTRJE_PERS0HRL) nu
uiolated - child record se mai face secvenial,
found
ci dup un alt criteriu. Administratorul bazei de date va ncerca s
Figura 4.28. Vigilena serverului fa de restriciile amnate se face simit n momentul
comiterii
Oracle. Ghidul dezvoltrii aplicaiilor profesionale 117
118 Crearea tabelelor i definirea restriciilor

Serverul Oracle s-a simit


SELECT ' ) I I CHRM31.
att de ofensat nct a anulat ntreaga
|| RPAD(table_jiame.30) II II CHRM231
tranzacie doar pentru o ncercare nevinovat" de a pcli o banal
FROM user_tables
UNION
restricie. Pentru a avea succes, trebuie procedat cuminte, n felul
SELECT '' II C H R ( 1 3 ) , | | RPAD(table_name,30) ||' || CHR(124) FROM
urmtor - chiar
user_tables ORDER BY dac 2; am amnat o restricie, Oracle n-are memorie
(RAM) scurt:
spool off_________________________________________________________

SET CONSTRAINT f k_ponta je_personal DEFERRED;


UPDATE personal SET marca = 1001 WHERE marca = 2001;
Cele
UPDATE trei pri
pontaje SETale comenzii
marca = 1001 WHERE TABLE:
CREATE marca = 2001 ;
COMMIT;
CREATE TABLE tabel (
atributltipl (lungimel [, poz_fracionarel] )
4.11. Scripturi SQL*Plus
[, atribut2 tip2 (lungime2 [, de refacere
poz_fracionare2] ) a
tabelelor i. .restriciilor
. ]
);
Pe baza complexelor informaii stocate n dicionarul bazei, pot fi
generate o serie de
sunt generate de scripturi pentru
trei fraze salvarea
SELECT tabelelor
speciale, i restriciilor
conectate prin
din schema curent. Operaiunea este util att pentru
operatorul UNION. La acestea se mai adaug o linie pentru spaiere, mutarea
bazei de date
linie care pe altspaiu
conine server,
i fr a recurge
caracterul la operaiunile
ASCII al tastei RETURN de export/
(13).
import, ct i pentru salvarea structurii bazei de date,
Pentru ca dispunerea liniilor s fie corect, se folosete, drept i, astfel,
diminuarea
artificiu, o asemnificativ
doua coloanace gradului de stresnumele
concateneaz al administratorului
tabelei
- ifb x'
cu: BD
spaiu,
4.11.1.
| Bk Edit Format yew tielp |
pentru linia CREATE TABLE
Re-crearea tabelelor ...;
CI identificatorul coloanei C2 id),
(column pentru linia
corespondent
Dac fiecrui atribut;
numele tabelelor pot
--PERSONAL
fi preluate din tabela virtual a
CREATE TABLE PERSONAL C
catalogului
MARCA NUMBER ( 5)
sistem ce
caracterul USER_TABLES,
are --PERSONAL
codul ASCII numele, 123 tipul,
mailungimea i valorile
marei dect orice
implicite
identificator
.NUMEPREN VARCHAR2 C 40)
ale atributelor
de coloan;se --PERSONAL
regsesc n USER_TAB_COLUMNS.
--PERSONAL 2
3
Scriptul
,COMPART VARCHAR2 ( 5)
,DATASV DATE (7) se obine n SQL*Plus prin comanda prin care rezultatele frazei
caracterul ce are PERSONAL
codul ASCII 124, pentru ultima
--PERSONAL SPOOL, 4
5
linie a
.SALORAR NUMBER ( 16, 2)
.SALORARCO NUMBER SELECT urmtoare
fiecrei tabele.
(16, 2) vor fi salvate
PERSONAL n fiierul ASCII re_creare_tabele.
6

sql
.COLABORATOR CHAR ( 1)
);
din directorul f:\oracle_car-
PERSONAL
PERSONAL
te\cap04_creare_tabele. {
7

n mod normal,
CREATE TABLE PONTAJE (
SELECT-ul
Listing de tabelelor
PONTAJE
4.7. Re-crearea
--PONTAJE
crearedin
arschema
fi trebuit
curent precedat de unul de
MARCA NUMBER ( 5) 1
.DATA DATE (7) tergere, de genul SELECT ' DROP --PONTAJE TABLE ' | | table_name |2 | ' CASCADE ; '
.ORELUCRATE NUMBER ( 2) PONTAJE 3

.ORECO NUMBER ( 2)
column H-Creare_tabele" FORMAT A60 PONTAJE 4

,ORENOAPTE NUMBER (2) column C2 FORMAT A40 PONTAJE 5


,OREABSNEM NUMBER ( 2) --PONTAJE 6
--PONTAJE
); spool f:\oracle_carte\cap04 creare_tabeleVre_creare_tabe!e.sql t

SELECT
____________________________________________________
>

CREATE TABLE ' || table_name ||' (' AS "-Crearejabele",


|| RPAD(table_name,30) || " as c2 FROM user_tables UNION
SELECT CASE columnjd WHEN 1 THEN '1 ELSE 7 END ||
column_name || " || data_type ||
CASE WHEN datajype NOT IN ('NUMBER', 'CHAR', 'VARCHAR2') THEN
ELSE'('ll
NVL(data_precision, datajength) ||
CASE WHEN data_scale > 0 THEN '|| data_scale ELSE " END
II T
END ,
'-' || RPAD(table_name,30) || TO_CHAR(column_id,999')
FROM user_tab_columns UNION
Oracle. Ghidul dezvoltrii aplicaiilor profesionale 119

4.11.2. Re-crearea clauzelor DEFAULT


La prima tentativ de recreare a tabelelor, observnd existena
atributului Data Default n USER_TAB_COLUMNS, ne-am avntat s
includem i clauza DEFAULT. Din pcate, cei de la Oracle s-au gndit
c formatul ideal pentru pstrarea valorilor implicite ale atributelor
este unul LONG. Pcatul decurge din faptul c acest tip de date este
extrem de nzuros, chiar documentaia Oracle recomandnd
degraba conversie a acestor atribute n formate LOB. Recomandarea
nu se aplic ns la propriile tabele din dicionarul de date, astfel
nct, pentru a salva situaia, am angajat temporar tabela TEMP1, n
care atributul Val lmpli- cit este de tip CLOB, iar la inserarea
liniilor din USER_TAB_COLUMNS s-a folosit funcia TO LOB - vezi
listing 4.8.
DROP TABLE tempi;

CREATE TABLE tempi ( tabela VARCHAR2(30), atribut VARCHAR2(30),


id_atribut NUMBER(2), tip_atribut VARCHAR2(20), valjmplicita CLOB );

INSERT INTO tempi


SELECT table_name, column_name, columnjd, data_type, TO_LOB(data_default)
FROM user_tab_columns
WHERE data_default IS NOT NULL ;

COMMIT;

spool f:\oracle_carte\cap04_creare_tabele\re_creare_default.sql

SELECT ' ALTER TABLE' || tabela ||' MODIFY * || atribut || DEFAULT


|| valjmplicita I I * ; ' AS " '
FROM tempi ;

spool off________________________ ________________________________________________

Fiierul ASCII generat prin comanda SPOOL este re creare default.


sql - vezi figura 4.30.

Figura 4.29. Fiierul generat de listingul 4.7.


120 Crearea tabelelor i definirea restriciilor

Figura 4,30. Scriptul de refacere a valorilor implicite

4.11.3. Restricii NOT NULL


/
Pentru fiecare atribut declarat NOT NULL, crem o restricie cu numele
nn_tabel_atribut, aa nct scriptul din listingul 4.9 funcioneaz fr
prea multe emoii.
Listing 4.9. Re-declararea restriciilor NOT NULL

spool f:\oracle_carte\cap04_creare_tabele\re_creare_notnull.sql

SELECT' ALTER TABLE ' || table_name||' MODIFY (' || column_name


II' CONSTRAINT NNJ || iable_name | | I I coiumn_name ||' NOT NULL );'
FROM user_tab_columns WHERE nullable = N'
ORDER BY table_name, column_name ;

spool off___________________________________________________________________________________

Am avea oarecari probleme dac restriciile de tip NOT NULL


pentru un atribut ar aprea, singure sau combinate, n clauze CHECK
la nivel de atribut sau nregistrare. Noi ns lucrm ordonat (din
acest punct de vedere).

4.11.4. Chei primare i alternative


Dup cum am vzut cteva pagini mai sus, cheilor primare (PRIMARY
KEY) i alternative le corespund n tabela virtual din dicionar
Oracle. Ghidul dezvoltrii aplicaiilor profesionale 121

cte o restricie de tip 'F i 'U'. Elementul de dificultate ine de


faptul c o cheie primar sau candidat poate fi compus din dou
sau mai multe atribute, fapt pentru care trebuie folosit atributul
Position din tabela virtual
USER_CONS_COLUMNS.
Scriptul din listing 4.10 terge mai nti toate restriciile de tip
cheie primar i alternativ., apoi, prin dou fraze SELECT, salveaz
n fiierul ASCII n care s-a fcut redirectarea dou rnduri de
comenzi ALTER TABLE corespunztoare celor dou tipuri de cheie
candidat. Logic ar fi fost s procedm analog (n sensul tergerii) i
pentru restriciile de non-nulitate din scriptul discutat n paragraful
anterior, ns niciodat nu e prea trziu.
Listing 4.10. Re-declararea cheilor primare i alternative

spool f:\oracle_carte\cap04_creare_tabele\re_creare_chei_primare_si_altemative.sql

SELECT 'ALTER TABLE ' || table_name ||' DROP CONSTRAINT' ||


constraint_name ||' CASCADE AS "-tergere restricie"
FROM user_constraints WHERE
constraintjype IN ('P', 'U');

SELECT 'ALTER TABLE ' || table_name ||' ADD CONSTRAINT pk ' || table_name ||
' PRIMARY KEY ' ||'( ||atr1 ||
CASE WHEN atr2 IS NOT NULL THEN ', ' || atr2 END ||
CASE WHEN atr3 IS NOT NULL THEN * || atr3 END | | ' ) ; '
AS "-Cheile primare
FROM user_constraints uc
LEFT OUTER JOIN
(SELECT constraint_name, column_name AS atr1
FROM user_cons_columns
WHERE position = 1) a1 ON uc.constraint_name = a1 .constraint_name
LEFT OUTER JOIN
(SELECT constraint_name, column_name AS atr2
FROM user_cons_columns
WHERE position = 2) a2 ON uc.constraint_name = a2.constraint_name
LEFT OUTER JOIN
(SELECT constraint_name, column_name AS atr3
FROM user_cons_columns
WHERE position = 3) a3 ON uc.constraint_name = a3.constraint_name
WHERE constraint_type = P;

SELECT 'ALTER TABLE ' || table_name ||1 ADD CONSTRAINT unj || table_name ||
|| atr1 ||
CASE WHEN atr2 IS NOT NULL THEN || atr2 END ||
CASE WHEN atr3 IS NOT NULL THEN '_' || atr3 END ||'
UNIQUE* ||'(' ||atr1 ||
CASE WHEN atr2 IS NOT NULL THEN ',' || atr2 END ||
CASE WHEN atr3 IS NOT NULL THEN ',' || atr3 END [ | ' ) ; '
AS "-Cheile alternative"
FROM user_constraints uc
LEFT OUTER JOIN
(SELECT constraint_name, column_name AS atr1
FROM user_cons_columns
WHERE position = 1) a1 ON uc.constraint_name = a1 ,constraint_name
LEFT OUTER JOIN
(SELECT constraint_name, column_name AS atr2 FROM
122 Crearea tabelelor i definirea restriciilor

WHERE position = 2) a2 ON uc.constraint name = a2.constrainf name LEFT


OUTER JOIN
(SELECT constraint_name, columnjiame AS atr3
FROM user_cons_columns
WHERE position = 3) a3 ON uc.constraint_name = a3.constraint_name
WHERE constraintjype = U';

spool off__________________________________________________________________

Structurile de tip CASE sunt limitate la trei coloane (atrl, atr2 i


atr3), deoarece tim c cele mai lungi chei candidat din schema
noastr au maximum trei atribute. Figura 4.31 arat coninutul
fiierului ASCII re creare chei prima- re si alternative.

E re_creare_chei_primare_si_altematve - Notepad (J[][)(


gle d(t Farmst Jjew Help
tergere restricie i
ALTER TABLE PERSONAL DROP CONSTRAINT PK^PERSONAL CASCADE ;
ALTER TABLE PERSONAL DROP CONSTRAINT UN_PERS0NA1_______NUMEPREN CASCADE ;
ALTER TABLE PONTAIE DROP CONSTRAINT PICJ>ONTA3E CASCADE ;
ALTER TABLE RETINERI DROP CONSTRAINT PK_RETINERI CASCADE ;
ALTER TABLE SALARII DROP CONSTRAINT PK^SALARII CASCADE ;
ALTER TABLE SPORURI DROP CONSTRAINT PlC_SPORURI CASCADE ;
ALTER TABLE TRANSE_SV DROP CONSTRAINT PK_TRANSE_SV CASCADE ;
7 rows selected.

Cheile primare

ALTER TABLE PERSONAL ADD CONSTRAINT pk_PERSONAL PRIMARY KEY (MARCA) ;


ALTER TABLE PONTADE ADD CONSTRAINT pk_PONTA3E PRIMARY KEY (MARCA, DATA) ;
ALTER TABLE SPORURI ADD CONSTRAINT pk_SPORURI PRIMARY KEY (MARCA, AN, LUNA) ; ALTER TABLE
RETINERI ADD CONSTRAINT pk_RETINERI PRIMARY KEY (MARCA, AN, LUNA) ; ALTER TABLE SALARII ADD
CONSTRAINT pk_SALARII PRIMARY KEY (MARCA, AN, LUNA) ; ALTER TABLE TRANSE_SV ADD CONSTRAINT
pk_TRANSE_SV PRIMARY KEY (ANI_LIMITA_INF) ;
6 rows selected.

--Cheile alternative

ALTER TABLE PERSONAL ADD CONSTRAINT un_PERSONAI_______NUMEPREN UNIQUE (NUMEPREN) ;

Six oli S-l M.

Figura 4.31. Fiierul text pentru refacerea cheilor primare i


alternative

Atenie! Denumirile restriciilor nu trebuie s depeasc 30 de


caractere, aa nct ar trebui luate msuri de siguran
(trunchierea unor eventuale denumiri mai lungi).
4.11.5. Reguli de validare la nivel de atribut i nregistrri
Trei chestiuni trebuie s avem n vedere atunci cnd extragem
informaii despre regulile de validare:
dicionarul de date le stocheaz n tabele USER_CONSTRAINTS
cu valoarea 'C pentru atributul Constraint Type;
expresia ce constituie restricia propriu-zis reprezint
valoarea coloanei Search Condition care este, ai ghicit, de tip
LONG;
Oracle include n aceste reguli i pe cele de tip NOT NULL.
Oracle. Ghidul dezvoltrii aplicaiilor profesionale 123

Aa nct scriptul din listing 4.11 refolosete tabela TEMP1


pentru conversia atributului LONG n CLOB.
Listing 4.11. Preluarea regulilor de validare

spool f:\oracle_carte\cap04_creare_tabele\re_creare_check.sql

DROP TABLE tempi;

CREATE TABLE tempi ( restricie VARCHAR2(30), tip_restrictie varchar(20), tabela


VARCHAR2(30), expresie CLOB );

INSERT INTO tempi


SELECT constraint_name, constraint_type, table_name,
TO_LOB(search_condition)
FROM user_constraints WHERE constraint_type = 'C ;

COMMIT;

SELECT 'ALTER TABLE * || tabela ||' DROP CONSTRAINT ' 1| restricie ||


AS "-tergere reguli de validare"
FROM tempi
WHERE expresie NOT LIKE '%NULL%;

SELECT' ALTER TABLE ' || tabela H ' ADD CONSTRAINT' 1 restricie ||


CHECK (' || CAST (expresie AS VARCHAR2(300)) | | ' ) A S check-uri"
FROM tempi
WHERE expresie NOT LIKE '%NULL%';

spool off_______________________________________________________________

4.11.6. Restriciile refereniale


//

Cu restriciile refereniale am ajuns la partea cea mai solicitant din


ceea ce ne-am propus n acest paragraf. Avem de identificat nu
numai componena cheilor strine (din tabelele copil), ci i pe aceea
a cheilor corespondente din tabelele copil, iar atributele pot avea
denumiri diferite. Dicionarul de date Oracle, prin tabela virtual
USER_CONSTRAINTS, furnizeaz att numele restriciei din tabela
copil (constraint name) pe baza creia pot fi identificate atributele
cheii strine, ct i numele restriciei (primare/unice)
corespunztoare din tabela printe
(r_constraint_name).
Impresionantul script din listing 4.12 folosete n SELECT-ul
124 Crearea tabelelor i definirea restriciilor

Listing 4.12. Preluarea restriciilor refereniale


spool f:\oracle_carte\cap04_creare_tabele\re_creare_refsql

SELECT 'ALTER TABLE ' || table_name ||' DROP CONSTRAINT ' ||


constraint_name ||' CASCADE AS "-tergere restr. ref."
FROM user_constraints WHERE constraintjype = ' R ' ;

SELECT 'ALTER TABLE ' || uc_copil.table_name ||' ADD CONSTRAINT ' || constraint_name || '
FOREIGN K E Y ' ||'( ||atrc1 ||
CASE WHEN atrc2 IS NOT NULL THEN ',' || atrc2 END ||
CASE WHEN atrc3 IS NOT NULL THEN ',' || atrc3 END
II ) ' It
' REFERENCES ' || uc_parinte.table_name |j' (' ||atrp1 ||
CASE WHEN atrp2 IS NOT NULL THEN \ ' || atrp2 END ||
CASE WHEN atrp3 IS NOT NULL THEN ',' |[ atrp3 END ' | | ' ) '
AS "-Restricii refereniale"
FROM user_constraints uc_copil
INNER JOIN user_constraints uc_parinte
ON uc copil.r_constraint_name = uc_parinte.constraint_name
LEFT OUTER JOIN
(SELECT constraint_name, column_name AS atrd
FROM user_cons_columns
WHERE position = 1) c1 ON uc_copil.constraint_name = c1 ,constraint_name
LEFT OUTER JOIN
(SELECT constraint_name, column_name AS atrc2
FROM user_cons_columns
WHERE position = 2) c2 ON uc_copil.constraint_name = c2.constraint_name
LEFT OUTER JOIN
(SELECT constraint_name, column_name AS atrc3
FROM user_cons_columns
WHERE position = 3) c3 ON uc_copil.constraint_name = c3.constraint_name
LEFT OUTER JOIN
(SELECT constraint_name, column_name AS atrpl
FROM user_cons_columns
WHERE position = 1) p1 ON uc_parinte.constraint_name = p1 ,constraint_name
LEFT OUTER JOIN
(SELECT constraint_name, column_name AS atrp2
FROM user_cons_columns
WHERE position = 2) p2 ON uc_parinte.constraint_name = p2.constraint_name
LEFT OUTER JOIN
(SELECT constraint_name, column_name AS atrp3
FROM user_cons_columns
WHERE position = 3) p3 ON uc_parinte.constraint_name = p3.constraint_name WHERE
uc_copil.constraint_type = ' R ' ;

spool off_____________________________________________________________________ _________

Fierul ASCII generat este prezentat n figura 4.32. Dei nu apare


explicit n figur, scriptul funcioneaz i atunci cnd cheile strine
sunt compuse, i atunci cnd restriciile refereniale sunt recursive,
adic tabela copil este simultan printe (ex. ierarhiilor). Dup cum
se observ ns, am inut cont c, n schema noastr, o cheie
primar (i, firete, strin) nu poate avea mai mult de trei
Oracle. Ghidul dezvoltrii aplicaiilor profesionale 125

C re_creare_ref * Notepad
p dit Format iew Help

--tergere restr. ref.

ALTER TABLE PONTAIE DROP CONSTRAINT FK_PONTA3E_PERSONAL CASCADE ALTER TABLE


PONTAJE_2003 DROP CONSTRAINT FK_Pl_P2 CASCADE ;
ALTER TABLE RETINERI DROP CONSTRAINT FIC_RETINERI_MARCA CASCADE ; ALTER
TABLE SALARII DROP CONSTRAINT FK_SALARII_PERSONAL CASCADE ALTER TABLE
SPORURI DROP CONSTRAINT FK_SPORURI_PERSONAL CASCADE

8 rows selected.

--Restricii refereniale

ALTER TABLE PONTAJE ADD CONSTRAINT FOREIGN KEY (MARCA) REFERENCES PERSONAL (MARCA) FOREIGN
ALTER TABLE SPORURI ADD CONSTRAINT KEY (MARCA) REFERENCES PERSONAL (MARCA) FOREIGN KEY
ALTER TABLE RETINERI ADD CONSTRAINT (MARCA) REFERENCES PERSONAL (MARCA) FOREIGN KEY (MARCA)
ALTER TABLE SALARII ADD CONSTRAINT REFERENCES PERSONAL (MARCA)
I I
8 rows selected.

I
Figura 4.32. Fiierul text pentru refacerea
restriciilor refereniale
Capitolul 5

Actualizarea tabelelor prin comenzi


SQL
Dup crearea tabelelor i implementarea mecanismului de
asigurare a integritii i coerenei bazei de date se poate trece la
folosirea sa efectiv, prin preluarea datelor legate de obiectele,
procesele i tranzaciile care constituie substana aplicaiei propriu-
zise. i n Oracle, sistemul clasic" de actualizare a tabelelor se
bazeaz pe trei comenzi SQL, INSERT, UPDATE i DELETE. Formatul
general al acestora este ns unul generos, cu att mai mult cu ct
fiecare poate folosi i subconsultri.

5.1. Adugarea de nregistrri - INSERT


Cum e i normal, ncepem capitolul cu prezentarea comenzii prin
care o tabel poate fi populat cu nregistrri. Pe parcursul
capitolului precedent am fcut apel n cteva rnduri la comanda
INSERT, pentru a pune n eviden modul n care Oracle reacioneaz
la nclcarea restriciilor declarate.

5.1.1. Dou formate;


Cea mai frecvent form a comenzii INSERT este:
INSERT INTO tabel
VALUES(val_atributl, val_atribut_2, . .., val_atribut_n)

Dac valorile enumerate sunt mai multe sau mai puine dect
atributele tabelei PERSONAL, atunci se declaneaz erorile din
figura 5.1. n primul caz, apare o valoare zero inutil, ce nu poate fi
asociat nici unui atribut, iar n al doilea, lipsete valoarea ultimului
atribut (Colaborator).
De asemenea, ordinea enumerrii valorilor trebuie s coincid cu
ordinea n care au fost declarate atributele la crearea tabelei. Pe
parcursul capitolului precedent a fost folosit i un al doilea format,
cel n care se declar atributele ce urmeaz a primi valori n clauza
VALUES. Astfel, n urma comenzii INSERT urmtoare, n linia nou
introdus, atributele Compart, SalOrar, SalOrarCO i Colaborator vor
128 Actualizarea tabelelor prin comenzi SQL

Reamintim c fiecrui atribut declarat NOT NULL i fr valoare


implicit (clauza DEFAULT) trebuie s i se precizeze o valoare n
clauza VALOES.

SQL> INSERT INTO personal UftLUES (101, Angajat 1, IT*,


2 T0_DATE( '12/10/1980', 'DD/MM/WW),56000, 55000, *N',0)
3 /
INSERT INTO personal UftLUES (101, 'ftngajat 1*, IT',
*
ERROR at line 1:
ORft-00913: too many values

SQL> INSERT INTO personal UftLUES (101, 'ftngajat 1', 'IT',


2 T0_DftTE(*12/10/1980', *DD/MM/YYYY* ) ,56080, 55000)
3 /
INSERT INTO personal UftLUES (181, 'ftngajat 1*, 'IT',
*
ERROR at line 1:
ORft-00947: not enough values

SQL>

Figura 5.1. Cele dou erori cauzate de neconcordana numerelor de valori i de atribute

5.1.2. Inserri i secvene


Secvena este un obiect al unei baze de date care genereaz valori
unice. Are un regim public, aa c n aplicaiile cu numr mare de
utilizatori orice atribut de tip cheie surogat (aa cum este PERSONAL.
Marca) poate beneficia de serviciile sale. Pentru exemplificare,
crem o secven care va genera mrci, astfel nct fiecare marc
s fie unic:

CREATE SEQUENCE seq_marca


INCREMENT BY 1 MINVALUE 101
MAXVALUE 5555 NOCYCLE
NOCACHE ORDER ;

Numele secvenei este SEQ MARCA. Valorile generate vor fi


consecutive (INCREMENT BY 1), ncepnd cu 101 i terminnd cu 5555.
Dac valorile generate ating limita maxim, iar la crearea secvenei
s-a folosit clauza NOCYCLE, la urmtorul apel al unei valori din
secven va fi generat o eroare (ORA-08004). Dac s-ar folosi CYCLE,
dup atingerea limitei superioare, se reiau valorile, ncepnd cu cea
minim. ORDER garanteaz generarea valorilor n ordinea n care
Oracle. Ghidul dezvoltrii aplicaiilor profesionale 129

Dup crearea secvenei, o valoare nou va fi generat folosind


clauza NEXTVAL; valoarea curent (ultima valoare generat) a
secvenei poate fi obinut prin clauza :URRVAL - vezi figura 5.2.

SQL> SELECT seqmarca.NEXTUAL FROM dual ;

NEXTUAL

101
SQL> SELECT seq_marca.NEXTUAL FROM dual ;

NEXTUAL

102
SQL> SELECT seqnarca.CURRUAL FROM dual ;

CURRUAL

102

SQL>

Figura 5.2. Generarea valorilor din secven


Atenie ns ! Clauza CURRVAL nu poate fi folosit dect dac
secvena a fost iniializat (printr-un NEXTVAL) n sesiunea
respectiv. Spre exemplu, n figura 5.3 se nchide sesiunea
Oracle. Apoi se deschide o nou sesiune, dup care, imediat,
se lanseaz fraza SELECT, prin care s-ar dori aflarea valorii
curente din secven. Eroarea declanat are codul ORA-08002.
SQL> DISCONNECT
Disconnected From Personal 0racle9i Release 9.2.0.1.8 - Production
With the Partitioning, OLAP and Oracle Data Mining options JServer
Release 9.2.0.1.0 - Production SQL>
SQL> CONNECT
Fotachem/fotache
Connected.
SQL>
SQL> SELECT seqmarca.CURRUAL FROM dual ;
SELECT seq_marca.CURRUAL
FROM dual *
ERROR at line 1:

ORA-08002: sequence SEQ_MARCA.CURRUAL is not yet defined in this

session SQL>
Figura 5.3. Clauza CURRVAL fr iniializarea secvenei
Exist ns o soluie pentru aflarea valorii curente din secven
fr a recurge la texTVAL (ceea ce ar echivala cu pierderea unei
valori). Dicionarul de date pstreaz informaii preioase despre
secvenele create n schema curent n tabela virtual
USER_SEQUENCES. Deoarece am declarat, la creare, c renunm la
Oracle. Ghidul dezvoltrii aplicaiilor profesionale 131

Ultima comand, COMMIT, are drept scop finalizarea tranzaciei i, n


consecin,
130 scrierea definitiv" a liniilor n tabel.
Actualizarea Detalii
tabelelor despre SQL
prin comenzi
mecanismul tranzacional v sunt oferite gratuit n alt paragraf. n
urma execuiei
opiunea scriptului,
CACHE, coninutul
atributul tabelei
CACHE SIZE va fieste cel aa
zero, din figura 5.5.
nct cmpul
LAST_NUMBER din interogarea SELECT * FROM user_sequences va indica
destul SQL>
de precis
SELECTce valoare
* FROM urmeaz
personal ; a furniza secvena la prima
solicitare - vezi figura 5.4.
M ARCO C0 M PA DATASU SALOR AR SAL 0 RAR C
N UM EPREH C0
1 01 1SQL> OESC
IT user_sequences
12 -0 CT- 8 0 Nane5 60 00 55 00 Q N
Ang a jat
1 02 2 CON TA 12 -N 0 U- 7 8 5 75 00 5 60 00 N
Ang
1 03 a jat 3 SEQUENCE
IT !XiAME
02 -JUL - 7 6 6 75 00 6 60 00 N
Ang
1 04 a jat 4 MIN_UALUE
PROD 05 -J AN- 8 2 7 50 00 7 50 00 N
Ang
1 05 a jat IT
5 MAXJJALUE 12 -N 0 U- 7 7 6 25 00 6 20 00 N
Ang
1 06 a jat 6 1NCREHENT_BV
CON TA 11 -A PR- 85 7 15 00 7 00 00 N
10Ang
7 Ang ajat 7 CYCLE_FLAG
a jat CON TA 21 -N 0 U- 9 1 6 15 00 6 00 00 N
10 8 Ang ajat 8 0RDER_FLAG
PROD 30 -DE C - 94 5 45 00 5 20 00 N
CACHESIZE
8 rows selected.
LRST_NUMBER

SQL>
SQL>SELECT * FROM user_sequences ;
|_________________________________________________________
SEQUENCE_N MIN_UALUE M A X UA LU E INCREMENT_BY C 0 CACHE_SIZE
Figura
L A 5.5.
S T N UConinutul
t ffi E R tabelei PERSONAL dup primul apel al listingului
SEQMARCA
La drept vorbind,101ideea 5555 generrii mrcilor1NY
att0 prin constante
103

(la primii
SQL doi angajai), ct ________________________________________________
i prin secven nu este prea
inteligent. Astfel,
Figura 5.4.dac
Informaiilansm n extrase
despre secven execuie a doua oar scriptul,
din dicionar
avem toate ansele
Succesiunea ca mrcile
de comenzi INSERTs din
fie cele din figura
listingul 5.1 populeaz tabela
5.6.
PERSONAL, folosind toate variantele discutate n acest paragraf,
inclusiv prin apelul la secven. Pentru a evita duplicarea cheii
primare i producerea erorii cu pricina, scriptul ncepe prin
tergerea eventualelor nregistrri.
Listing 5.1. Script de populare a tabelei PERSONAL
RCA NUMEPREN C0HPADATASU
DELETE FROM personal;
SALORAR SAL0RARC0 C
109 Angajat 3 INTO personal
INSERT IT 02-JUL-76
VALUES (101, 'Angajat 1\ 67500
'IT. 66000 N
TO_DATE('12/10/1980', DD/MM/YYYY'),56000, 55000, * N ' ) ; 75000 N
110 Angajat 4 PROD 05-JAN-82 75000
INSERT INTO personal VALUES (102, Angajat 2', CONTA',
111 Angajat 5 IT 12-N0U-77 62500
TO_DATE('12/11 /1978', 'DD/MM/YYYY'), 57500, 56000, 'N');
62000 N
112 Angajat 6 CONTA11-APR-85 71500
INSERT INTO personal VALUES (seq_marca.NextVal, Angajat 3', 'IT, 70000 N
113 Angajat 7 CONTA21-N0U-91
TO_DATE('02/07/1976', 'DD/MM/YYYY'),67500, 61500
66000, ' N ' ) ; 60000 N
114 Angajat 8 PROD 30-DEC-94 54500 52000 N
101 - se folosesc
Angajat 1 valorile
IT implicite ale atributelor Compart,
12-0CT-80 56000 SalOrar, SalOrarCO
55000 siN Colaborator
INSERT INTO personal (marca, numepren, datasv)
102 Angajat 2 CONTA12-N0U-78 57500 56000 N
VALUES (seqjnarca.NextVal, Angajat 4', DATE'1982-01-05');

INSERT INTO personal VALUES (seq_marca.NextVal, Angajat 5', 'IT,


TO_DATE('12/11/1977', 'DD/MM/YYYY'),62500, 62000, ' N ' ) ;
INSERT INTO personal VALUES (seq_marca.NextVal, Angajat 6, 'CONTA',
TO_DATE('11/04/1985', 'DD/MM/YYYY'),71500, 70000, ' N ' ) ;
INSERT INTO personal VALUES (seq marca.NextVal, 'Angajat 7', 'CONTA',
TO_DATE('21/11/1991', 'DD/MM/YYYY'),61500, 60000, ' N ' ) ;
INSERT INTO personal VALUES (seq_marca.NextVal, 'Angajat 8', 'PROD',
TO_DATE('30/12/1994', 'DD/MM/YYYY'),54500, 52000, ' N ' ) ;

COMMIT ;
132 Oracle. Ghidul dezvoltrii aplicaiilor profesionale
Actualizarea tabelelor prin comenzi SQL
133

FROM personal
INSERT INTO WHERE
personal VALUES
marca (seq_marca.NextVal,
NOT IN (102,107) 'Angajat T, IT,
DATE'1980-10-12',56000,
UNION 55000, ' N ' ) ;
INSERT INTO personal VALUES (seq_marca.NextVal, 'Angajat 2\ 'CONTA',
SELECT marca, DATE'2003-07-02', 0, 8
DATE'1978-11-12',57500, 56000, 'N');
INSERT INTO FROM
personalpersonal
VALUES (seqjnarca.NextVal, Angajat 3', IT,
WHERE marca IN (102,107)
DATE'1976-07-02',67500, 66000, N') ; ;
INSERT INTO personal (marca, numepren, datasv) VALUES (seq_marca.NextVal, 'Angajat 4',
DATE'1982-01-05');
INSERT INTO personal VALUES (seqjnarca.NextVal, 'Angajat 5, IT,
SQL> INSERT INTO pontaje
DATE'1977-11-12',62500,
2 SELECT62000,
marca, ' N 'DATE
); 1
2003-07-01 *, 8, fl, 0, 0
INSERT INTO personal
3 VALUES
FROM personal(seqjnarca.NextVal, 'Angajat 6, 'CONTA',
DATE'1985-04-11',71500,
4 / 70000, ' N ' ) ;
INSERT INTO personal VALUES (seq_marca.NextVal, 'Angajat 7', 'CONTA',
8 rows
DATE'1991-11-21', created.
61500, 60000, N ' ) ;
INSERT INTO personal VALUES (seq_marca.NextVal, 'Angajat 8', 'PROD',
SQL>
DATE'1994-12-30', SELECT
54500, 52000,* FROM
N ' ) ; pontaje ;

COMMIT;_____________________________________________________________________________
M AR DATA ORELUC ORECO OREN OA ORE ABS
CA RATE PTE N EM
0 1- JUL - 8 0 0 0
18 1 05.1.3.
3 Inserare prin subconsultare
10 2 0 1- JUL - 8 0 0 0
3 JUL -
10 3 0 1- 8 0 0 0
10 400Am
3
1- JULepuizat
- cam8 fugitiv 0subiectul0 populrii
0 cu nregistrri a tabelei
10 500PERSONAL,
3 JUL -
1- 8 0 0
aa c ne grbim s continum 0 cu cea mai stufoas
10 6 0 3
1 - 8 0 0 0
dintre
JUL
10 7 0 - 03 - tabele -8 PONTAJE.
1- JUL 0 Firete,0 i aici putem
0 apela la unul dintre
10 8 0formatele
3
1- JUL - mai 8mult sau 0mai puin 0 clasice0 de mai sus. Ins mult mai
03
atractiv ar fi s adugm dintr-o singur micare cte o linie pentru
fiecare angajat.
Dei 1 iulie 2003 cade ntr-o mari, i marea nu e prea indicat pentru
nceputuri, comanda INSERT urmtoare va avea efectul scontat:

INSERT INTO pontaje


SELECT marca, DATE'2003-07-01', 8, 0, 0, 0
FROM personal ;

Celor nencreztori le este dedicat figura 5.7.


ncepnd cu 2 iulie, intr n concediu angajaii cu mrcile 102 i 107:
Figura 5.6. Coninutul tabelei PERSONAL dup al doilea apel al
INSERT INTO pontaje (marca, listingului
data, orelucrate, oreco)
SELECT marca, DATE'2003-07-02', 8, 0 FROM
personal
Dac Angajat 1 i Angajat 2 i pstreaz" mrcile, celelalte valori
WHERE marca NOT IN (102,107)
urmeaz
UNION cursul secvenei. Cel mai sigur este s ne folosim fie numai
SELECT marca, DATE'2003-07-02', 0, 8 FROM de constante, fie numai
A
personal
de secven. In IN
WHERE marca plus, scriptul ; prezentat n listing 5.2 re-creeaz
(102,107)
secvena, astfel nct ntotdeauna prima marc va fi 101.
Interesant este c numele unei tabele poate fi substituit printr-o
Listing 5.2.
subconsultare. Noul
Astfel, script de
echivalent populare
comenzii de a tabelei
mai sus sePERSONAL
poate
scrie:
DELETE FROM personal;
INSERT INTO
(SELECT
DROP marca,
SEQUENCE data, orelucrate, oreco FROM pontaje)
seq_marca;
SELECT marca, DATE'2003-07-02' 8, 0
CREATE SEQUENCE seq marca INCREMENT BY 1
134 Actualizarea tabelelor prin comenzi SQL

UNION SELECT marca. DATE'2003-07-03', 0, 8 FROM personal WHERE marca IN (102.107);


- 4 iulie 2003
INSERT INTO pontaje (marca, data, orelucrate, oreco)
SELECT marca, DATE'2003-07-04', 8, 0 FROM personal WHERE marca NOT IN (102,107) UNION
SELECT marca, DATE'2003-07-04', 0, 8 FROM personal WHERE marca IN (102,107);

- 7 iulie
2003 INSERT
INTO pontaje
SELECT marca, DATE'2003-07-07',
CASE WHEN marca IN (102,107) THEN 0 ELSE 8 END AS OreLucru,
CASE WHEN marca IN (102, 107) THEN 8 ELSE 0 END AS OreCO,
CASE marca WHEN 103 THEN 4 ELSE 0 END AS OreNoapte,
CASE marca WHEN 105 THEN 2 ELSE 0 END AS OreAbsente FROM personal;

- 8 iulie
2003 INSERT
INTO pontaje
SELECT marca, DATE'2003-07-08', CASE WHEN marca=103 THEN 0 ELSE 8 END AS OreLucru,
CASE WHEN marca=103 THEN 8 ELSE 0 END AS OreCO,
CASE marca WHEN 104 THEN 2 ELSE 0 END AS OreNoapte,
CASE marca WHEN 105 THEN 1 ELSE 0 END AS OreAbsente FROM personal;

/* pe luna august introducem aceleai date ca i pe iulie, ns cu 0 la absene nemotivate i


orenoapte; n plus, se evit pontajele pentru smbete i duminici 7 INSERT INTO pontaje
SELECT marca, ADD_MONTHS(data,1), oreliufrate, oreco, 0 AS orenoapte, 0 AS absnem FROM
pontaje
WHERE EXTRACT (MONTH FROM data) = 7 AND
8 rows selected.
RTRIM(TO_CHAR(ADD_MONTHS(data,1),DAY)) NOT IN ('SATURDAY', SUNDAY') ;
SQL> |
/* pe luna septembrie, prelum datele din iulie, ca i pentru august; n plus,
nimeni nu mai e n concediu 7 INSERT INTO (SELECT marca, data FROM
pontaje)
Figura 5.7. Inserare & consultare
SELECT marca, ADD_MONTHS(data,2)
Prin
FROM pontajescriptul din listingul 5.3 se introduc pontaje
WHERE EXTRACT (MONTH FROM data) = 7 AND
corespunztoare zilelor de 1, 2, 3, 4, 7 i 8 iulie i pentru lunile
august i septembrie 2003. Pe NOT
RTRIM(T0_CHAR(ADD_MONTHS(data,2),'DAY')) 1 iulie, lucreaz
IN ('SATURDAY*, toi COMMIT;
'SUNDAY'); angajaii. Pe 2,
3, 4, 7 i 8 iulie, angajaii cu mrcile 102 i 107 sunt n concediu. n
data de 7 iulie, angajatul cu marca 103 a lucrat 4 ore n regim de
noapte, iar cel cu marca 105 a chiulit (i l-a aflat eful) 2 ore. 8 iulie
este ziua n care omul muncii cu marca 104 are 2 ore de noapte, iar
cel cu marca 105 a mai tras o porie de chiul, este adevrat, numai
Din
de raiuni
o or. de pur comoditate - ct de pur poate fi comoditatea
- pe lunile august Listing prelum 5.3. nregistrrile
Script de populare din a iulie.
tabeleiPe august,
PONTAJE
angajaii 102 i 107 sunt tot n concediu, n timp ce n septembrie
DELETE FROM pontaje ;
toat lumea e la lucru. Pentru ambele luni nu sunt nici ore lucrate n
- 1 iulie 2003
regim INSERT
de noapte i nici absene nemotivate. n plus, dac 2 iulie
INTO pontaje
cade ntr-o miercuri,
SELECT 2 august este
marca, DATE'2003-07-01', 8, 0, 0,o smbt.
0 FROM personal;Aa c, pentru aceste
dou luni se vor elimina zilele care ar cdea n weekend (smbete i
- 2 iulie 2003
duminici).
INSERT INTO pontaje (marca, data, orelucrate, oreco)
Din punct de vedere"
SELECT marca, SQL,8, 0n
DATE'2003-07-02, interogri
FROM personal WHEREapar destule
marca nouti:
NOT IN (102,107) UNION
SELECT marca, DATE'2003-07-02', 0, 8 FROM personal WHERE marca IN (102,107);
structuri CASE, funciile ADD_MONTHS, RTRIM, TO_CHAR, EXTRACT i alte
bunti
- ce vor fi expuse pe parcursul capitolelor 6 i 7.
3 iulie 2003
INSERT
Analog pot INTO fi
pontaje (marca, data,
populate orelucrate, oreco)
tabelele SPORURI, REINERI i SALARII
_______SELECT marca, DATE'2003-07-03', 8, 0 FROM personal WHERE marca NOT IN (102,107)
pentru o lun dat. Astfel, corespunztor lunii iulie 2003 se
SELECT marca, 2003, 7 F R O M personal ;

INSERT INTO reineri (marca, an, luna)


SELECT marca, 2003, 7 FROM personal ;
Oracle. Ghidul dezvoltrii aplicaiilor profesionale 135
INSERT INTO salarii (marca, an, luna)
SELECT marca, 2003, 7 FROM personal ;
COMMIT ;

5.1.1. Inserri n tabele multiple


Comanda INSERT are i un format de-a dreptul exotic, prin care, simultan, pot fi
introduse linii n dou sau mai multe tabele, pe baza unor condiii aplicate
rezultatului unei fraze SELECT. Astfel, presupunem c se dorete arhivarea
separat, pe luni calendaristice, a pontajelor. De aceea, periodic, din tabela
PONTAJE se vor salva nregistrrile corespunztoare n tabele de genul PONTAJE.
2003 1, PONTAJE_2003_3 etc. Crearea acestor tabele nu ridic probleme. La
nceputul anului 2003 se lanseaz fabulosul script din listing 5.4.
Listing 5.4. Crearea tabelelor de arhivare
CREATE TABLE pontaje_2003_ianuarie AS SELECT * FROM pontaje WHERE 1=2 ;
CREATE TABLE pontaje_2003_februarie AS SELECT * FROM pontaje WHERE 1=2 ;
CREATE TABLE pontaje_2003_martie AS SELECT * FROM pontaje WHERE 1=2 ;
CREATE TABLE pontaje_2003_aprilie AS SELECT * FROM pontaje WHERE 1=2 ;
CREATE TABLE pontaje_2003_mai AS SELECT * FROM pontaje WHERE 1=2 ;
CREATE TABLE pontaje_2003_iunie AS SELECT * FROM pontaje WHERE 1=2 ;
CREATE TABLE pontaje_2003Julie AS SELECT * FROM pontaje WHERE 1=2 ;
CREATE TABLE pontaje_2003_august AS SELECT * FROM pontaje WHERE 1=2 ;
CREATE TABLE pontaje_2003_septembrie AS SELECT * FROM pontaje WHERE 1=2 ;
CREATE TABLE pontaje_2003_octombrie AS SELECT * FROM pontaje WHERE 1=2 ;
CREATE TABLE pontaje_2003_noiembrie AS SELECT * FROM pontaje WHERE 1=2 ;
CREATE TABLE pontaje 2003 decembrie AS SELECT * FROM pontaje WHERE 1=2 ;___________________

Presupunnd c am ajuns n luna octombrie i ultima arhivare a


fost fcut pentru luna iunie, urmtoarea comand INSERT umple"
dintr-o singur micare tabelele corespondente lunilor iulie, august
i septembrie:
INSERT ALL
WHEN EXTRACT (YEAR FROM data) = 2003 AND
EXTRACT (MONTH FROM data) = 7 THEN
INTO pontaje_2003_iulie WHEN EXTRACT (YEAR FROM
data) = 2003 AND
EXTRACT (MONTH FROM data) = 8 THEN
INTO pontaje_2003_august W H E N EXTRACT (YEAR
FROM data) = 2003 AND
EXTRACT (MONTH FROM data) = 9 THEN
INTO pontaje_2003_septembrie
136 Actualizarea tabelelor prin comenzi SQL

SELECT * FROM pontaje

5.2. tergerea liniilor - DELETE


Operaiunea de tergere este mult mai simpl i, statistic vorbind,
este cea care se deprinde cel mai uor, uneori funcionnd chiar mai
bine dect inteniona cel care a lansat-o. n plus, ca i INSERT, DELETE
este deja folosit de cteva capitole, aa c vom cheltui puin timp
i spaiu cu discutarea sa. Prima variant terge toate liniile din
tabela PONTAJE_2003_SEPTEMBRIE n care marca este 101 i data 1
septembrie:

DELETE FROM pontaje_2003_septembrie


WHERE marca = 101 AND data = DATE'2003-09-01' ;

Pentru cazul nostru, o singur linie ndeplinete predicatul


specificat n clauza WHERE. Pentru zpcii, cel mai neplcut la
comanda DELETE este c, atunci cnd se omite specificarea clauzei
WHERE, se terg toate liniile din tabel. Astfel,

DELETE FROM pontaje_2003_septembrie ;

va terge, nendoielnic, toate nregistrrile tabelei


PONTAJE_2003_SEPTEM- BRIE. Noroc cu mecanismul tranzacional i
comanda ROLLBACK, altminteri rata sinuciderilor n rndul
informaticienilor era cu mult mai mare.
Trecnd la lucruri un pic mai dificile, ne propunem ca, o dat
fcut salvarea pontajelor pe luna august 2003 (n tabela
PONTAJE_2003_AUGUST), s tergem liniile respective din tabela
surs - PONTAJE. Comanda de tergere face apel la o subconsultare
prin care se extrag angajaii i zilele ce prezint pontaje pentru
aceast lun i care au fost salvate n tabela-arhiv:

DELETE FROM pontaje WHERE (marca,' data) IN


(SELECT marca, data FROM pontaje_2003 august) ;

Pentru plcerea de a SQL-ui (se pronun e s c h i u e l u i ), folosim


i o variant exotic ce are cam acelai efect ca al ultimei comenzi:

DELETE FROM (SELECT * FROM pontaje ) pol


WHERE EXISTS (SELECT 1
FROM pontaje_2003
WHERE po2.marca=pol.marca AND po2.data=pol.data) ;

Dou elemente rein atenia n mod deosebit. Mai nti, faptul c


n locul numelui tabelei PONTAJE s-a folosit o fraz SELECT. Al doilea
element ine de recursul la o interogare corelat (pentru detalii,
Oracle. Ghidul dezvoltrii aplicaiilor profesionale 137

Consultarea de dup clauza FRGM nu pare a fi de prea mare efect.


Cu totul altfel stau ns lucrurile cnd aceasta va conine o
jonciune. Astfel, s presupunem c, deoarece am fcut arhivarea
pentru septembrie 2003 att a pontajelor, ct i a tabelelor de
sporuri, reineri i salarii, dorim s tergem liniile din SALARII i
SPORURI corespunztoare acestei luni. S ncercm un DELETE mai
special:

DELETE FROM
(SELECT *
FROM sporuri sp INNER JOIN salarii sa
ON sp.marca=sa.marca AND sp.an=sa.an
AND sp.luna=sa.luna WHERE sp.an=2003 AND
sp.luna=9 ) ;

Nu tim la ce v-ai ateptat, ns comanda de mai sus terge


nregistrri, dar numai din tabela SPORURI, dup cum se observ n
figura 5.8. nainte de tergere, ambele tabele joncionate numrau

Figura 5.8. Jonciunea, ca argument al unei comenzi de tergere -


caz 1
n schimb, dac modificm ordinea tabelelor la joncionare,
SALARII este cea din care se va face tergerea:
138 Actualizarea tabelelor prin comenzi SQL

DELETE FROM (SELECT *


FROM salarii sa INNER JOIN sporuri sp
ON sa.marca=sp.marca AND sa.an=sp.an
AND sa.luna=sp.luna WHERE sa.an=2003 AND
sa.luna=9 ) ;
dup cum reiese din figura 5.9.

Figura 5.9. Jonciunea ca argument al unei comenzi de tergere - caz 2

5.3. Modificarea valorilor - UPDATE


Nici comanda UPDATE nu are un format suprtor de complicat,
chestiunile de finee fiind legate de apelul la subconsultrile
corelate. Dac, spre exemplu, conducerea firmei ia eroica decizie de
a mri salariile orare tuturor angajailor cu 10%, incrementarea
atributului SalOrar din tabela PERSONAL s-ar realiza prin comanda:

UPDATE personal SET salorar = salorar * 1 . 1 0 ;

Deoarece nu apare clauza WHERE, modificarea precizat n clauza


SET va afecta toate liniile tabelei, inclusiv pe cele care se refer la
colaboratori. Excluderea colaboratorilor de la aceast bine venit
operaiune se realizeaz astfel:
UPDATE personal
SET salorar = salorar * 1 . 1 0
WHERE colaborator o 'N' ;
MARCA AM LUNA ORELUCRATE ORECO

181 2883 7 48 8
182 2883 7 16 32

Oracle. Ghidul dezvoltrii aplicaiilor profesionale 139


Actualizarea tabelelor prin comenzi SQL
140

Presupunem
), c procentul de cretere este difereniat pe
compartimente:
oreco = ( 10% pentru producie, 8% pentru contabilitate i
12% pentru IT (dac
SELECT autorii acestei cri erau contabili, fii convini
SUM (oreco)
c alteleFROM
ar fi fost procentele
pontaje po !). Cea mai banal soluie este format
WHERE EXTRACT
din trei comenzi UPDATE: (YEAR FROM data)=sa.an AND
r EXTRACT (MONTH FROM data) = sa.luna
AND po.marca=sa.marca )
UPDATE
WHERE anpersonal
= 2003 AND luna = 7 ;
SET salorar = salorar * 1.10 WHERE compart = 'PROD' ; UPDATE
Comanda poate fi simplificat, prin calcularea simultan a celor
personal
SET salorar o
dou atribute folosind = singur
salorar *interogare.
1.08 WHERE compart = 'CONTA' ; UPDATE
personal
SET salorar = salorar * 1.12 WHERE compart = 'IT' ;
UPDATE salarii sa
SET (orelucrate, oreco) = (
Nu putem
SELECT totui lua o min de
SUM (orelucrate), cunosctori SQL cu aa o variant
SUM(oreco)
primitiv. Astfel
FROM stau po
pontaje lucrurile dac folosim o structur de tip CASE:
WHERE EXTRACT (YEAR FROM data)=sa.an AND
UPDATE personal
EXTRACT (MONTH FROM data) - sa.luna AND
SET salorar
po.marca=sa.marca
= salorar *
) CASE compart
WHERE an = 2003
WHEN AND lunaTHEN
'PROD' = 7 ; 1.10
WHEN 'CONTA' THEN 1.08
Oricare ar fi varianta,
WHEN 'IT' rezultatul
THEN 1.12ar trebui s fie cel din figura
5.10. ELSE 1
END

Putem chiar
SQL UPDATE salarii exagera,
sa folosind o interogare corelat:
2 SET (orelucrate, oreco) - (
3 SELECT SUH (orelucrate), SUM(oreco)
UPDATE
4 personal
FROM pontaje po pl
5 SET EXTRACT
WHERE salorar =FROM
(YEAR salorar * AND
data)*sa.aii
6 EXTRACT (MONTH FROM data) - sa.luna AND po.raarca-sa.aiarca
7 ) (SELECT CASE compart
8 WHERE an = 2883 AND luna WHEN
-7; 'PROD' THEN 1.10
8 rows updated. WHEN 'CONTA' THEN 1.08
WHEN 'IT' THEN 1.12 ELSE
SQL> SELECT inarca, an, luna,1
orelucrate,
END oreco FROM salarii WHERE luna7
2l FROM personal p2 WHERE pl.marca=p2.marca) ;

In general ns, interogrile corelate reprezint prea mult pentru


o asemenea problem. Altfel stau lucrurile pentru cazurile
urmtoare. Cmpurile OreLucrate i Or eCO din SALARII centralizeaz
orele lucrate i de concediu pentru un angajat pe o lun. Dac dorim
s actualizm cele dou atribute pentru iulie 2003 i presupunem c
pentru aceast lun exist cte o linie corespunztoare fiecrui
angajat, putem ncerca o comand de genul:

UPDATE salarii sa
SET orelucrate = (
SELECT SUM (orelucrate)
FROM pontaje po
WHERE EXTRACT (YEAR FROM data)=sa.an AND
EXTRACT (MONTH FROM data) = sa.luna
Oracle. Ghidul dezvoltrii aplicaiilor profesionale 141
183 2003 7 40 8
184 2803 7 48 8
1 05 2083 7 48 0

s
2083 7 48 8
186
107 2883
UPDATE 7
(SELECT
16
marca,
32
an, luna, orenoapte FROM sporuri)
108 2083 SET orenoapte
7 48 = 8

rf* j *lu(SELECT SUM(orenoapte) 'cfx'

Oracl< SQL s
FROM pontaje p
i File dit Search Options Help

WHERE p. marca=s.marca AND


|SQL> SELECT FROM sporuri WHERE
EXTRACTluna=7;
(YEAR FROM data)=s.an
an=2003 fiHO

MARCA
AH LUNA AND EXTRACT
SPUECH ORENOAPTE (MONTH
SPN0APTE ALTESP FROM data)=s.luna
2003 7 )
101
2003
WHERE
7
an=2003 AND luna=7
102
103 2003 7
104 2003 7
105 2003 Valorile
7 nregistrrilor din tabela SPORURI de dinainte i de dup
2003 7
comanda UPDATE sunt cele din figura 5.11.
106
107 2003 7
2003 7
106

18 rows selected -

|SQL> UPDATE (SELECT narea, an, luna, orenoapte FROM sporuri) s


2 SET orenoapte * (SELECT SUH(orenoapte) FROM pontaje p
3 WHERE p.marcaos.narea AND EXTRACT (VEAR FROM data)~s.an

4 AND EXTRACT (N0NTH FROM datais.luna


5 )
1 6 WHERE an= 2003 AND luna-7

8 rows updated.

jsQL> SELECT * FROM sporuri WHERE an=2003 AND


luna=7;

MARCA AH LUNA SPUECH ORENOAPTE SPN0APTE ALTESP

101 2003 7 0
102 2003 7 0
103 2003 7 4
104 2003 7 2
105 2003 7 0
106 2003 7 0
107 2003 7 0 , , *n . *j i f-.
2003 7
108 0

18 rows selected

SQL>
LI___
>

8 rows selected.

SQL> I_____________________________________________________________________________________

Figura 5.10. Actualizarea atributelor SALARII.OreLucrate i


SALARII.OreCo

i n cazul comenzii UPDATE, n locul numelui de tabel se poate


specifica o subconsultare. Spre exemplu, dac n tabela SPORURI se
dorete centralizarea orelor de noapte pentru luna iulie 2003, se
142 Actualizarea tabelelor prin comenzi SQL

SALARII.orelucrate i SALARII. oreco, am putea fi tentai s lansm


comanda:

UPDATE
sporuri.an, sporuri.luna,
orenoapte, orelucrate, oreco
FROM sporuri INNER JOIN salarii ON
sporuri.an=salarii.an AND
sporuri.luna=salarii.luna
AND sporuri.marca=salarii.marca) s
SET (orelucrate, oreco, orenoapte) =
{SELECT SUM(orelucrate), SUM (oreco), SUM(orenoapte)
FROM pontaje p WHERE p.marca=s.marca AND EXTRACT
(YEAR FROM data)=s.an
AND EXTRACT (MONTH FROM data)=s.luna

WHERE an=2003 AND luna=7

Mesajul recepionat - vezi figura 5.12 - este unul clar: Oracle nu


are nimic mpotriv dac subconsultarea prezint o jonciune, ns
nu se poate modifica dect una dintre tabele.

SQL> UPDATE (SELECT sporuri.narea, sporuri.an, sporuri.luna,


2 orenoapte, orelucrate, oreco
3 FROM sporuri INNER JOIN salarii ON
sporuri.an-salarii.an AHO sporuri.luna~salarii.luna ANO sporuri.marca-salarii.narea) s
5 SET (orelucrate, oreco, orenoapte) (SELECT SUN(orelucrate), SUN (oreco), SUM(orenoapte)
6 FROM pontaje p WHERE p.narca-s.narea AND EXTRACT (VEAR FROM data)s.an
7 AND EXTRACT (MONTH FROM data)=s.luna
8 )
9 WHERE an2003 AND luna-7 10 /
SET (orelucrate, oreco, orenoapte) > (SELECT SUM(orelucrate), SUN (oreco), SUH(orenoapte)

ERROR at line 5:
ORA-01776: cannot nodiFy More than one base table through a join uiew

Figura 5.12. Tentativ (nereuit) de actualizare simultan a dou tabele

Probabil c pn acum nici una dintre comenzi nu a creat


frisoane, aa c ncercm altceva: actualizarea tabelei SPORURI
pentru luna iulie 2003 pe baza datelor din PONTAJE, PERSONAL i
TRANSE_SV, ultima pentru calculul sporului de vechime. n prealabil,
populm tabela TRANSEJ3V - listing
Listing 5.5. nregistrrile 5.5.TRANSEJ3V
tabelei

INSERT INTO transe_sv VALUES (0,3,0);


INSERT INTO transe_sv VALUES (3,6,5);
INSERT INTO transe_sv VALUES (6,10,10);
5.11. Actualizarea" unei subconsultri
Figura(10,15,14)
INSERT INTO transe_sv VALUES
INSERT INTO transe_sv VALUES (15,20,18)
Atunci
INSERT cndVALUES
INTO transe_sv subconsultarea
(20,99,25) ce substituie numele unei tabele
conine o jonciune, Oracle devine mult mai reticent. Astfel, dac am
COMMIT
dori s ;___________________________
calculm, dintr-o singur micare, pentru luna iulie 2003,
att SPORURI . orenoapte, ct i
144
Oracle. Ghidul dezvoltrii aplicaiilor profesionale
Actualizarea tabelelor prin comenzi
143 SQL
HAH AN LU SPUEC ORENOA SPNOA
CA
1 2 NA
7 11446 H PTE PTE
fi e
81
162 083 >
2 7 38408 86
Oracle SQL'Plus 6 a
183 803 7Liniile
200 956
File 0 Search 4Qpaons
acesteia
Edit 41660
vor s spun c, pentru angajaii cu un numr de
Help
164 3 7 12388
280 0U 2 23008
185 3ani7 de
280 16290
SQL> 88
vechime cuprins
UPDATE fl
sporuri sp fi ntre 0 i 3, procentul .sporului de vechime
166 208 72 84568
SET spuech - 6 6
167 3este
280 73 zero
43268
( 8(prima 6nregistrare),
8 cei cu numrul ntre 3 i 6 benriciaz
163 200 7 35508 6 6 salorar
A SELECT ROUND((3UM(orelucrate * procentsu ) *
3de 55%SUH(oreco8
spor de vechime .a.m.d. Acest procent este aplicat venitului
* salorarco * procent_sv )) 7180,-3)
6 FROH personal pe INNER JOIN pontaje po ON pe.narca-po.narca
de 8baz
7 INNERpeJOINluna
transe respectiv,
su ON TRUNC(HONTHScalculat
BETWEEN ( ca sum ntre venit din lucrul
DATE'2 883- 07 - 01', datasu )/l2,8) >= ani linita_inf AND
efectiv
9 TRUNC(HONTHS_BETWEEN
(OreLucrate *< SalOrar) i venitul
10 DATE'2003-87-01', datasu )/12,0) < ani_linita_sup
din concedii de odihn (OreCO
11 GROUP BV pe.narca, EXTRACT (VEAR FROH data), EXTRACT (HONTH
* SalOrarCO). FRON data)
12 HAUING pe.narca-sp.narca AND EXTRACT (VEAR FROH data)-sp.an AND
innd
13 EXTRACT seama
18 ).
(NONTH FROH c
data)sporul
- sp.luna pentru orele de noapte este de 15%,

actualizm
15 orenoapteliniile
- tabelei
(SELECT SPORURIpontajeWHERE
SUH(orenoapte)FROH
16 EXTRACT (VEAR FRON data)-sp.an AND
astfel: narca-sp.narca AND
17 EXTRACT (NONTH FROH data) - sp.luna ),
18 spnoapte -
UPDATE
19 ( sporuri sp
SET
20 SELECT spvech =
ROUtd)(SUH(orenoapte
21 FROH personal pe INNER JOIN
*salorar .15 ),-3)
pontaje po ON pe.narca-po.narca
22 (
GROUP BV pe.narca, EXTRACT (VEAR FROH data), EXTRACT (HONTH FROH data)
23 HAUING pe.narca-sp.narca AND EXTRACT (VEAR FROH data)-sp.an
ANDSELECT ROUND((SUM(orelucrate
20 EXTRACT (MONTH FROM data) - sp.luna * salorar * procent_sv ) +
25 ) SUM(oreco * salorarco * procent_sv )) /100,-3) FROM personal pe
26 /
INNER
8 rows updated.
JOIN pontaje po ON pe.marca=po.marca INNER JOIN
SQL> SELECT * transe_sv
FROH sporuri ON
WHERETRUNC{MONTHS_BETWEEN
an-2883 At luna-7; ( DATE'2003-07-
01' , datasv ) / 1 2 , 0 ) >= ani_limita_inf AND
TRUNC(MONTHS_BETWEEN ( DATE' 2003-07-01', datasv
) / 1 2 , 0 ) < ani_limita_sup
GROUP BY pe.marca, EXTRACT (YEAR FROM data),
EXTRACT (MONTH FROM data)
HAVING pe.marca=sp.marca AND
EXTRACT (YEAR FROM data)=sp.an AND EXTRACT (MONTH
FROM data) = sp.luna ),
orenoapte =
(SELECT SUM (orenoapte) FROM pontaje WHERE
marca=sp.marca AND
EXTRACT (YEAR FROM data)=sp.an AND
EXTRACT (MONTH FROM data) = sp.luna ), spnoapte
=
(
SELECT ROUND(SUM(orenoapte * salorar * .15 ) , - 3 ) FROM
personal pe INNER JOIN pontaje po ON pe.marca=po.marca
GROUP BY pe.marca, EXTRACT (YEAR FROM d a t a ) ,
EXTRACT (MONTH FROM data)
HAVING pe.marca=sp.marca AND
EXTRACT (YEAR FROM data)=sp.an AND
EXTRACT (MONTH FROM data) = sp.luna
)
Execuia i rezultatul SQL*Plus pentru aceast comand simt cele
din figura
5.13.
Oracle. Ghidul dezvoltrii aplicaiilor profesionale 145

iulie pentru fiecare angajat. Dup aceast operaiune, brusc ne dm


seama c mai trebuie introduse pontajele pentru 10 i 11 iulie. Mai
mult, ncepnd cu data de 10 iulie avem i doi boboci" la firm,
trecui pe nedrept cu vederea.
Listing 5.6. Doi angajai i alte trei zile de pontaje
INSERT INTO personal VALUES (seq_marca.NextVal, 'Primul Angajat Nou, IT,
DATE'2003-07-10', 55500, 0, ' N ' ) ;
INSERT INTO personal VALUES (seq_marca.NextVal, 'Al Doilea Angajat Nou', PROD, DATE'2003-07-10',
50500, 0, ' N * ) ;

- 9 iulie 2003
INSERT INTO pontaje
SELECT marca, DATE'2003-07-09', CASE WHEN marca=103 THEN 0 ELSE 8 END AS OreLucru, CASE
WHEN marca=103 THEN 8 ELSE 0 END AS OreCO,
CASE marca WHEN 104 THEN 3 ELSE 0 END AS OreNoapte,
CASE marca WHEN 105 THEN 1 ELSE 0 END AS OreAbsente
FROM personal;

- 10 iulie 2003
INSERT INTO pontaje
SELECT marca, DATE'2003-07-10, CASE WHEN marca=103 THEN 0 ELSE 8 END AS OreLucru, CASE
WHEN marca=103 THEN 8 ELSE 0 END AS OreCO,
CASE marca WHEN 110 THEN 2 ELSE 0 END AS OreNoapte,
0 ALTESP

FROM personal;

- 11 iulie 2003
INSERT INTO pontaje
SELECT marca, DATE'2003-07-11, CASE WHEN marca=103 THEN 0 ELSE 8 END AS OreLucru, CASE
WHEN marca=103 THEN 8 ELSE 0 END AS OreCO,
CASE marca WHEN 110 THEN 3 ELSE 0 END AS OreNoapte,
8 rows selected.
0
SQL> i <
FROM personal;
COMMIT ;_________________________________________________________________________________
Figura 5.13. Un UPDATE ceva mai pretenios

Aceste noi nregistrri trebuie cumulate datelor deja existente,


ceea ce presupune, pe de o parte, incrementarea orelor lucrate i de
5.4. O comand recent: MERGE
concediu cu orele celor trei zile de pontaje pentru vechii" angajai,
n timp ce, pentru nou-venii, trebuie inserat cte o nregistrare n
Nu, nu e nici o trimitere la O m u l r e c e n t al lui H.R. Patapievici (mai
SALARII. Operaiunea, complicat n aparen, poate fi tranat
ales c aceast comand nu are nimic postmodern n ea) i nici la
printr-o comand MERGE:
puseurile belicoase ale lui I.B. Lefter vizavi de cartea cu pricina. Pur
i simplu, cei INTO
MERGE de lasalarii
Oracle SA s-au
USINGgndit
(SELECT (n-avem idee dac au fost
primii sau nu) la (YEAR
EXTRACT o comand care s
FROM data) AS fie
an,o combinat
INSERT-UPDATE.
EXTRACT (MONTH FROM data) AS luna,
Comenzilemarca,
UPDATE SUM(orelucrate) AS orelucrate,
prin care calculm orele lucrate, de concediu
SUM(oreco) AS oreco
sau de noapte funcioneaz corect numai dac n prealabil s-a fcut
FROM pontaje
inserarea de nregistrri corespunztoare n SALARII i SPORURI. Pe
WHERE EXTRACT (YEAR FROM data) = 2 0 0 3 AND
de alt parte,
EXTRACTcomanda
(MONTH FROM INSERT este
data) = 7maiANDnimerit
EXTRACT dup scenariul
totul sau
(DAYnimic",
FROM data) o recalculare
>= 9 GROUP BY a EXTRACT
atributelor
(YEAR centralizatoare
reclamnd un DELETE
FROM d a t a ) , prealabil.
S lum un exemplu.
EXTRACT (MONTH Scriptul
FROM d adin
t a ) ,listing
marca 5.3 conine secvena de
populare) PO
a ONtabelei PONTAJE pentru lunile iulie, august i
MARCA OREC
ORELUCRATE O
181 48 8
182 16 32
183 40 8
1 146
04 48 6 Actualizarea tabelelor prin comenzi SQL
185 48 0
1flfi 48 8
187 16
(SA.an 32
=8 PO.an AND SA.luna=PO.luna AND
188 48
8 rows SA.marca = PO.marca )
selected. WHEN MATCHED THEN
UPDATE SET SA.orelucrate = SA.orelucrate +
PO.orelucrate,
SA.oreco = SA.oreco + PO.oreco
WHEN NOT MATCHED THEN
INSERT (SA.an, SA.luna, SA.marca, SA.orelucrate, SA.oreco)
VALUES (PO.an, PO.luna, PO.marca,
PO.orelucrate, PO.oreco)
Tabela specificat dup clauza INTO este cea n care vor fi
efectuate actualizrile - n cazul nostru, SALARII (sinonim local SA).
Dup clauza USING este plasat fraza SELECT, care centralizeaz
orele lucrate i de concediu pentru fiecare angajat.
MARCA OREC
ORELUCRATE
* Oracle SQL*Plus O I-
189 File Edit Search
24 .Options Help
0
110 SQL> SELECT
24 marca, orelucrate,
B oreco FROM salarii WHERE an-2083 AND luna7 ; A
181 72 0
102 40 32
183 40 32
184 72 0
185 72 0
186 72 0
187 40 32
1 08 72 0
1 0 rows
selected.

SQL> MERGE INTO salarii SR USING


2 (SELECT EXTRACT (VEAR FROM data) AS an, EXTRACT (MONTH FROM data) AS luna,
3 marca, SUM(oreluerate) AS orelucrate, SUM(oreco) AS oreco
4 FROM pontaje
5 WHERE EXTRACT (VEAR FROM data) - 2803 AND EXTRACT (MONTH FROM data) - 7
6 Atffi EXTRACT (DAV FROM data) >- 9
7 GROUP BY EXTRACT (VEAR FROM data), EXTRACT (MONTH FROM data), area
B ) PO
9 ON (SA.an - PO.an AND SA.luna*PO.luna AND SA.marca - PO.raarca )
10 WHEN HATCHED THEN
11 UPDATE SET SA .orelucrate - SA.orelucrate * PO.orelucrate, SA.oreco - SA.oreco PO.oreco
12 WHEN NOT HATCHED THEN
13 INSERT (SA.an, St).luna, St).marca, St).orelucrate, SA.oreco)
14 VALUES (PO.an, PO.luna, PO.marca, PO.orelucrate, PO.oreco)
15 /
18 rows merged.
SQL> SELECT marca, orelucrate, oreco FROM salarii WHERE an-2003 AND luna-7 ;
148Oracle. Ghidul dezvoltrii aplicaiilor profesionale
Actualizarea tabelelor prin comenzi SQL
147
vorbim de cazul !invers,
Se iau nn care am nclca i eventuala restricie referenial.
Atenie considerare numai noile pontaje, de dup 9
De
asemenea, iulie,
dac pentru c celelalte
la un moment sunt deja
dat ne-am centralizate.
hotr s renunm Prin urmare, unei -
la detaliile
rezultatul subconsultrii, care va fi referit/ drept PO, conine
facturi, ar cte fi ofoarte
linie normal s renunm
pentru fiecare angajaticelaare antetul"
mcar ofacturii respective.
zi lucrat
'
* sau de concediu n perioada 9-31 iulie 2003. Pentru raportare
la SALARII (SA), n PO au fost incluse i coloanele An i Luna.
5.5.1. Comanda COMMITUPDATE de pe ramura WHEN MATCHED se va executa
i ROLLBACK
numai pentru angajaii care au deja, la momentul curent, o
Revenind nregistrare n SALARII
la cazul nostru pentru
concret anul pontaje
(despre i luna de referin.
i salarii), Practic, se
o secven
t r a n zvor
a c iincrementa
o n a l de cele dou cmpuri
operaiuni ar putea i OreCO)
fi urmtoarea:
(OreLucrate cu valorile
consemnm
calculate
orele lucrate de dectresubconsultare
un angajat n(PO).tabela Liniile
PONTAJE,subconsultrii
apoi calculm ce nusau se
gsesc
recalculm n SALARII
sporurile (n sensul
(tabela c nu
SPORURI) i,exist
n celenregistrare corespondent
din urm, actualizm i
pentru
tabela SALARII. care valorile atributelor An, Luna i Marca s fie identice) vor
fi adugate
nainte s trecem tabeleila prin intermediul
lucru", trebuie comenzii
nentrziatINSERT de pe ramura
menionat c o
WHEN NOT MATCHED. Coninutul
COM P A DATASO
tranzacie va ncepe fie imediat dup conectarea laR Q tabelei SALARII,
SALOR A SALORARnainte
serverul
C
de bazedup
i de
C
2 00 1 A ng ajat 21 CON TA 1 5- JUL - 3 30 00 28 00 0 H
date (de exemplu, printr-o sesiune SQL*PLUS), 91 fie dup o comand care a
2 00 2 A ng ajat 22 C0 H TA 1 7- M AY- l 30 80 30 00 0 N
ncheiat
A ng ajattranzacia precedent F1 (adic 3ROLLBACK sau
00 COMMIT).
2 00 3 5.5.23 Tranzacii FIN 2
H 0
9 1-
9 3-
9 FEB-
M AY- 8 90
7 00 00
85 00 0 H
65 00 0 H
aj at 2*
2 60 1 AngSQL> /
2 00 5 A ng ajat ROLLBACK;
25 8 7-
H ARK1 5 M AY- 45 Q00 40 00 0 H
93
Rollback complete.
Unul dintre lucrurile considerate agasante" de ctre primii venii n
lumea bazelor de
SQL> date Oracle este faptul c, dup o sesiune
St}L> SELECT * FROH personal;
fructuoas" cu SQL*PLUS (sau alt client cu o fa" mai
prietenoas), sesiune ncheiat prin super"-comanda EXIT, acetia
constat c la reconectare toate datele atent" introduse sau
modificate anterior nu se mai regsesc... sunt disprute i, din
pcate, definitiv pierdute. S fie un server de baze de date de
calibrul Oracle att de neatent" cu datele noastre ?!?
SQL> iSELECT
totui, cteva
FROH pagini
pontaje ORDERmai nainte ntlnim o fraz tulburtoare
BV narea;
... ultima comand, COMMIT, are drept scop finalizarea
t r a n z a c i e i i, n consecin, s c r i e r e a d e fi n i t i v a l i n i i l o r
n t a b e l " . Pentru a elimina, n cele din urm, frustrrile mai sus
menionate, a venit vremea s dezvluim tlcul" acestor cuvinte i,
mai cu seam, a termenului tranzacie".

Pe scurt, o t r a n z a c i e reprezint modalitatea prin care se poate


mpacheta ntr-o singur unitate de lucru o secven de operaii
privind datele dintr-o baz de date. Aceast unitate se remarc n
principal prin a t o m i c i t a t e sau, cu alte cuvinte, fie vor fi pstrate
permanent n baza de date toate modificrile operate (cazul
COMMIT), fie se va renuna la toate acestea (cazul ROLLBACK).
Unitatea de lucru care se suprapune peste o tranzacie este
determinat (i delimitat mai ales) de prelucrrile din sistemele de
aplicaii. Astfel, o tranzacie poate nsemna introducerea
< _______________________________________________________________________________ > unei
facturi, ceea ce se materializeaz de regul prin introducerea liniei
Figura 5.14. Funcionarea comenzii MERGE
corespunztoare ntr-o tabel FACTURI, urmat de introducerea
M AR DATA 0 RELUC 0RE C0 OREN OA 0 REABS
CA RATE PTE N EH
2 0 07 -F EB-
0 1 83 6 0 0 0
20 10 -F EB- 10 0 2 0
0
210 03
11 -F EB- 4 0 4 0
00
2 1 03 -F EB-
07 6 0 0 0
0
220 83
10 -F EB- 10 0 2 0
0
220 83
07 -F EB- 6 0 0 0
0
230 83
07 -F EB- 6 0 0 0
00
2 4 B3 -F EB-
11 4 0 4 0
0
248 83
07 -F EB- 6 0 0 0
05 O3
Oracle. Ghidul dezvoltrii aplicaiilor profesionale 149

Tranzacia noastr se va deraia n felul urmtor:

Pa s u l 1 - Inserm o nou linie n PONTAJE, linie care consemneaz


orele de noapte lucrate de ctre salariatul 2001 n data de
12/02/2003.
INSERT INTO pontaje(marca, data, orelucrate, orenoapte) VALUES(2001,
TO_DATE(12/02/2003', dd/mm/yyyy'), 8, 4);

Pa s u l 2 - Actualizm linia din tabela SPORURI corespunztoare


salariatului mai sus menionat pentru luna februarie. Ne intereseaz
(deocamdat) sporul de noapte i totalul orelor noapte:

UPDATE sporuri SET spnoapte = .15 *


(SELECT salorar FROM personal WHERE marca = 2001) * (SELECT
SUM(orenoapte) FROM pontaje WHERE marca = 2001 AND
TO_CHAR(data, mm') = 2 AND TO_CHAR(data, 'yyyy') = 2003),
orenoapte =
(SELECT SUM(orenoapte) FROM pontaje WHERE marca
= 2001 AND T0_CHAR(data,'mm') = 2 AND
T0_CHAR(data, yyyy') - 2003)
WHERE marca = 2001 AND luna = 2 AND an = 2003;

Pa s u l 3 - Ardem de nerbdare s aducem i la cunotina" liniei


corespunztoare (marca 2001, luna februarie din 2003) din tabela
SALARII modificrile intervenite n tabela PONTAJE. ns, dup cum
se observ din figura 5.15, aceast nregistrare nu exist. Ca
urmare, mai nti o crem:

INSERT INTO salarii (marca, an, luna)


VALUES (2001, 2003, 2);

apoi o vom actualiza:

UPDATE salarii SET orelucrate =


(SELECT SUM(orelucrate) FROM pontaje WHERE marca = 2001
AND TO_CHAR(data, yyyy') = 2003 AND TO_CHAR(data, mm')
= 2), oreco = (SELECT SUM(oreco) FROM pontaje WHERE marca
= 2001 AND TO_CHAR(data, 'yyyy') = 2003 AND
TO_CHAR(data, mm) - 2)
WHERE marca = 2001 AND an = 2003 AND luna = 2;

9 rows
(ca selected.
s par o tranzacie mai lung, am recurs la dou comenzi SQL,
dei operaia anterioar se putea face foarte bine printr-una
SQL> SELECT * FROM sporuri;
singur).
In MARCA
fine, putemAN verificaLUNA
situaia la acest
SPUECH moment
OREHQAPTE (vezi figura
SPHQAPTE 5.16).
ALTESP
Dac starea bazei
2001 2 003
de date 2
se va pstra aa cum este prezentat n
figura 5.16 depinde de modul
in careSELECT
SQL> vom ncheia tranzacia:
* FRON salarii; no rows selected
/

Figura 5.15. Situaia iniial n tabelele ce urmeaz tranzacionate"


Oracle. Ghidul dezvoltrii aplicaiilor profesionale 151
150 Actualizarea tabelelor prin comenzi SQL
INSERT INTO pontaje(marca, data, orelucrate, orenoapte)
~ prin COMMIT,
VALUES(2001, astfel nct dup mesajul
TO_DATE(12/02/2003, Commit
'dd/mm/yyyy), complete"
8, 4);
modificrile vor deveni permanente n baza de date i, de
Paasemenea, vizibile i(anticipnd
s u l 2 - Prevztori ctre ceilali utilizatori; pasului urmtor),
fatalitatea"
declarm un
- prin ROLLBACK, i atunci vom reveni la starea din figura 5,15
savepoint:
SQL> SELECT * FROM pontaje ORDER BY marca;

SAVEPOINT act_pontaje;
MA DATA ORELU OREC OREHO QREAB
RCA
28( 87- CRATE
6 O
0 APTE8 SNEM
8
11 18-
208 FEB-83 18 0 2 e
288 11- 4 0 4 0
288 12- 8 0 4 0
288 87- fi 0 0 0
280 18- 10 0 2 6
208 87- fi 0 0 8
288 B7- 6 8 0 8
288 11- 4 8 4
288 87- 6 6 6 0
FROH pontaje i ORDER BV marca;
SQL> SELECT 10 rows selected.

DATASQL>
ORELUCRATE
SELECT * FROM sporuri; 0REC0 ORENOAPTE 0REABSNEH
HARCA
MARCO AN LUMA SPUECH 0REN0APTE SPNOOPTE ALTESP

2001 2003 2 10 49500

SQL> SELECT * FROM salarii;

MARCA AH LUNA ORECO UENITBAZA SPORURI IMPOZIT REINERI

ORELUCRATE
2001 2003 2 28 0

Figura 5.16. Situaia n tabelele bazei de date dup derularea operaiilor


tranzacionale

5.5.2. Puncte de salvare: SAVEPOINTS


Ce s-ar ntmpla ns dac, dup ce am actualizat tabela SPORURI,
realizm c am greit (spre exemplu, am actualizat nregistrarea
altui salariat). Dup cum s-a derulat tranzacia n momentul
anterior, am avea dou alternative: fie vom mai executa un UPDATE,
sau mai multe, de corecie (dac tim exact ce avem de corectat i
cunoatem n detaliu consecinele acestei operaiuni, consecine pe
care ni le asumm), fie recurgem la ROLLBACK i ncepem tranzacia
de Ia capt. Dac de la nceputul tranzaciei nu s-au derulat prea
multe operaiuni, atunci deranjul n-ar fi prea mare, dar dac am
executat mcar vreo 10 comenzi, atunci situaia se complic.
Din fericire, exist posibilitatea segmentrii unei tranzacii
principale n sub- tranzacii mai mici, care s poat fi anulate
individual n ordinea nceperii lor (nu exist i posibilitatea comiterii
lor individuale: primul COMMIT va ncheia ntreaga tranzacie, adic
suma segmentelor tranzacionale ncepute pn n acel moment).
Comanda care ne scoate astfel la liman" este SAVEPOINT.
Ca exemplu, s relum secvena de operaii anterioare din starea
al, descris n figura 5.17.
2001 07-FEB-03 6 0 0 0
2001 10-FEB-03 10 0 2 0
2001 11-FEB-03 4 0 4 0
2002 07-FEB-03 6 0 0 0
2002 10-FEB-03 10 0 2 0
2003 07-FEB-03 0
Actualizarea tabelelor prin comenzi SQL
152 6 0 0
2004 07-FEB-03 6 0 0 0
2004 11-FEB-03 4 0 4 0
INSERT
2005 O7-FEB-03 INTO6
salarii (marca,
0 an,
0 luna) 0

9 rows selected. VALUES (2002, 2003, 2);

FROH sporuri;
SQL> SELECT
apoi o vom actualiza:
AN LUNA SPUECH ORENOAPTE SPNOAPTE ALTESP
HflRCA
UPDATE salarii SET orelucrate =
2003 2
2001 (SELECT SUM(orelucrate) FROM pontaje WHERE marca =
2003 2
2002 2001 AND TO_CHAR(data, 'yyyy') = 2003 AND TO_CHAR (data,
SQL> SELECT FROH salarii;
'mm') - 2), oreco = (SELECT SUM(oreco) FROM pontaje
no rows selected WHERE marca - 2001 AND TO_CHAR(data,
yyyy') = 2003 AND TO_CHAR(data, mm) = 2) WHERE
MARCA AN LUNA SPUECH ORENOAPTE SPN0APTE ALTESP
marca = 2002 AND an = 2003 AND luna = 2;
2003 2
2001
2003 2 10 49508
n fine, verificm rezultatul tranzaciei noastre i constatm
2002

neconcordanele fa de rezultatul scontat (vezi figura 5.18).

SQL> SELECT FROM sporuri;

Figura 5.17. Situaia iniial a bazei de date

Pa s u l 3 - Actualizm linia din tabela SPORURI, ns, din


greeal (neprovocat), lum n considerare salariatul 2002:

UPDATE sporuri SET spnoapte = .15 *


(SELECT salorar FROM personal WHERE marca = 2001) *
(SELECT SUM(orenoapte) FROM pontaje WHERE marca = 2001
AND TO_CHAR(data, mm) = 2 AND TO_CHAR(data, yyyy') =
2003), orenoapte = (SELECT SUM(orenoapte) FROM pontaje
WHERE marca = 2001 AND TOJOHAR(data, 'mm') = 2 AND
TO_CHAR(dat a, yyyy') - 2003)
WHERE marca = 2002 AND luna = 2 AND an = 2003;
Inconsistena este dat de faptul c linia salariatului cu marca
2002 din tabela SPORURI este actualizat cu datele salariatului cu
marca 2001.

Pa s u l 4 - Persistm n eroare i actualizm i tabela SALARII,


ns fr a reflecta, din nefericire, modificrile intervenite n tabela
PONTAJE. Dar, dup cum se observ din figura 5.15, aceast
nregistrare nu exist. Ca urmare, mai nti o crem:
SQL> SELECT FROM salarii;

MARCA AN LUNA ORELUCRATE ORECO UENITBAZA SPORURI IMPOZIT REINERI

2002 2003 2 28 0

Figura 5.18. Relevarea inconsistentelor introduse


Dac am fost prevztori i am trecut prin pasul 2, atunci putem
lansa comanda;
ROLLBACK TO SAVEPOINT actjpontaje;

i vom anula efectul operaiilor din paii 3-4, pstrnd ceea ce am


muncit n pasul 1 (vezi figura 5.19). Dup care putem relua, cu
atenie, irul modificrilor n tabelele SPORURI i SALARII.
153
Oracle. Ghidul dezvoltrii aplicaiilor profesionale Interogri157
156158Oracle. Ghidul dezvoltrii aplicaiilor profesionale Interogri SQL
SQL
M ARC A N UM EPR EH COM P B ATAS U SALORA SAL 0 RAR COL ABOR
1 01 Ang aj at
SQL>
SELECT
Care
1
SELECT sunt
*SQL>
* ART
angajaii
IT 1 2- 0cu
CT-salariul
88 56orar
R
00 0 cuprins
C0 ATOR
55 B80 Nntre 55000 i
ROLLBACK TO SAUEPOINT act_pontaje; Rollback
2 FROM
65000
1 03 Ang aj
FROM personal
personal
at 3 lei ? IatIT o soluie
8 2- JUL fr
- 76 BETWEEN:
67 50 0 6 60 00 N
3 WHERE
1 05 Ang 5 compart
aj1atWHERE compart
IT
complete. ==1 'PROD'
2- N0 U- OR compart
62 50 0 =6 20 00 N
1 09 Prim'ITul 'IT' ORDER
Ang a jat IT BY compart,
1 7 JUL - 03datasv
7 0- 55 50 0 8N
SELECT *SELECT
N o u 4 ORDER BYSQL> numepren * FROM pontaje ORDER BV narea;
5 / FROM personal
A doua
WHEREsoluie se>=
salorar nfrupt" dinsalorar
55000 AND operatorul IN:
<= 65000
Capitolul 6
SELECT *
i una
FROMcu:
personal
SELECT *
ORDER personal
BY compart, datasv
Interogri SQL
WHERE compart IN 'PROD' , 'IT' )
FROM
SQL> |
COM P DATASU SALORA SALORA COL A BOR
WHERE salorar ART 6.1.
Figura BETWEEN
Prima 55000 AND
interogare R 65000
RCO ATOR
1 09 Prim ul No Peu tema
IT importanei
1 0- JUL - 03 55 50 0(din
SQL-ului acest
n lumea 0Ncapitol)
bazelor de date au curs
Ang a jat Numele
101 Ang a jat 1 mult cror persoane conine
cerneal i mult toner, att din stilouri,
IT 1 2- C T- 80 56 00 litera
0 55G p
00 e
0Na treia
ct poziie ?
i din imprimante;
102 Ang a jatPrimele
2 Rezultatuldou
Acesta esteIT un CON clauze
esteTA 1cel
2- N0sunt
din U- obligatorii.
figura 57 6.4.
50 0 56Prin
00 0N comparaie, exist
aj at 5multecataste
1 05 AngSGBD-uri, auprim
7fost
1
exemplu
8 N0apsate
2- - idebile cutare
de
00 mouse
intr-orostogolite.
tabel a unui Fr a
SdL> SELECT
PostgreSQL,
*
n care62clauza 50 0 62
FROM 0Neste facultativ. n
1 07 Ang aj at caracter/ir
7exagera, CON de TA
cum caractere
deja U- specificat.
7 N0ncepusem,
7 1-
2 61 50 0 seCei 60 doi
poate
00 0N specificatori
spune c Oracle multiplieste
Oracle,
2 FROM atunci
personal cnd 9valoarea
1 ce se dorete a fi afiat este o
3(jokeri)
construit
WHERE
constant
folosii
salorar
Figura
sau, 6.4.
n
n predicate
n jurul
BETWEEN SQL.55000
Operatorul
orice caz, nu
de tip SQL
Dialectul
esteAND
BETWEEN LIKE din sunt _ (underscore),
Oracle,
extras dintr-o tabel anume, se
ce
dei pe alocuri
substituie
diferit* de
65000 / un singur caracter,
standardele SQL-92 i i
% SQL:1999,
(procent) ce estesubstituie
unul dintreun cele
ir demai
recurge la o tabel pus la dispoziie n acest scop, DUAL, cu o
caractere de lungime variabil. Iat soluia
puternice, prin comparaie cu orice SGBD contemporan, medieval pentru exemplul nostru,
singur coloan (dummy) i o singura linie - vezi figura 6.2.
precum
sau antic.i rezultatul
SQL> SELECT FROH(figura 6.5):
salarii; no rows selected
SQL> SELECT * FROM dual ;
SELECT *
FROM6.1. personalSintaxa DUMMYde baz a frazei SELECT
Figura 5.19. Efectul anulrii unei sub-tranzacii marcate printr-un SAVEPOINT
WHERE UPPER (numepren) LIKE _G% 1
X______________________
SQL>Nu SELECT
o s intrm Figura n6.2. prea multe explicaii
Impresionanta tabel DUAL despre fundamentele
2 FROM personal
teoretice ale frazei SELECT i despre corespondena cu algebra
3Obinerea datei curente presupune
WHERE UPPER(nunepren) LIKE ' GV interogarea" acestei tabele -
4 /relaional,
C a r e s u n t deoarece
a n g a j a i iam c u face
n u m concuren
e c u p r i n s neloial
n t r e C a lcrii
ancea deT.SQL
vezi figura 6.3. Formatul de afiare depinde de setrile SQL*Plus
Vascris
s i l e ideD uunul
m i t rdintre
i u F. Cautorii
e z a r ? de fa i epublicat
ntrebarea tot la Editura
un pic retoric,
(vezi capitolul 3) i poate fi ameliorat folosind funcia TO CHAR,
Polirom. Cum n mai toate capitolele
deoarece, prin strdaniile din capitolul anterior, tabela PERSONAL precedente am presrat, din loc
despre care vom vorbi n paragraful urmtor:
n loc,
conine cte
nite o interogare,
nume cu totul aiurea. ne mulumim
Oricum, sdoar cu cteva
presupunem c,exemple
la un
moment
banale.
SELECT dat, vom
SYSDATE FROMintroduce
dual date reale, iar rspunsul la ntrebare va
fi furnizat de interogarea:
Care sunt angajaii din compartimentul IT, ordonai alfabetic ?
Acest
SELECT exemplu
* SQL>esteSELECT dedicatSYSDATE celor FROMcareDUALau; deschis mai trziu
FROM personal
aparatele de...SYSDATE
SQL i pune n eviden cele trei clauze cvasi-foiosite
WHERE numepren
(SELECT, BETWEEN plus
FROM i WHERE), 'Calancea
cea deT. Vasile' (ORDER BY) - figura 6.1.
ordonare
AND 'Dumitriu F. Cezar'
13-HAY-83
Care SELECT
sunt *pontajele din perioada 1-6 SAL
iulie 2003
M AR N UM EPR EN COM P DATASU
SQL> SALORA
|_____________________ 0 RA COL? A BOR
CA SELECT * A RT R RC0 ATOR
1 01 Ang aj 1 FROM pontaj IT
e 1 2- OCT- 8 0 56 00 0 55 00 0N
at
1 02 Ang aj 2 WHERE data CON Figura
TA 1 2-DATE' 6.3. Afiarea
N0 U- 2003-07-01'57 50 0 datei56 curente
00 0N
BETWEEN AND DATE' 2003-07-06'
1 03 Ang ajPredicatul
3 de ITselecie 0 2-(clauza
JUL - 76 WHERE) 67 50 0 poate 66 00conine
0N operatori de
1 04 Ang
at aj 4 PROD 0 5- JAN - 82 75 00 0 75 00 0N
at compae
1 05 Ang aj 5 Listai, (>, n ordinea
IT 1compartimentului
2- N0 0- 7 7 62 50 0 i62 a 00 0N
vechimii, personalul
1 06 Ang<,ajangajat
6=, *), dar i CON TA 1 1- APR-
operatori precum 71 50 0
BETWEEN,70 00 0N
LIKE, IN, IS NULL i
1 07 Ang aj 7 la Contabilitate i 1T.
CON TA 2 1- N0 U- 61 50 0 60 00 0N
1 08 AngEXISTS.
aj 8 PROD 3 0- DEC - 54 50 0 52 00 0N
at Primul servete 9 4 facil
la o mai definire
Atenie ! Se folosete operatorul OR, anuunui
AND, interval numeric,
chiar dac enunul
calendaristic sau de tip i de caractere. Al
este ...personalul angajat la CONTA i IT": doilea, la cutarea
Oracle. Ghidul dezvoltrii aplicaiilor profesionale 159

Lista persoanelor ce trebuie felicitate de Sfntul Ion


Trebuie avut n vedere ca, pe lng Ioni", s fe extrase i
persoanele cu prenume ca loan, Ioana, Ioanid, iar pe de alt parte,
nu trebuie luate n considerare persoanele cu prenumele Caraion i
Simion:
SELECT *
FROM PERSONAL
WHERE UPPER( Prenume! LIKE % ION%
OR UPPER( Prenume) LIKE
'%IOAN%OR UPPER(Prenume) LIKE
%-ION% OR UPPER(Prenume7 LIKE

6.2. Expresii i funcii sistem


Prelucrrile la care sunt supuse informaiile extrase din baza de
date reclam folosirea unei serii de funcii i expresii, din care
cteva vor fi expuse n acest paragraf.

6.2.1. Funcii pentru iruri de caractere


Una dintre cele mai frecvente operaiuni cu iruri de caractere este
concatenarea, care se realizeaz fie prin operatorul | |, fie prin
funcia CONCAT.

SELECT numepren | | ' lucreaz in compartimentul


' | I compart AS text FROM PERSONAL
sau
SELECT CONCAT (numepren, CONCAT
( ' lucreaz in compartimentul ', compart) ) AS
text FROM PERSONAL

TEXT

Primul Angajat Nou lucreaz in compartimentul IT


Al Doilea Angajat Nou lucreaz in compartimentul PROD
Angajat
8 rows selected.1 lucreaz in compartimentul IT
Angajat 2 lucreaz in compartimentul CONTA
Figura 6.5. Angajaii cu litera G pe a treia poziie a numelui
Angajat 3 lucreaz in compartimentul IT
Angajat
Funcia 4 lucreaz
UPPER in compartimentul
asigur extragerea deopotrivPROD
a liniilor pe care
Angajat 5 lucreaz in compartimentul
G"-ul cutat este majuscul sau minuscul. IT
Angajat 6 lucreaz in compartimentul CONTA
Angajat 7 lucreaz in compartimentul CONTA
n numele cror persoane apare, mcar o dat, litera G
Angajat 8delucreaz
(indiferent in compartimentul
poziiefpoziii) ? PROD
SELECT *
Figura 6.6. Nite concatenri
FROM personal
WHERE UPPER (numepren) LIKE '%G%'
De data aceasta, jokerul folosit este %, plasat att naintea, ct i dup litera G.
Oracle.
162
160 Ghidul dezvoltrii aplicaiilor profesionale Interogri161
SQL
* IT**IT *
IT* are numai
PROD* *
ConcatSELECT
SQL> * dou
PROD*PROD
argumente,
|| compart || **aaOSccorapart,
n interogarea de mai
sus2 au
[|fost necesare
IT**IT dou funcii.
|| '**Interesant
LPOD(compart,15) AS este15c n Oracle pot fi
IT* * * " L_PflD
C0NT0 * concatenate i date de 0alte tipuri
3 *'I| C0NT0**C0NT
RP0D(compart,15) || **dect
* OS " iruri de caractere.
R_PftD_15Spre
IT* * exemplu,
H FROMinterogarea
IT**IT urmtoare:
PERSONAL *
* 5 /
PROD SELECT numepren | | ' lucreaz din ' i *I datasv | |
PROD*PROD
IT* * IT**ITorar de ' | I salorar [ | ' lei.'
' si are salariul
C0NT0* * COMPART C0NT0**C0NT0
L POD 15 * R POD 15
AS text
C0NT0* * C0NT0*C0NT0 *
FROM PERSONAL
PROD* * PROD*PROD *
funcioneaz, chiar dac NumePren este de tip ir de caractere,
DataSV dat calendaristic, iar SalOrar numeric.
Tot n categoria funciilor folosite frecvent intr cele de
conversie: UPPER (toate literele vor fi convertite n majuscule),
Dintre funciile de informare" despre un ir de caractere, ne
LOWER (toate literele vor fi convertite n minuscule), INITCAP (prima
oprim asupra celei care numr lungimea irului i a alteia care
liter din fiecare cuvnt este majuscul, iar restul litere mici). Iat o
depisteaz pe a cta poziie a unei expresii/unui atribut apare un
interogare lmuritoare i un rezultat pe msur - figura 6.7.
caracter sau ir specificat. Astfel, interogarea:
SELECT numepren, LENGTH, (numepren),
UPPER(numepren) LOWER(numepren), INITCAP(numepren) '
INSTR (numepren,
FROM PERSONAL ' j ' ) , INSTR (numepren, 'D' )
FROM PERSONAL
10 rows
PRIMUL selected.
ANGAJAT NOU primul angajat nou Primul Angajat Nou
determin, pentru numele
AL DOILEA ANGAJAT fiecrui
al doilea angajat, numrul
angajat Al Doileade caractere
Angajat
care-1
NOUSQL>alctuiesc
| i penou ce poziie apar literele Nouj i D - vezi figura
ANGAJAT 1
6.10. angajat 1 Angajat 1
REPLACE(NUMEPREN,A
Figura 6.8. Completare
angajat 2 ' U la)
cu spaii, SUBSTR
stnga i laAngajat
dreapta 2 aj), INSTR
ANGAJAT
SQL> 2 numepren,
SELECT *, LENGTH (numepren), INSTR
(NUMEPREN,5 ,4) (numepren,
ANGAJAT
Primul Angajat Nou 3 0)Primul Angujut
(numepren, angajat Nou3 ul A Angajat 3
2FROMOperaiunea
PERSONAL
ANGAJAT 4 invers, de eliminare
angajat 4 (tundere") Angajat a spaiilor
4 de la
Al Doilea 3Angajat
/ Nou Al Doileu
stnga sau de la dreapta Angujut
valorii
angajat oile
5 unui atribut/expresie Angajat 5se realizeaz
Angajat 1 ANGAJAT 5 Angujut 1 jat
ANGAJAT 6 angajat 6 Angajat 6
Angajat 2 prin funciile LTRIM i 2RTRIM. La primajat
Angujut am apelat n capitolul 4, cnd
ANGAJAT 7
Angajat 3 am definit o regul
Angujutde angajat 7
3 validare pentru jat Angajat 7
atributul numepren, prin care
ANGAJAT 8
Angajat 4 interziceam Angujut 4 angajat 8 jat Angajat 8
ca primul
Figura 6.7.caracter dintr-un
Litere mari, micinume s fie spaiu. Pentru
i combinate
Angajat 5 eliminarea simultan
Angujut 5 a spaiilor la jatstnga i la dreapta, se
Angajat 6 Completarea Angujut 6
valorilor jat
recomand
Angajat 7 la funcia
Angujut TRIM7 cuunui atribut/expresie
opiunea BOTH.
jat
cu un caracter pn
atingerea
Atunci cnd unei lungiminlocuirea
se dorete specificate unui se realizeaz prin funciile
Angajat 8 Angujut 8 jat ir de caractere cu un altul
LPAD (completare
ntr-o expresie la stnga)
deFunciile
acest tipREPLACE
se poatei RPAD (completare la dreapta).
Figura6.9. i recurge
SUBSTRla funcia REPLACE, iar
Interogarea urmtoare completeaz
pentru a extrage o poriune dintr-un ir, cu spaii, la stnga i la
SUBSTR. Interogarea
dreapta,
urmtoare valorile atributului
nlocuiete Compart - vezi figura 6.8. Dup lungimea
toate a"-urile cu u"-uri din numele
pe
angajailor i extrage <Jin acelaise
care se va face completarea, poatepatru
atribut specifica un alt ncepnd
caractere, caracter
dect spaiul, pentru umplutur". n premier, numele coloanei
cu al cincilea:
(clauza AS)
SELECT face apel la ghilimele pentru a putea fi incluse spaii.
numepren,
SELECTREPLACE{numepren,
'* ' | | compart | | ' a' , '' u
AS' ) compart,
,
SUBSTR (numepren, 5, 4)
| | LPAD (compart, 15) || ' * ' A S " L_PAD 15 ",
' * ' 1 1 RPAD(compart,15) | | '* ' AS " R_PADjl5 " FROM
PERSONAL
N UM EPREN L EN GTH ( N UM E IN STR( N UM E PRE IN STR(N UM EPR
PREN ) N,J*) EN ,' D' )
Pr iiM il Rt ig aj at 18 12 0
N
Alo u
Do ile a Ang a jat 21 15 4
Ang a jat 1 9 5 0
Ang a jat 2 9 5 8
Ang a jat 3 9 5 0
Ang a jat 4 9 5 8
Ang a jat 5 9 5 0
Ang a jat 6 9 5 8
Ang a jat 7 9 5 0
Ang a jat 8 9 5 8
M ARC SALOR SALOR AR/1 6 CEIL FLOOR ROUN D* ROUN D TRUN C
A AR 8 - *
10 9 5 55 00 33 0 .3 57 14 3 33 1 33 0 33 0 .3 6 30 0 33 0 .3 5
11 0 5 05 00 30 0 .5 95 23 8 30 1 30 0 30 0 .6 30 0 30 0 .5 9
10 1 5 60 00 33 3 .3 33 33Ghidul
Oracle. 3 33 4 33aplicaiilor
dezvoltrii 3 33 3 .3profesionale
3 30 0 33 3 .3 3 163
10 2 5 75 00 34 2 .2 61 90 5 34 3 34 2 34 2 .2 6 30 0 34 2 .2 6
10 3 6 75 00 40 1 .7 85 71 4 40 2 40 1 40 1 .7 9 40 0 40 1 .7 8
10 4 7 50 00 44 6 .4 2857ROUND
1 44 7 - rotunjete
(p, n) 44 6 44 6 .4 3 rezultatul
40 0 unei
44 expresii (p) la un
6 .4 2
10 5 6 25 00 37 2 .0 23 81numr37 3 37 2 fracionare,
de poziii 37 2 .0 2 40 0 n
dac 37 2 .0pozitiv
este 2 sau, dac n
10 6 7 15 00 42 5 .5 95 23 8 42 6 42 5 4 25 .6 40 0 42 5 .5 9
10 7 6 15 00 36 6 .0 71 42este
9 36negativ,
7 36rotunjirea
6 36 6 .0 7se face
40 0la ordinul
36 6 .0 7 zecilor, sutelor,
10 8 5 45 00 32 4 .4 04 76miilor
2 32etc.
5 32 4 3 24 .4 30 0 3 24 .4
TRUNC (p, n) - are efect similar funciei ROUND, numai c n loc de
rotunjire (incrementare cu 1 a poziiei de referin, dac poziia de
ordin inferior are valoare mai mare sau egal cu 5) se face trunchiere.

Pentru comparaie, interogarea de mai jos folosete toate cele


patru funcii, rotunjirea realizndu-se att cu argument pozitiv, ct
i negativ. Rezultatul din figura 6.11 este ct se poate de gritor.

SELECT marca, salorar, salorar/168,


CEIL(salorar/168) AS CEIL , FLOOR(salorar/168) AS FLOOR,
ROUND(salorar/168,2) AS "ROUND+", ROUND(salorar/168,-2)
AS "ROUND-",
TRUNC(salorar/168,2) AS "TRUNC+"
FROM PERSONAL

SQL> SELECT narea, salorar, salorar/168,


2 CEIL(salorar/168) AS CEIL , FL00R(salorar/168) AS FLOOR,
3 ROUND(salorar/168,2) AS ROUND*", R0UM)(salorar/168,-2) AS
R0UM>-, i TRUNC(salorar/168,2) AS TRUNC*
5 FROM PERSONAL
6 /

Figura 6.10. Funciile LENGTH i INSTR

6.2.2. Funcii pentru valori numerice


Trecem peste funciile trigonometrice i algebrice care n aplicaiile
economice se regsesc ceva mai rar. Ajungem rapid la cteva funcii
de trunchiere/rotunjire:
CEIL (p) - ntoarce cel mai mic ntreg mai mare sau egal cu
argumentul
(p);
164 Interogri SQL

CURRENT_TIMESTAMP AS " Data si ora curenta "


FROM DUAL

SQL> SELECT CURRENT_DATE AS M CURRENT_DATE ,


2 CURRENT_TIMESTAMP AS " Data si ora curenta "
3 FROM DUAL
4 f

CURRENT Data si ora curenta

17- MAV-03 17-MAV-03 08.44.56.325000 AM -07:00

Figura 6.12. Data i ora exacte!


Pentru operaii cu date calendaristice, funciile disponibile nc
din Oracle 7 surit
ADD MONTHS (dat a) - adun un numr de luni la data-argument
LAST DAY(data) - furnizeaz ultima zi din luna n care se afl data-
argument;
NEXT DAY (data, zi) - ntoarce data primei zile (luni, mari...) ce
urmeaz datei-argument.

Astfel, interogarea urmtoare afieaz ziua curent (lansrii


comenzii SELECT), data de peste dou luni calendaristice, ultima zi a
lunii curente i data viitoare n care o s cad o zi de mari - vezi i
figura 6.13.

SELECT SYS DATE AS "Astzi",


ADD_MONTHS (SYSDATE, 2) AS "Peste doua luni",
LAST_DAY(SYSDATE)"Ultima_zi_a_lunii curente",
NEXT_DAY (SYSDATE, 'TUESDAY' ) AS "Urmtoarea mari"
FROM DUAL

SQL> SELECT SYSDATE AS "Astzi", ADDM0NTHS (SYSDATE,2) AS "Peste doua


luni, Figura 6.11. Cteva funcii numerice
2 LAST_DAY(SYSDATE) "Ultima_zi_a_lunii_curente",
3 NEXTDAY (SYSDATE, TUESDAY) AS "Urmtoarea mari"
4 FROM DUAL
5 / 6.2.3. Date calendaristice
Oracle
Astzi Peste douai-a
luni ameliorat, o dat cu ultimele Urmtoarea
Ultima_zi_a_lunii_curente versiuni, nu numai funciile
mari
pentru lucrul cu date calendaristice, dar mai ales conformitatea cu
17-MAV-03 17-JUL-03 31-MAY-Q3 2O-MAV-03
standardele SQL. Dac, tradiional, singura funcie ce furniza date
sistemului
Figura era una
6.13. Funciile proprietar",
ADD_MONTHS, SYS DATE,
LAST_DAY de la 9i apare i
i NEXT_DAY
CURRENTDATE, preluat din SQL. Tot n Oracle 9i apar funciile
Cu funciile ROUND i TRUNC am fcut cunotin ceva mai nainte.
CURRENT_TIMESTAMP i SYSTIMESTAMP ce furnizeaz, deopotriv, data
E mbucurtor c rotunjirea i trunchierea funcioneaz i pentru
curent, ora exact (att ct de bine este reglat ceasul
date calendaristice, dup logica acestora. Astfel, ROUND (data [,
calculatorului), la fraciuni de secund ce pot fi specificate.
format]) rotunjete o dat calendaristic dup un format specificat,
iar TRUNC (data
SELECT[,CURRENT trunchiaz
format]) DATE o dat
AS " CURRENT calendaristic dup
DATE",
formatul specificat. Spre exemplu, dac la format se specific YEAR
ANUL LUNA ZIUA ORA MINUTUL SECUNDA

2003 5 17 19 Sk 53.5H2

Oracle. Ghidul dezvoltrii aplicaiilor profesionale


166 Interogri165
SQL

atunciSELECT
SQL> ntoarce(VEAR
ROUNDEXTRACT anul FROM
urmtor, n timp
SVSDATE) ce TRUNC tot anul
AS Anul,
2curent.
EXTRACTCnd formatul
(MONTH FROMse SVSDATE)
refer la lun (MONTH, MON sau MM), atunci
AS Luna,
3luna furnizat
EXTRACT (DAVeste luna
FROM curent,
SVSDATE) ASns dac data cade" n a doua
Ziua,
k EXTRACT (HOUR FROM SVSTIMESTAMP)
jumtate (dup 15 ale lunii), ROUND ntoarce AS luna
Ora,urmtoare:
5 EXTRACT (MINUTE FROM SVSTIMESTAMP) AS Minutul,
6 EXTRACT (SECOND
SELECT SYS FROM
DATE AS SVSTIMESTAMP) AS Secunda
"Astzi",
7 FROM ROUND(SYSDATE,'YEAR')
DUAL AS Rot_ AN,
8 / TRUNC(SYSDATE, 'YYYY' } AS Trunc_AN,
ROUND(SYSDATE,'MON') AS Rot_LUNA,
TRUNC(SYSDATE, 'MONTH') AS Trunc LUNA,
ROUND(SYSDATE,'DDD' ) AS Rot_ZI,
TRUNC(SYSDATE, 'DDD') AS Trunc ZI
FROM DUAL

SQL> SELECT SYSDATE AS "Astzi",


2 ROUND (SVSDflTE , YEAR1) AS Rot_AN, TRUNC (SVSDflTE, YYYY*) AS
Tt*unc_AN,
3 ROUND (SYSDATE,MON') AS Rot_LUNfi, TRUNC (SYSDATE, 'MONTH ) AS
Trunc_LUNA,
1 ROUND(SYSDATE,DDD*) AS Rot_ZI, TRUNC(SYSDATE, "DDD") AS Trunc_ZI
5 FROM DUAL
6 /
Astzi ROTAN TRUNCAN ROT_LUNA TRUNCLUN ROT_ZI TRUNC_ZI

IZ-MAV-OS 01-JAN-O3 01-JAN-03 01-JUN-03 01-MAY-03 17-MAY-03 17-MAY-03


Figura 6.14. Diverse rotunjiri i trunchieri

Dac pentru extragerea anului/lunii/zilei dintr-o dat


calendaristic versiunile mai vechi ale Oracle necesitau funcii de
conversie precum TOCHAR sau TO NUMBER, n 8i i 9i lucrurile s-au
simplificat simitor. Similar standardelor SQL, prin funcia EXTRACT
putem afla orice component a unei date/ore:

SELECT EXTRACT (YEAR FROM SYSDATE) AS Anul,


EXTRACT (MONTH FROM SYSDATE) AS Luna,
EXTRACT ( DAY FROM SYSDATE) AS.Ziua,
EXTRACT (HOUR FROM SYSTIMESTAMP) AS Ora,
EXTRACT (MINUTE FROM SYSTIMESTAMP) AS Minutul,
EXTRACT (SECOND FROM SYSTIMESTAMP) AS Secunda
FROM DUAL

Cum este i firesc, argumentele YEAR, MONTH, DAY pot fi aplicate


unui atribut, unei variabile sau constante de tip dat calendaristic,
Oracle. Ghidul dezvoltrii aplicaiilor profesionale 167

SELECT SYS DATE AS Azi,


ADD_MONTHS (SYSDATE, 26} + 12 AS "Peste 2a_21_12z",
SYSDATE+ INTERVAL '2' YEAR + INTERVAL '2' MONTH +
INTERVAL '12' DAY AS Idem,
FROM DUAL

SQL> SELECT SVSDATE fiS Azi,


2 ADDMONTHS (SVSDATE, 26) + 12 AS Peste 2a_2l_12z",
3 SVSDATE + INTERUAL -21 VEAR + INTERUAL 12' MONTH +
!* INTERUAL *12* DAV AS Idem
5 FROM DUAL
6 /

AZI Figura
Peste 2a6.15. Funcia EXTRACT
21 12z IDEM
n privina operaiunilor cu datele calendaristice, se cuvine s
18-
ncepem prin a MAV-03 30-JUL-05 (sau
reaminti c, dac o constant 30-JUL-05
o variabil
ntreag) apare Figura
ntr-o 6.17.
expresie cu unin atribut de tip dat,
Somewhere tme
constanta/variabila se va considera a fi un numr de zile. Curios este
Lucrurilestau identic
c lucrurile pot fi
pentru aplicate
atributele desimilar
tip timp: i pentru
atribute/variabile/constante/ expresii de tip timp. Astfel, pentru a
aflaSELECT SYSDATEde
ora exact AS Azi,
peste 71 minute i 100 de secunde de la
momentul curent (cel al"Peste
SYS DATE + 43 AS 43 deinterogrii),
execuiei zile", se poate folosi fraza
SYSTIMESTAMP AS "Acum",
SELECT urmtoare - vezi figura 6.18.
SYSTIMESTAMP + 34 AS "Peste 34 de. . . "
FROM DUAL
SELECT SYSTIMESTAMP AS Ora_exacta,
SYSTIMESTAMP + INTERVAL ' 7 1 ' MINUTE +
Astfel, ne-am atepta ca SYSTIMESTAMP + 34 s calculeze ora
INTERVAL '100' SECOND AS Peste_71min_100sec FROM
exact
DUALde peste 34 secunde sau minute, ns, dup cum se observ
n figura 6.16, 34 este considerat numrul de zile.
SQL> SELECT SYSTIMESTAMP AS Ora_exacta,
2SQL>
SYSTIMESTAMP IHTERUAL
SELECT SVSDATE AS Azi, *71' MINUTE
SVSDATE AS "Peste 43 de zile",
+ 43
3
2 IHTERUAL '100* SECOND
SYSTIMESTAMP AS SVSTIMESTAMP + 34 AS "Peste 34 de..."
AS "Acum".
3 Peste_71nin_1OOsec
FROM DUAL < FR0N DUAL
5 /
4 /
ORA EXACTA PESTE 71MIN 1OOSEC
AZI Peste
18-MAY-03 43 de zile Acun
11.39.46.125000 PestePH
AH -07:00 18-HAY-03 12.S2.26.125000000 34-07:00
de...

17-MAY-83 29-JUN-03 17-MAY-03


Figura 6.18.01.57.36.443000
Un interval PM -07:00 20-JUN-O3
Figura 6.16. Incrementri ale unor valori de tip dat i timp
Mai mult, n Oracle 9i exist dou tipuri de date INTERVAL, YEAR
TO Dac
MONTHdorim
i DAYsTO incrementm
SECOND, care o dat
pot cu un interval
fi asociate de ordinul
unor atribute, ceea
lunilor/anilor, o funcie de mare ajutor este ADD MONTHS,
ce uureaz sensibil gestionarea unor informaii de tip perioad pe care am
folosit-o ceva mai
calendaristic. Sprenainte.
exemplu, Astfel, raportat
echivalent la ziua
celor doucurent
variante(18
de MAI
mai
2003 - data execuiei), peste 2 ani, 2 luni i 12
sus, data care cade" peste exact 2 ani, dou luni i 34 de zile sezile va fi data
obinut prin astfel:
poate obine expresia ADD MONTHS (SYSDATE, 26) + 12, unde 26 este
2 ani * 12 luni + 2 luni. Similar standardelor SQL, ultimele versiuni
Oracle
SELECTau SYSDATE
introdusAS un mult mai elegant tip de dat, INTERVAL, aa
Azi,
nct putem
SYSDATEformula aceeai
+ INTERVAL '2-2'condiie
YEAR TO mult
MONTH mai explicit: SYSDATE +
+ 34,
SYSDATE+ INTERVAL ' 2 - 2 ' YEAR(1)
INTERVAL '2' YEAR + INTERVAL '2' MONTH + INTERVAL TO MONTH + 34 ' 12' DAY. Iat
FROM DUAL
168 Interogri SQL

Literalul '2-2' indic un numr de ani egal cu 2, cratima este


separatorul, iar cel de-al doilea 2 reprezint numrul de luni. Al
doilea format precizeaz, prin YEAR (1 ), numrul de poziii pe care
se reprezint anii din interval. Dac la acest gen de interval
delimitatorul este cratima (-), la intervale orare se folosete
Interogarea urmtoare afieaz, pe rnd, urmtoarele momente:
curent, cel de peste dou zile, 8 ore i 34 minute, cel de peste 17
ore i 49 minute i cel de peste 120 zile, 12 ore, 44 minute i 45
secunde:

SELECT 'Acum ' AS "Ce se dorete",


CURRENTJTIMESTAMP AS Momentul FROM DUAL
UNION
SELECT 'Peste 2 zile, 8 ore si 34 minute ',
CURRENT_TIMESTAMP + INTERVAL '2 8 : 3 4 ' DAY ( 1 ) TO MINUTE FROM
DUAL
UNION
SELECT 'Peste 17 ore si 4 9 minute ',
CURRENTJTIMESTAMP+ INTERVAL ' 1 7 : 4 9 ' HOUR TO MINUTE FROM DUAL
UNION
SELECT 'Peste 120 de zile, 12 ore, 44 minute si 45 secunde ',
CURRENT_TIMESTAMP+INTERVAL ' 120 1 2 : 4 4 : 4 5 '
DAY ( 3 ) TO
SECOND FROM DUAL

Rezultatul este cel din figura 6.19. Pentru un plus de fotogenie,


s-a recurs la reuniunea a patru fraze SELECT, anticipnd scurta
discuie despre operatorul UNION pe care o vom purta peste cteva
pagini.
SQL> SELECT 'Acum AS "Ce se doreste".
2 CURRENTJTIHESTAHP AS Honentul FROH DUAL
3 UHIOH
4 SELECT 'Peste 2 zile. 8 ore si 34 Minute',
5 CURREHT_TIHESTAHP + 1HTERUAL '2 8:34' DAV (1) TO HINUTE FROH DUAL
6 UNION
7 SELECT 'Peste 17 ore si 49 ninute*,
8 CURRENT_TIHESTAHP * INTERUAL '17:49' HOUR TO HINUTE FROH DUAL
9 UNION
10 SELECT 'Peste 120 de zile, 12 ore, 44 ninute si 45 secunde*,
11 CURRENT_TIHESTAHP * INTERUAL *120 12:44:45' DAV (3) T0 SECOND FROH DUAL
12 /

Ce se doreste H0HENTUL

Acum 19-MAV-03 89.54.58.699000000 AH -07:08


Peste 120 de zile, 12 ore, 44 minute si 45 secunde 16-SEP-83 10.39.43.699000000 PH -07:00 Peste 17 ore si 49 minute
20-HAV-B3 03.43.58.699000008 AH -07:00
Peste 2 zile. 8 ore si 34 ninute 21-H8Y-03 66.28.58.699000800 PH -07:00

Figura 6.19. Alte intervale


Formatul de afiare a datei calendaristice poate fi modificat prin
comanda
ALTER SESSION:
ALTER SESSION SET NLS DATE FORMAT = 'DD-MM-YYYY HH24 :MI: SS'
Oracle. Ghidul dezvoltrii aplicaiilor profesionale 169

Dup aceast comand, datele calendaristice vor fi afiate n


formatul specificat - vezi figura 6.20.

SQL> ALTER SESSION SET NLSDATEFORMAT = 'DD-MMVYYV


HH2*:HI:SS
2 /

Session altered.

SQL> SELECT SYSDATE FROM DUAL ;

SYSDATE
19- B5-2003 11:20:i9
Figura 6.20. Modificarea formatului de afiare a datei

De reinut c nu se pot aduna i nici scdea dou date


calendaristice. Ne intereseaz captul perioadei calendaristice n
care jumtatea este ziua curent (18 mai 2003, data execuiei).
Suntem tentai s folosim interogarea:

SELECT SYSDATE +
SYSDATE FROM DUAL

Execuia sa se soldeaz cu mesajul de eroare din figura 6.21, care


este destul de limpede n privina motivului declanrii erorii.

SQL> SELECT SYSDATE + SYSDATE


2 FROM DUAL
3 /
SELECT SYSDATE + SYSDATE
*
ERROR at line 1:
ORA-00975: date + date not allowed
Figura 6.21. Eroare la adunarea a dou date calendaristice

Pentru a rezolva problema, trebuie s transformm data curent n


interval:

SELECT CURRENT_DATE AS Astzi,


FROMSYSDATE+
DUAL INTERVAL '2002-05' YEAR(4) TO MONTH +
170 Interogri SQL

SQL> SELECT CURRENTJJATE AS Astzi,


2 SVSDATE + INTERUAL *2082-05* YEAR<4) TO MONTH *
3 INTERUAL *19* DAV AS Oale_si_ulcele
4 FROM DUAL
5 /

ASTAZI OALE SI ULCELE

19-05-2003 16:40:55 07-11-4005 16:40:55


Figura 6.22. Conversia unei date n interval

Tabela PERSONAL ncorporeaz atributul DataSV ce reprezint


data de la care se calculeaz anii de vechime ai angajatului, ani n
funcie de care se acord sporul de vechime. De aceea, o
importan deosebit o va avea, pe parcursul multora dintre
capitolele viitoare, calculul numrului ntreg de ani scuri de la data
de calcul a sporului de vechime pn la 1 ale lunii curente (aprilie
2003, mai 2003 etc ). Funcia la care se poate face apel din Oracle 7
ncoace este MONTHS BETWEEN (datai, data2), care calculeaz
numrul de luni (cu tot cu poziii fracionare) dintre dou date
calendaristice. Fraza SELECT de mai jos determin numrul de ani
cuprini ntre 1 mai 2003 i data sporului de vechime. n prealabil,
modificm formatul de afiare a datei calendaristice.

ALTER SESSION SET NLS_DATE_FORMAT = 'DD-MM-YYYY' ;

SELECT numepren, datasv,


MONTHS_BETWEEN( DATE'2003-05-01', datasv) AS Nr_Luni,
TRUNC(MONTHSJ3ETWEEN ( DATE' 2003-05-01', datasv) /12,0)
AS Ani_Intregi
FROM personal ;

ntruct la vechime intereseaz numrul ntreg de ani, fr


rotunjiri, ctul mpririi funciei MONTHS BETWEEN la 12 este
trunchiat. Rezultatul este cel din figura 6.23.
Oracle. Ghidul
172 Oracle. dezvoltrii
Ghidul aplicaiilor
dezvoltrii profesionale
aplicaiilor profesionale Interogri173
SQL 171

SQL>
SQL> SQL>
SELECT
SELECT SELECT nurcepren,
numepren,
numepren, datasu,
datasu,
22 TO_OATE(
MONTHSBETWEENi
MONTHS_BETWEEN(
2 DATE DATE2003-05-01',
* 81/85/2883*, *8D/NM/YVYY* datasu) AS
1 ) AS **1_Hai_Muncitoresc",
2803-05-01 *, datasu)/12 AS NrLuni,
Ani_Fractionari
33 TO CHAR(datasu, 'DO-HW-YVYY*) AS **Data->Sir, i
TRUNC(MONTHS_BETMEEN(
(DATE'2003-05-01
3 - datasu) VEAR(2) DATETO *
MONTH 2003-05-01
AS *, datasu)/12,)
Ani si Luni, AS
TQ_CHA R(salorar, *999999*) AS "Hunar-iSir",
4 Ani_Intregi
EXTRACT (YEAR FROM
5 TO_NUMBER(TO_CHAR(datasu, ((DATE-2003-05-01
*tw*)) AS
1
"Luna (Data->Sir->Nuar)'* - datasu) YEAR(2) TO MONTH))
6 FROM FROM personal ;
ASpersonal
4 Ani
5
7/ FROM personal
N UM EPREN6 / HUMEPREN
DATASU DATASUAN I AN I SI NRLUN LUNI
I ANI AN NTREGI
I
Primul Angajat Nou FRAC 10-07-2003
ION RI -2.2903226 0 Al Doilea
Pr imul Ang aj at No u
Angajat 1Nou
0- JUL - 03
10-07-2003 -.19-2.2903226
0 86 02 2 - 000 00Angajat
00 00 0 - 1 12-10-1980
0
02
270.645161
Al Do ile a Ang a jat 22- 83
1 0- JUL Angajat -.1920 12-11-1978
86 02 2 - 00 00293.645161
00 00 0 - 24 Angajat
6
N o u a jat 1
Ang 1 2- QCT- 8 0321.967742
3 02-07-1976 2 2.5 53 76 3 4+
26 02
00 00 0 00 22
Angajat 4 - 05-01-1982
22
Ang a jat 2 12 -N 021
255.870968 U- 7 8
Angajat2 4.45 70 43 0 1 +
12-11-1977 07
00305.645161
00 0 00 24 - 25 2Angajat
4
Ang a jat 3 0 2- JUL - 76216.677419
6 11-04-1985 2 6.8 30 64 5 2+
18 06
00 00 0 00 26
Angajat 7 - 21-11-1991
26
Ang a jat 4 137.3548390 5- JAN11- 82
Angajat2 1.3 22 58 0 6 +
8 30-12-1994 10
00100.064516
00 0 00 21 - 8 2 1
Ang a jat 5 12 -N 0 U- 7 ? 2 5.4 70 43 0 1 + 04
00 00 0 00 25 - 25
Ang a jat 6 11 -A PR- 85 1 8.0 56 45 1 6 + 06
00 00 0 00 18 - 18
Ang a jat 7 21 -N 0 U- 9 1 1 1.4 46 23 6 6 + 01
00 00 0 00 11 - 11
Ang a jat 8 30 -DE C - 9 II 8 .3 3 87 09 6 8 0 +5
00 00 0 00 08 - 8
04
Figura 6.23. Funcia MONTHS_BETWEEN
Figura 6.24. Intervale obinute prin scdere i numrul de ani extras dintr-un interval
De la Oracle 9i putem beneficia de una dintre mreele cuceriri
ale nucleului SQL, i anume lucrul cu intervale. Astfel, dac dorim s
vedem ci ani i cte luni s-au scurs ntre dou date calendaristice,
6.2.4. Conversii dintr-un tip n altul
pn n Oracle 8i, am avea nevoie de numr de virtuozitare SQL.
DacAcums-ar fi ns,
fcut pe baza tipului
o statistic privind gradul YEAR
INTERVAL de folosire lucrurile
a funciilor
TO MONTH, devin o
sistem,
istoriabanalitate:
Oracle ar (DATE'
fi cosemnat n unul - dintre
2003-05-01' datasv) primele locuri:
YEAR(2) TO CHAR,
TO MONTH. Iar
TOdac
DATEanterior
i TO NUMBER,am folositadic funcia clasice depentru
funciile EXTRACT determinarea
conversie ntre tipurile unei
majore componente a datei calendaristice (ziua, luna sau anul),
de date, numere, iruri de caractere i date calendaristice. aceeai
Astfel, o
funcie
constant de poate
tip datfi aplicat i intervalelor,
calendaristic poate fi definitaa nct
att n maniera
EXTRACT DATE'FROM
(YEAR
2 0 0 3( -(DATE'2003-05-01'
0 5 - 0 1 ' , ct i TO- DATE
datasv) ( ' YEAR(2)
0 1 / 0 5 / 2 TO
0 0 3MONTH) ) va furniza
' , 'DD/MM/YYYY' numrul
). Prima
de ani
variant e maipe care l conine
scurt, ns a intervalul. Zis i fcut:
doua, mai flexibil. Noi am ales ablonul
z i / l u n / a n , dar cei curioi pot consulta documentaia Oracle pentru a se
minuna SELECT numepren,de
de puzderia datasv,
abloane pus la dispoziie de nucleul SQL al
MONTHS_BETWEEN(DATE'2003-05-01', d a t a s v ) / 1 2
acestui produs.
AS Ani_Fractionari,
Operaiunea invers, de transformare a unei date calendaristice n ir
(DATE'2003-05-01' - datasv) YEAR(2) TO MONTH
de caractere, AS se realizeaz prin funcia TO CHAR. Tot TO CHAR face
Ani_si_Luni,
conversia unui numr
EXTRACT (YEAR ntr-un
FROMir de caractere, dup
((DATE'2003-05-01' un ablon
-datasv) YEAR(2)specificat:
TO MONTH) ) AS
SELECT numepren,
Ani1_Mai_Muncitoresc
FROM personal Data->Sir Nunar->Sir Luna (Data->Sir->Numar)

TO_DATE 2 0 0 3 ' , 'DD/MM/YYYY'


( ' 0 1 / 0 5 /18-07-2003 ) AS "l_Mai_Muncitoresc" ,
Primul Angajat Nou
Tocmai pentru
01-MAY-83
TO CHAR(datasv, a pstra o )paralel
'DD-MM-YYYY' cu interogarea anterioar, se
55500
AS "Data->Sir",
7

Al Doilea Angajat Nou 01-MAY-83 10-97-2003 505 00 7


Angajat 1 afieaz,
TO_CHAR(salorar,
81-MAY-83 pe rnd: data de la
'999999')
12-18-1980 56000care
AS se calculeaz sporul
"Numar->Sir", 18 de vechime,
Angajat 2
Angajat 3
numrul
81-MAY-83
01-MAY-03
de ani calculai
TO_NUMBER(TO_CHAR(datasv,
12-11-1978
02-07-1976
cu parte
'MM'))
57500
67500
fracionar (prin MONTHS
11
7
BETWEEN),
Angajat ** ASY-83"Luna
intervalul
01-MA (Data->Sir->Numar)"
anilor i lunilor scurse
05-01-1982 75000 ntre 1 mai 2003 i 1data sporului de
Angajat 5 FROM vechime
personal
01-MAY-03 12-11-1977
i, n fine,
62500 11
11-08-1985 glazura 71500
Angajat 6 01-MAY-03 de pe tort (sau bomboana 4 de pe coliv,
Angajat 7
depinde
01-MAY-03
cum privii
21-11-1991
lucrurile),
61500
numrul de ani extras 11
din interval -
Angajat 8
n schimb,
01-HAV-03
conversia unui ir de
30-12-199* 58500
caractere ntr-un numr,12
cu sau fr
vezi figura 6.24.
ablon, se realizeaz prin funcia TO NUMBER. Ultima coloan a interogrii
urmtoare (vezi figura 6.25) extrage luna din data sporului de vechime,
prin TO CHAR, iar irul obinut este convertit apoi n numr.
Oracle. Ghidul dezvoltrii aplicaiilor profesionale 175
176
174 Interogri SQL

n comunitatea
SELECT SQL, funcia consacrat n privina conversiilor
marca, numepren,
Pe acelai calapod colaborator,
este construit i logica funciei
este CAST.
DECODE Dintre multiplele
(colaborator , posibiliti, urmtoarea fraz SELECT
NUMTODSINTERVAL, numai c, n aceast situaie, o constant
ilustreaz
' N ' ,urmtoarele conversii:
'Angajat cu norma din , numr n ir de caractere, din
intreaga'
numeric poate fi convertit, dup caz, n zile (DAY), ore (HOUR),
tip dat'D' , 'Colaborator',n tip timp i din dat calendaristic n ir de
calendaristic
minute 'Nu
(MINUTE) sau secunde
este specificat ! ! ! ' (SECOND) - vezi figura 6.27:
) AS Tipul_Angajatului
caractere:
FROM personal
SELECT '3 zile cu 7 minute si 5 secunde' AS Descriere,
NUMTODSINTERVAL
SELECT CAST (marca AS C (3,
H A' D
RA(6Y )' ) ASMarca_Sir,
+
Logica este urmtoarea:
NUMTODSINTERVAL (7,AS
primul
'MINUTE')
argument
+
al funciei, colaborator,
CAST (CURRENT_DATE TIMESTAMP) AS Data_Timp,
este comparat
CAST cu prima
NUMTODSINTERVAL
(datasv valoare
(5,
AS VARCHAR2 ( 4 de
'SECOND') referin,
0 ) )AS
ASInterval
Data_Sir 'N'; dac cele dou
valori sunt
FROM
FROM egale,
dual UNION
personal funcia
SELECTreturneaz
'3 zile fara 7irul 'Angajat
minute' , cu norma intreaga' ;
n caz c nu, datelor
se trecerezultatelor
NUMTODSINTERVAL
Tipologia la (3,
verificarea - egalitii
' D A Y ' ) n dintre colaborator
urma conversiei i a
(figura 6.29)
reiese NUMTODSINTERVAL
doua valoare etalonde
i din modul - 'D',(7, 'MINUTE')
iar atunci
aliniere. Astfel, cnd cele dou
coloana Marca valori coincid,
Sir este se
aliniat
FROM dual
returneaz
la ce indic Dac
'Colaborator'.
stnga, ceea faptulvaloarea
c tipul su atributului nu caractere.
este ir de se potrivete
cu nici una dintre valorile specificate, se returneaz ultimul ir 'Nu
Figura 6.25. Conversii
este specificat ! ! ! '. Iat rezultatul - INTERURL
DESCRIERE
MARCA_SIR DATA_TIMP figura 6.30.
O dat cu versiunea 9i, apar, printreDATA_SIRaltele, dou funcii de conversie cu
un 3
cert grad04.30.47.000000
20-MAV-03
zile decu
utilitate.
7 PrimaPMeste NUMTOYMINTERVAL,
minute 10-JUL-03
si 5 secundecare+000000083
convertete
109
un numr ntr-un interval YEAR TO MONTH. Exemplu:
00:07:05.000000000
110 20-MAV-03 04.30.47.000000 3 PM zile fara 7 minute
10-JUL-03 +000000002
20-MAV-03 23:53:00.000000000
04.30.47.000000
101 SELECT '4 ani' AS Descriere, PM 12-0CT-80
102 20-MAY-03 04.30.47.000000
NUMTOYMINTERVAL
Figura 6.27.(4, PM 12-N0U-78
'YEAR')NUMTODSINTERVAL
Funcia AS "Interval"
103 20-MAY-03
FROM dual 04.30.47.080000 PM 02-JUL-76
104 Interogarea
20-MAY-03
UNION urmtoare
04.30.47.000000
SELECT '7 folosete
PM cele dou funcii pentru a
05-JAN-82
105 calcula
l u n i 'datele
20-MAY-03 i orele exactePMde peste
, 04.30.47.000000 4 a n i J u r 7 l u n i i peste 3
12-N00-77
106 z i l e
20-MAY-03 f r 7 m i n
NUMTOYMINTERVAL u t e
04.30.47.000000, relativ la
(7, PM momentul
'MONTH') execuiei:
11-APR-85
107 FROM dual
20-MAY-03 UNION SELECT
04.30.47.000000 PM 21-N0U-91
SELECT
'4 ani si 'Astzi'
7 luni' ,AS Obiectiv, PM
108 20-MAY-03 04.30.47.000000 30-DEC-94
TO_CHAR( SYS DATE,{4,
NUMTOYMINTERVAL 'DD-MM-YYYY
'YEAR') + HH:MI:SS' ) AS Data_Ora
FROM dual UNION
NUMTOYMINTERVAL
Figura 6.29. Folosirea funciei (7, 'MONTH')
SELECT
FROM 'Peste
dual UNION4 ani fara 7 luni ' ,
CAST
Adevrata
SELECT '4 anifor
fara 7aluni'
TO_CHAR(SYSDATE funciei CAST iese la(4,
+ ,NUMTOYMINTERVAL iveal
'YEAR')atunci
- cnd se
NUMTOYMINTERVAL
doreteNUMTOYMINTERVAL
conversia dintr-un (7, 'MONTH' ) ,
tip utilizator
(4, 'YEAR') - 'DD-MM-YYYY HH :
n altul, cu sauM I : S S ' ) fr
FROM
subconsultri NUMTOYMINTERVAL
care extrag seturi (7, 'MONTH')
de nregistrri. Despre aceste
dual dual
FROM
faciliti vom discuta cu alt ocazie.
UNION
6.2.5.
SELECT
Dup Structuri
'Peste
constanta 3 zile alternative:
fara 7 minute'
numeric , DECODE
apare 'YEAR' i CASE ceea ce indic
sau 'MONTH',
TO_CHAR(SYSDATE+NUMTODSINTERVAL
semnifi caia numrului (este an sau lun). Utilitatea (3, 'DAY') -
acestei funcii este
In Oracle exist dou
NUMTODSINTERVAL opiuni
(7, ' Mpentru
I N U T E ' lucrul cu secvene
) , 'DD-MM-YYYY
dat de operaiunile n care poate fi angajat, dintre care cteva sunt
alternative:
HH: MI: SS' )
FROM dual
funcia DECODE, disponibil nc din Oracle 7, i structura CASE, care
exemplificate n interogarea precedent, al crei rezultat se prezint n
e ceva mai cald" (din Oracle 8i i 9i n PL/SQL). Tabela PERSONAL
figura 6.26.
Ceea atributul
conine ce se obine n urma pentru
Colaborator lansriiantiSQL*Plus seamnrespectiv
dac persoana izbitor cu
este angajat cuDESCRIERE
carte de munc, caz Interval
n care valoarea atributului
este 'N', figura 6.28.colaborator
sau este 0BIECTIU DATA
al fimei ORA n afara celor dou
('D').
MARCANUMEPREN 4 ani +000000004-00
COLABORATO 4 ani fara
TIPUL_ANGAJATULUI
valori, laAstzi
un moment dat, valoarea 20-05-2003
poate s fie11:11:12
NULL, ceea ce
7RD
luni +000000003-05
Colaborator
4 ani si
109 Primul AngajatPeste
nseamn Nou Al
fie c situaia
37zilelunifara angajatului
7 minute este
+000000004-07 7 incert,
23-05-2003
luni fie c, pur i
Doilea Angajat
simplu, esteNouvorba
11:04:12 despre4o ani
Peste Nu este
neglijen specificat
fara 7 aluni ?!?
operatorilor. Ne propunem
20-10-2006
110 +000000000-07
s afim,
101 Angajat 1 n dreptul
11:11:12 N fiecrei linii din tabel,
Angajat cu normaunintreaga
mesaj care s indice
102 Angajat 2 persoanei respective.
tipul N Figura 6.26. Angajat
Folosind
Funcia cu norma
funcia
NUMTOYMINTERVAL intreaga
DECODE, se poate scrie:
103AngajatFigura
3 6.28. Expresii
N ce folosesc funcii
Angajat cude conversie
norma numr-interval
intreaga
104Angajat 4 N Angajat cu norma intreaga
105Angajat 5 N Angajat cu norma intreaga
106 Angajat 6 N Angajat cu norma intreaga
107Angajat 7 N Angajat cu norma intreaga
108 Angajat 8 N Angajat cu norma intreaga
Figura 6.30. DECODE i CASE
Din Oracle 8i apare, pe linia alinierii cu SQL-92, structura CASE,
aa c, echivalent frazei de mai sus putem folosi i alte dou soluii:

SELECT m a r c a , numepren, colaborator,


CASE colaborator
WHEN 'N' THEN 'Angajat cu norma intreaga'
WHEN 'D' THEN 'Colaborator'
ELSE 'Nu este specifi cat ! ! !'
END AS Tipul_Angaj atului FROM personal sau
SELECT marca, numepren, colaborator,
CASE
WHEN colaborator = 'N' THEN 'Angajat cu norma intreaga'
WHEN colaborator = 'D' THEN 'Colaborator'
ELSE 'Nu este specifi cat ! ! !'
END AS Tipul_Angajatului FROM personal
Oracle, Ghidul dezvoltrii aplicaiilor profesionale 177
178 Interogri SQL

Prima este 'SATURDAY',


mai apropiat de logica funciei DECODE i permite
'simbata',
specificarea unei serii de condiii,
'Zi lucratoare' relativ la un singur parametru sau
)AS Categoria__Zilei
expresie. A doua este mai flexibil, fiecare ramur WHEN avnd
FROM pontaje
WHERE
propria TO_CHAR(data,
condiie ' M M / Yn
de evaluat. Y Yoricare
Y ' ) = ' 0dintre
7 / 2 0 0 variante,
3' important
este ordinea de enumerate a condiiei/ valorii-etalon, deoarece o
Deidentificat
dat obicei, veteranii Oracle manifest
o egalitate, execuia este un ataament (attachment)
direcional numai pe
deosebit fa de DECODE. La fel i bobocii"
ramura respectiv, chiar dac ar urma i alte condiii ce Oracle care vor s ar
par
fi
veterani. Cnd valorile etalon sunt punctuale, atunci
ndeplinite. Pe de alt parte, dac lipsete ramura ELSE (echivalenta poate c e de
preferat DECODE.
OTHERWISE) Situaiile
i exist valori complexe
care nu se(intervale,
ncadreaz spre exemplu)
n nici sunt
una dintre
cele n care
condiiile CASE-ul ivaloarea
enumerate, arat fora. Spre exemplu,
returnat este NULL fiecrui
- veziangajat
figura
vrem
6.31. s-i afim un mesaj care s indice intervalul n care se
situeaz numrul anilor si de vechime n munc: sub 10 ani, ntre
SQL>
10 i SELECT
20 de narea,
ani i nunepren,
peste 20 colaborator,
de ani. Cu o structur CASE, lucrurile nu
2 CASE
sunt prea complicate:
3 WHEN colaborator = N* THEN 'Angajat cu
norma ntreaga
4SELECT
WHENnumepren, datasv,
colaborator = 'D' THEN 'Colaborator'
5EXTRACT
END AS (YEARFROM { ( D A T E ' 2 0 0 3 - 0 5 - 0 1 ' -datasv)
TipulAngajatului
6YEAR (2 personal
FROM ) TOMONTH) ) AS Ani,
7 / CASE
109 EXTRACT
WHEN Primul Angajat D
(YEARFROM ( ( D A T E ' 2 0 Colaborator
0 3 - 0 5 - 0 1 ' - datasv)
Nou YEAR (2) TOMONTH))
110 Angajat
111 Al Doilea 1 Angajat cu norma ntreaga
<10 THEN 'Sub 10 ani de
N Angajat cu norma ntreaga
vechime' Angajat cu norma ntreaga
112 Angajat 2
WHEN EXTRACT (YEARFROM ( ( D A T E ' 2 0 0Angajat 3 - 0 5 - 0cu
1 ' norma
- datasv)
N ntreaga
YEAR (2) T O M O N T H ) ) BETWEEN Angajat 10
cu norma ntreaga
113 Angajat 3
AND 20N THEN 'Vechime intre 10 Angajat
si 20 de cu
ani' norma ntreaga
ELSE
114'Peste 20 de ani de vechime'
Angajat 4 Angajat cu norma ntreaga
ENDAS Situatie_vechime
N Angajat cu norma ntreaga
FROM personal
115 Angajat 5
Figura 6.31. Condiie "netratat" ntr-o structur CASE
n schimb, deoarece DECODE lucreaz pe baz de egalitate de
Lund n apela
discuie tabela
truc:PONTAJE, dorim
prin ca n dreptul fiecrei
valori, vom la un convertim, TO CHAR, numrul de
nregistrri corespunztoare lunii iulie 2003 s apar DUMINIC",
ani ntr-un ir de caractere, apoi testm primul caracter din ani; n
smbt" sau Zi lucrtoare". Soluia bazat pe CASE este:
cazul n care anii sunt mai puini de 10, vom avea situaii de genul
1", 7" etc., deci primul caracter este spaiu; dac primul caracter
SELECT ponta je . *,
este 1", nseamn
CASE TO_CHARc numrul
(data, 'DAY' este
5 cuprins ntre 10 i 19:
WHEN 'SUNDAY' THEN 'DUMINICA'
SELECT
WHENnumepren,
'SATURDAY' datasv,
THEN 'simbata'
EXTRACT (YEARFROM
ELSE 'Zi lucratoare' ( ( D A T E ' 2 0 0 3 - 0 5 - 0 1 ' - datasv)
YEAR
END AS Categoria_Zilei) FROM
(2) T O M O N T H ) AS Ani,
DECODE
pontaj e (
SUBSTR(TO_CHAR
WHERETO CHAR(data, (EXTRACT
' M M / Y Y Y(YEARFROM
Y') = '07/2003'
( ( D A T E ' 2 0 0 3 - 0 5 - 0 1 ' - datasv) /
YEAR (2) TOMONTH) ) , ' 99' ) , 2 , 1 ) ,
iar cea bazat pe DECODE:
' ' , 'Sub 10 ani de vechime' ,
'1' , 'Vechime intre 10 si 20 de a n i ' ,
SELECT pontaj
'Pestee. *,20 de ani de vechime' )
DECODE (TO_CHAR(data,
AS Situatie_vechime ' D AY ' ) ,
'SUNDAY' , 'DUMINICA',
Pr imul Ang aj at No u 10 -JUL -
Al Do ile a Ang a jat 83
10 -JUL -
N o u a jat 1
Ang 03 -OC T-
12
Ang a jat 2 80
12 -N 0 U-
Ang a jat 3 78
02 -JL -
Ang a jat H Oracle, Ghidul
76 dezvoltrii aplicaiilor profesionale
05 -J AN- 179
Ang a jat 5 82
12 -N 0 U-
Ang a jat 6 NUPREN 77 -A PR-
11 DATASU ANI SITUATIEUECHIME
Ang a jat 7 85 -N 0 U-
21
Ang a jat 8 91 -DE C -
30
94
180 Oracle. Ghidul dezvoltrii aplicaiilor profesionale Interogri SQL 181

SPORURI i SALARII,
distincie realizatdin
ntre atributele prin intermediul
PI i cele din P2.celor trei brucanian
Intuiia atribute, ne
Marca, An i c
spune Luna, se poate
primele realiza
apte prin sunt
atribute trei variante:
ale PI. iar celelalte apte ale
6 Sub 10 ani de uechime O Sub
P2. 10 ani de vechime 22 Peste 20 de
tip SQL1: ani de uechime 2h Peste 20 de ani
SELECT * de uechime 26 Peste 20 de ani de
FROM sporuri, salarii uechime 21 Peste 20 de ani de
WHERE sporuri .marca = salarii .marca AND uechime 25 Peste 20 de ani de
sporuri.an = s a l a r i i . a n AND sporuri.lunauechime
= s a l a r18
i i . lUechime
una intre 10 si
20 de ani 11 Uechime intre 10 si
28 de ani 8 Sub 10 ani de uechime
cu INNER JOIN:
SELECT *
FROM sporuri INNER JOIN s a l a r i i
Figura 6.32. CASE/DECODE pe intervale
ON sporuri.marca = s a l a r i i . m a r c a AND
sporuri.an = s a l a r i i . a n AND sporuri.luna = s a l a r i i . l u n a

6.3. Jonciuni
cu NATURAL JOIN: interne
SELECT *
FROM sporuri NATURAL
ntruct JOIN salarii
inta prezentei lucrri este una covritor practic, nu
cheltuim prea mult spaiu cu fundamentarea te eretic a jonciunilor
Care sunt colegii de compartiment ai lui Angajat 2 ?
interne, ca o combinaie dintre produs cartezian i selecie, i nici cu
detalii reclam
Problema legate un
deartificiu
theta-jonciune, echi- jonciune
SQL: joncionarea i jonciune
a dou instane
natural.
ale tabelei Vom lucra,
PERSONAL duppentru nceput,
atributul la modul
compari general,liniilor
i filtrarea cu jonciuni
pentru pe care
una dinleinstane
vom aplica pentru rezolvarea
(numepren = 'Angajat ctorva probleme.este
2'). Operaiunea
posibil folosind dou alias-uri pentru cele dou instane.
Care sunt zilele din iulie 2003 n care Angajat 2 a fost la lucru ?
Informaia
SELECT care ne intereseaz, adic valorile atributului data,
pl. numepren
FROMprecum i pl,
personal condiia
personalprezen
p2 la lucru" - OreLucrate > 0, se afl n
WHERE pl. compart
tabela PONTAJE. = p2n
. compart
schimb,AND p2 . numepren
numele = 'Angajat
celebrului angajat2 ' se afl n
sau tabela PERSONAL. Aa c apelm la jonciune Pn la versiunea 9i,
Oracle s-a ncpnat s foloseasc exclusiv notaia SQL-89:
MAR NUMEfREH GDffrtr DATAS SALORA SALORARC NUMEPR COM DATASU SALDR SALORAR C
ae

CA R OC EN PA AR CO
S

Angajat 2 CONT 12-N0U-78 57588 56660 H 102 Angajat 2 CONT 12-N0U-78 57506 56000 N
1? SELECT A SELECT
pl. numeprendata A
106 Angajat A CONT 11 APR-85 71588 78608 H 102 Angajat 2 CONT 12-HOU- 575 08 56008 N
A A 78 N0U-7S
187 Angajat 7
Angajat 2 FROM CONT
A
CONT
FROMpontaje,
21 NUU-
personal
91
12-HOU-
61588
pl
57588 INNER personal
6 0808
56608
N
H
102 Angajat 2
JOIN
106 personal
Angajat 6 p2 CONT
A
CONT
12
11-APR-0S
57588
71500
56 000 N
70606 H
182 A 78 A
CONT WHERE pontaj78108 e. Nmarca = personal. A marca AND
1 06 Angajat 6 ON 11-APR-
pl.compart 71588 106 Angajat 6 CONT 11-OPR-85 71500 70080 N
187 Angajat 7 A
CONT 85
21 NOV- 61586 = p2.compart
oeoa N 106 Angajat 6 CONT 11-OPfl 85 71500 70000 N
182 Angajat 2 A
CONT 91
12-N0U-78 57560 56080 N 187 Angajat 7d a t a ) = A
CONT
186 Angajat 6 WHERE A p2
CONT 11 . EXTRACT
APR-85 numepren
71508 (YEAR
= N'Anga
78680 FROM
107 j 7
Angajat A
CONT 2 21-H0U-91
0 0 3 AND
21-NDU-91
61580
61500
60008 N
60800 N
1 87 Angajat 7 A
CONT 21-NGO-EXTRACT 61580 68668 N 187 Angajat 7 A
CONT 21-HBU-91 61500 60000 H
(MONTH FROM dMau
a t a )A
IT = 10-JUI-B3
7 AND 555 00
Angajat 1
at 2'
1 Primul Angajat Nousau A
II
IT
91
18-jm-ea
12-0CT-88
55588
56 880 55061
60
N
109 Primul
109 Primul
Angajat
Angajat Nnu IT 10-JUI -83 55508
0D
0D
1 81
1 Angajat 3 IT 02-JUL-76 numepren=
67568 66860'Angajat
N 189 Primul1'Angajat Hau IT 1S-JUL-B3 55580 0D
1 #5 Angajat 5 IT 12-NGV- 62568 62080 H 189 Primul Angajat Nou 17 10-JUL-B3 55500 fl D
189 Primul Angajat Hou IT 77
18-JUL-83 55580 00 1 81 Angajat 1 IT 12-OCT80 56000 55000 N
SELECT pl. numepren
181 Angajat 1
103 Angajat 3
IT
ITDin 9i, Oracle a revenit la sentimente mai bune fa de SQL-92,
12-0CT-88
C2-JIIL-76
56868
67586
55806 N
66160 N
181 Angajat 1
181 Angajat 1
IT 12-0CT-88 56000 55008 N
185 Angajat 5 FROM IT personal
12 HOU- pl INNER
2588 62668 N JOIN personal
101 Angajat 1 p2 ITIT
12-0CT-80
12-OCT-
56800
56800
ssooe N
55080 N
189 Primul Angajat Hau aa nct notaia este mai elegant:
IT
ON
77
18-Jill -83
pl. compart55500
= p2 0D
. 103 Angajat 3
compart AND IT Qfl
62-JllL-76 67500 66000 N
181 Angajat 1 IT 12-0CT-88 56868 55666 N 103 Angajat 3 IT 82-J0L-76 67500 66000 N
183 Angajat 3 IT B2-JUI.-76 7566 66860 N 103 Angajat 3 M 02-JUL-76 675 00 66000 N
185 Angajat 5 p2.numepren=
IT 12-NOU- 2566 'Angajat
62066 H 2'
103 Angajat 3 IT 02-JUL-76 67500 66000 N
189 Primul Angajat Hou IT SELECT
77
10-JUL-03 data
55580 6D 105 Angajat 5 IT 12-H0U-77 62500 62000 N
101 Angajat 1 IT 12-0CT-8B 56886 55601 H 105 Angajat 5 IT 12-N0U-77 62500 62880 N
183 Angajat 3 IT FROM pontaj e INNER JOIN personal
82-JUL-76 67508 66680 H 105 Angajat 5 IT 12-N0U-77 2500 62000 N
105 Angajat 5 Dincolo de notaia diferit, cele trei soluii au acelai principiu de
IT 12-N0U-77
18 JLMON 58588
62506 62000 N 105 Angajat 5 IT 12-N0U-77 62500 62 800 N
118 Al Doilea Angajat Hau PRO pontaje.marca 0 110 Al= personal.marca
Doilea Angajat Nou PROD 111-JUL sesee 0
funcionare, n prima faz, se joncioneaz instana Pl a tabelei
108 Angajat 8
10* Angajat *
D
PRO
D
PRO
30DEC-9*
WHERE
05-JAN-82
5*568
EXTRACT
75868
52BOB N
75888 H (YEAR FROM(MONTH
110 Al Doilea d
Angajat a t
Nou a )
PROD =
03
110 Al Doilea Angajat Nou PROD 10-JUL-03
2 0
10-JUL-B3 0 3
50500
AND
50500
0
EXTRACT
0
D
118 Al Doilea Angajat Hou PRO 18-JUI-83 585 8 8 8 108 Angajat 8 PfiflO 30-DFC-9* 5*5 08 52808 N
PERSONAL cu instana P2 a aceleiai tabele, atributul de joncionare
188 Angajat 8 D
PRO
D
30-DEC-9* FROM 5*588 d a 75660
t a ) N= 168
52600 H 7 AND
1B8 Angajat 0numepren= PROD 'Angajat
30-DEC-9* 5*5 1' 52080 N
00 52880
18* Angajat * PRO 85-JAH-82 75886 Angajat 8 PROD 3Q-DEC-9* 5*506 N
fiind D
D Rezultatul este cel din figura 6.33. SQL*Plus este un
compart.
11 H Al Doilea Angajat Hau PRO 18-JUL-83 5 05 6 0 a 18* Angajat * PROD 05-JAN 82 75000 75006 N
188 Angajat 8 PRO 36-DEC-9* 5*560 52688 H 10* Angajat * PROD 05-JAN-82 75600 75000 N
D
pic derutant,
18* Angajat *
Ba, deoarece
Dmai mult,n
PRO BS-JAN-
82 figur
cnd nu tabele
dou se poate
75 068
face
sunt joncionate dup atribute cu
75008 N 10* Angajat * PROD 05-JAN-82 75600 75000 N

nume identic, se poate apela cu succes la operatorul NATURAL JOIN.


Astfel, joncionarea tabelelor
182 Interogri SQL

FROM (p o nt a je po l IN N ER JOIN pe rs o nal p e l ON


p o l .mare a = p e l .mar ca AN D nume p re n = ' Ang ajat 1 ' )
IN N ER JOIN
( po nt aje po 2 IN N ER JOIN pe rs o nal p e2 ON
p o2 .ma rca = p e2 .ma rc a AN D pe 2 . nume p re n =
' Prim ul Ang a jat N o u' )
ON po l.d at a = p o2 .d at a

Rezultatul este cel din figura 6.35.

1 SELECT pol.data AS Ziua


2 FROM (pontaje pol INNER JOIN personal pel ON
3 pol.marca = pel.marca AND numepren = Angajat 1)
If INNER JOIN
5 (pontaje po2 INNER JOIN personal pe2 ON
6 po2.marca = pe2.marca AND pe2.numepren = Primul Angajat Nou a)
7 * ON pol.data - po2.data
SQL> /

ZIUA

9- JUL-03
Figura 6.33. Jonciunea a dou instane ale tabelei PERSONAL prin atributul compart
10- JUL-03
11- Rezultatul
JUL-03 final al interogrii este cel din figura 6.34. Pentru
eliminarea Angajatului 2 Intersecie
Figura 6.35. din rezultat ar trebui ca n WHERE s fie
prin jonciune
inclus i condiia pl. nume- pren O 'Angajat 2'.

6.4. Reuniune,
SQL> SELECT intersecie, diferen
p1.nunepren
2 FROM personal p1 INNER JOIN personal p2
Discuia
3 ONdin acest paragraf
p1.compart este, in mare
= p2.compart AND parte, de prisos,
p2.nunepren deoarece 2*
= Angajat
pn n acest
/ paragraf am recurs de cteva ori i la reuniune, i la
intersecie.
NUMEPREN
Care sunt angajaii compartimentelor Contabilitate i IT?
Angajat
La
2 cele dou soluii formulate n primul paragraf al capitolului
Angajat
(operatorii SAU logic i IN), putem aduga una ce utilizeaz UNION:
6
SEL E CT * FROM p e rs o nal WH ERE co mp art = ' CON TA'
Angajat
UN
7 ION
SEL E CT * FROM p e rs o nal WH ERE co mp art = ' IT'
Figura 6.34. Colegii de compartiment ai lui Angajat 2 (plus el nsui)
Care sunt zilele din iulie 2003 n care a lucrat mcar unul dintre
oameniiCare
muncii (dezilele
sunt la orae i sate)
n care au Angajat 1 i Primul
lucrat simultan Angajat
Angajat 1 i Primul
Nou Angajat
? Nou?
DacDei
se folosete operatorul
ne este destul UNION,
de greu, srezultatul ar conine
presupunem c nu nou linii, de
tim nimic
corespunztor
existena celor nou zileINTERSECT,
operatorului n care mcar
pe unul dintre
care-1 vomceipomeni
doi a n
venit laSELECT
serviciu:
p o l . data AS Ziua
SEL E CT Dat a
Oracle. Ghidul dezvoltrii aplicaiilor profesionale 183

ON po .ma rca= p e .mar ca WH ERE nume p re n


= ' Ang ajat 1' AN D
TO_CH AR(d at a, 'M M/ YY YY' ) = ' 07 /2 00 3 '
UN ION
SEL E CT Dat a
FROM po nt aje po INN ER JOIN p e rs o na l pe ON po ,mar ca= p e .marc a
WH ERE nume p re n = ' Pri mul Ang ajat N o u'
AN D TO_CH AR( d at a, 'M M/ YY YY' )= ' 07 /2 00 3'

n schimb, operatorul UNION ALL extrage 12 linii, neeliminnd


duplicatele, astfel nct din analiza figurii 6.36 putem deduce c pe
9, 10 i 11 iulie ambii angajai au fost la lucru, n timp ce n restul
zilelor numai Angajat 1 a fost prezent.
SEL E CT Dat a
FROM po nt aje p o IN N ER JOIN p e rso na l pe ON po .mar ca= p e .marc a
WH ERE nume p re n = ' Ang aj at 1 ' AN D
TO_CH AR(d at a, 'M M/ YY YY' ) =' 0 7/ 20 03 '
UN ION AL L
SEL E CT
Dat a
FROM po nt aje p o IN N ER JOIN p e rso na l pe ON
p o .marc a= pe .m arc a WH ERE numep re n = Pr imul Ang ajat No u'
AN D TO_CH AR( d at a, 'M M/ YY YY' ) =' 0 7/ 20 03 ' *
SQL> SELECT Data
SQl> SELECT Data 2 FROM pontaje po INNER JOIN personal pe
2 FROM pontaje po INNER JOIN personal pe 3 ON po.narca-pe.narca
3 OH po.nareape.narca *t WHERE nunepren - 'Angajat 1*
a (MERE nunepren 'Angajat 1* AND 5 AN) TO CHAR (data, *NH/VW )-'07/2 083'
5 TO CHAR(data, *HH/VVVV*)-*07/2003* 6 UNION ALL
6 ONION 7 SELECT Data
7 SELECT Data 8 FROH pontaje po INNER JOIN personal pe
0 FROM pontaje po INNER JOIN personal pe 9 ON 9 ON po.narca-pe.narca
po.narcape.narca 10 WHERE nunepren - Prinul Angajat Nou*
t o WHERE nunepren - 'Prlnul Angajat Nou* AND 11 AND TO_CHAR(data , *HN/VVVV )-* 07/2003*
11 TO CHAR(data, MH/VVVV )-* 07/2003* 12 /
12 /"
DATA
DATA

1- J
JUL-03
JUL-03 L
J0L-03 -
0A-JUL-O3 0
07-JUL-03 3
D8-J0L-03 2- J
D9-JUL-03 U
10- JUL-03 L
11- JUL-03 -
9 rows selected. O
3
B
12 rows selected.

Figura 6.36. Diferena dintre UNION i UNION ALL

Ef e ct ul UN ION AL L es t e s imila r fo los ir ii o pe r at o rului OR s au


s o lu ie i b azat e p e
IN:

SEL E CT Dat a
FROM po nt aje p o IN N ER JOIN p e rs o nal pe ON p o .marc a= pe .m arc a
WH ERE^ n ume p re n = ' Ang aj at 1 ' OR
184 Interogri SQL
Oracle.
186 Ghidul dezvoltrii aplicaiilor profesionale Interogri185
SQL
nume p re n= ' Primu l Ang a j at No u ' ) AN D TO_CH AR
M ERGE IN TO s alar ii SA USIN G
( d at a, MM / YYY Y ' ) = ' 0 7/ 20 03 '
(SEL
SEL ECTE CT p.ma
EX TRACrc a,T nume
( YEAR FROM
p re n, co mpd atart
a) ,AS a n,
Care EXTRA
o re lucr
suntat eCT AS( MON
zilele Ore n_LTHucr_
care FROM
Aug ,doat
au lucrat rea) AS ASlun a, mar
cosimultan ca, 1 i Primul
Angajat
SUM ( o
Angajat Nou?
Ore _CO_Aug re lucr at e ) AS o re lucr
FROM personal p L EFT OUTER JOINat e ,
s alarSUM
ii s ( o re co ) AS o re co FROM po nt a je
Acum WHputem
ERE
ON EXTRp.m ACaT =( YEAR
arc
recurge sla.marc FROM
a ANdDatan=
operatorul a) = 20303
2 00
INTERSECT: andANluna=
D EXTR 8 ACT
(M ON TH FROM d at a) = 8 GROUP BY EX TRAC T ( YEAR FROM
Ultimele dou rnduri din figura 6.38 corespund celor doi
d at a
SEL ) , d at a AS Ziu a
E CT
angajai fr CT
EXTRA niciMun pontaj pe daugust 2003, lucru indicat de spaiile
FROM po nt a j (e ON
p o TH
IN NFROM
ER JOIN at
pea)rs, oma
nalrcpe
a ON
ce )apar
POp on dreptul coloanelor r e f e r i t o a r e l a o r e l e l u c r a t e i
.marc a = pe .ma rca AN D nume p re n = ' Ang aj at 1'
o r eIN
l eTERS
ON d e.ECT
( SA anconcediu.
= P O. an AN In DSQL*Plus,
SA . luna= Pspaiile
O. lun a AN respective
D S A .m arcsemnific,
a =
pentru
SEL Eacest
CT d atgen
PO. mar ca
a ) de situaii, valori NULL.
FROM po nt a j e pTH
WH
MORCO EN M ATCH
NUMEPREN ED ENN ER JOIN pe rs
o IN COMPA
o nal ORE
pe ON LUCR AUG ORE CO AUG
UPDATE SET SA .o re lucr at e = S A .o re
p o .m arc a = pe . mar ca AN D nume p re n = ' Primu lu crat e + P O.o re
l lucr
Angat e , No u f
aj at
SA181.o re co Angajat
= S A .o re1 co + PO.o re co WH EN N OT
M ATCH
Care 182ED TH
sunt EN
Angajat
zilele din iulie2 2003 n care a lucrat Angajat 1, dar NU a
INSERT
lucrat Primul 183 Angajat(S A . an,
Angajat S A
Nou?3.lu na, S A .m arc a, S A .o re lu crat e ,
184 SA .o re co)
Angajat 4 VALUES ( PO. an, P O.lun a, P O. ma rc a,
185 Angajat PO. 5 o re lucr at e , PO. o re co )
Soluia se bazeaz pe diferen, ns, spre deosebire de standardul
SQLCare 186
n sunt
care Angajat
operatorul 6 folosit estepentru
EXCEPT, n angajat
Oracle pese
187 orele lucrate
Angajat 7 i de concediu fiecare
ntrebuineaz
luna^imie 2003 MINUS: ?
188 Angajat 8
189SEL E CT
Primul Angajat Nou
\S\S^
Folosind d at a AS Ziu a se obine rezultatul din figura 6.37, n care
jonciunea,
110 Al Doilea Angajat Nou
FROM po nt a je p o IN N ER JOIN p e rs o nal pe ON po .ma rca = p e . m arc a
sunt exclui angajaii 109 i 110, deoarece liniile lor din PERSONAL
AN D nume p re n= ' Ang aj at 1' AN D TO_CH AR( d at a,
nu au corespondent
'MM/YYYY') =' 07 n/ 20
PONTAJE.
03
M IN US
SEL E
SEL ECT
CT dp.ma
at a rc a, nume p re n, co mp art , o re luc rat e AS
Ore _L ucr_A
FROM po nt a ugje
, opre
o co
IN NAS
ER Ore _CO_
JOIN p e Aug FROM
rs o nal p e rso
pe ON na l p aIN=N pe
p o .marc ER.ma rc a
JOINANs alar ii s ON p . marc a = s .ma rca
D nume p re n = ' Pr imul Ang aj at No u' AN D an= 20 03 and
luna= 8

Angajat 1 IT 32 0
101
102 Angajat 6.5.
2MARCO Jonciuni
CONTA externe,
NUMEPREN 16 valori
DOMPA ORE LUCRnule
16AUG ORE C0 AUG
103 Angajat 3 IT 24 8
104 Angajat 4
Jonciunea PROD are o larg
extern 32 utilizare 0datorit posibilitii
105 Angajat 5 IT
extragerii, din cele dou tabele 32 0
joncionate, att a liniilor
106 Angajat 6 CONTA 32 0
corespondente, ct i a celor fr corespondent. Standardul SQL-92
107 Angajat 7 CONTA 16 16
introduce
Angajat 8 operatorii
PROD necesari jonciunii
32 externe:
0
108
LEFT OUTER JOIN pentru jonciune extern la stnga,
RIGHT OUTER JOIN pentru jonciune extern la dreapta,
FULL OUTER JOIN pentru jonciune extern total (n ambele direcii).

Pentru luna Figura 6.37.2003,


iulie Lista incomplet,
toi cei datorat
zece jonciunii
angajaiinterne prezint pontaje; n
schimb, n august,
Rezolvarea problemeidoi dintrevine de ei,lacei cu mrcile
operatorul 109 i extern
jonciune 110, sunt
la
totalmente abseni. Beneficiind de suportul
stnga, care, pe lng liniile jonciunii interne, include n rezultat i comenzii MERGE,
discutat n ultima
nregistrrile tabeleipartedin a capitolului precedent, actualizm
stnga (PERSONAL), tabela
unde valorile
32 8
atributului Marca nu se regsesc n SALARII pentru anul 2003, luna
CONTA 8: 16 16
IT 24 8
PROD 32 0
IT 32 8
CONTA 32 8
CONTA 16 16
PROD 32 0
1 01 Ang aj at 1 72 32 1 84
1 02 Ang aj at 2 40 16 56

188 Interogri SQL 187


Oracle. Ghidul dezvoltrii aplicaiilor profesionale
MARCO NUMEPREN ORE_LUCR_IUL ORE_LUCR_OUG Ore_Lucr_Iul-Aug

Transformnd fraza SELECT pe logica jonciunii externe la


dreapta, obinem:
SEL ECT p.ma rc a, nume p re n FROM s alari i s , p e rso na l p
WH EREs . mar ca ( + ) = p. mar ca AN D a n ( + ) = 2 00 3 AN D lun a
(+ ) = 8 AN D s . mar ca IS N UL L sau, dup noul format conform cu
SQL-92:
SEL ECT p.ma rc a, nume p re n
FROM s al ari i s RIGH T OUTER JOIN pe rs o nal p
ON s .marc a = p .ma rca AN D an = 20 03 AN D luna = 8
WH ERE s .marc a IS N UL L

Firete, aceeai informaie putea fi obinut din PONTAJE astfel:


SEL ECT pe .mar ca, numep re n FROM p e rso na l pe L EFT OUTER
JOIN po nt a je p o ON pe . mar ca = po . ma rca AN D TO_CH AR( d at a,
'M M/ YY YY' ) = ' 08 /2 00 3'
WH ERE p o . m arc a IS N ULL

Care sunt orele lucrate de fiecare angajat n lunile iulie i august


2003, att pe luni, ct i nsumat IT ?
PROD
Se joncioneaz extern tabela PERSONAL cu dou instane ale
tabelei SALARII,
Figurauna pentruextern
6.38. Jonciune lunalaiulie
stnga i altaAL-SALARII
PERSON pentru august:
Interesant
SEL ECT p.ma este
rc a,c,
numepn
p re n,las l.o
versiunea 9i, Ore
re lu cr at e AS Oracle nul, a avut
_L ucr_Iu
implementate
s2 .o recele
lucr attrei clauze
e AS dedicate
Ore _L ucr_ aug , jonciunii externe, n acest
scop folosindu-se semnul
s l.o re lu crat e + s2+. Astfel,
.o re lucr at ejonciunea extern
AS "Ore _L ucr_ la "stnga se
Iul- Aug
realiza de maniera urmtoare:
FROM p e rso n al p
L EFT OUT ER JOIN s alar ii s l
SEL ECT ON p .marc
p.ma rc a, a = s lp.m
nume arcco
re n, a mp
AN Darts ,l. an= 20 03 AN D s l.
luna= 7 L EFT OUTER JOIN s ala rii s 2
o re lucr at e AS Ore _L ucr_A ug , o re co AS Ore
ON p .mar ca = s 2 .mar ca AN D s 2 . an= 2 00 3 AN D s2 . luna= 8
_CO_Aug
FROM p e rso n al p , s alari i s
WHDin
EREpcate,
p.ma rctotalul
a = s .ma se rccalculeaz numai
a ( + ) AN pentru
D 20 03 = an ( cei
+ ) care
and au lucrat
8= lun a
( +n) ambele luni (figura 6.39), deoarece o valoare NULL care apare
ntr-o expresie atrage dup sine NULL-itatea expresiei, indiferent de
Semnul (+) se plaseaz la atributul din dreapta semnului egal,
valorile celorlali termeni.
atribut care trebuie s fie, obligatoriu, din tabela n care nu se
gsesc nregistrri corespondente valorilor tabelei din stnga.

Care sunt angajaii fr nici un pontaj pe august 2003 ?

Pn la a ajunge la subconsultri, putem valorifica faptul c liniile


fr corespondent prezint n rezultatul unei jonciuni externe
valoarea NULL. Aa c interogarea urmtoare funcioneaz:
SEL ECT p.ma rc a, nume p re n
FROM p e rso n al p , s alari i s
WH ERE p . mar ca = s .ma rca ( + ) AN D20 0 3= a n ( + ) a nd 8= luna ( +
1 83 Ang aj at 3 40 24 64
1 04 Ang aj at 4 72 32 1 04
1 85 Ang aj at 5 72 32 1 04
1 06 Ang aj at 6 72 32 1 04
1 87 Ang aj at 7 40 16 56
1 08 Ang aj at 8 72 32 1 04
1 09 Prim ul Ang a jat N o u 24
1 10 Al Do ile a Ang aj at No u 24

Figura 6.39. Propagarea valorii NULL


n asemenea situaii, Oracle pune la dispoziie NVL care
funcia , transform o
eventual valoare nul ntr-o alta
specificat:
SELECT p.marca, numepren,
NVL( sl.orelucrate,0) AS Ore_Lucr Iul,
NVL(s2.orelucrate,0) AS Ore Lucr aug,
NVL(sl.orelucrate,0) +NVL(s2 .orelucrate,0)
AS "Ore Lucr Iul-Aug"
FROM personal p
LEFT OUTER JOIN salarii sl
ON p.marca = sl .marca AND sl. an=2003
AND sl.luna=7
LEFT OUTER JOIN salarii s2
ON p.marca = s2 .marca AND s2 . an=2003
AND s2 . luna=8

Cum este i normal, pentru nsumarea orelor pe iulie i august,


valorile nule vor
fi substituite prin zero, ceea ce conduce la un vezi figura
calcul corect - 6.40.
IUL 0 re _L ucr_Iu -
M ARC A N UM EPR EN 0RE_LU CR_ AUG
0RE_LUCR l Aug

1 01 Ang aj at 1 72 32 1 04
1 02 Ang aj at 2 40 16 56
1 03 Ang aj at 3 40 24 64
1 04 Ang aj at 4 72 32 1 04
1 05 Ang aj at 5 72 32 1 04
1 06 Ang aj at 6 72 32 1 04
1 07 Ang aj at 7 40 16 56
1 08 Ang aj at 8 72 32 1 04
1 09 Prim ul Ang a jat N o u 24 0 24
1 10 Al Do ile a Ang aj at No u 24 0 24
URCA NUMEPREN 0RE_L_IUL SAL_BAZA_IUL CRE_L_AUG SALBAZAAUG 0re_lul-Aug SalBaza_Iul-Aug

181 Angajat 1 72 4032 000 32 1792000 104 5024000

190
Oracle. Ghidul dezvoltrii aplicaiilor profesionale Interogri SQL
189

diferit de NULL.
CASE WH ENDes2asemenea, nuISde
. o re lu crat e N OTmult
N ULLtimp a aprut funcia
TH EN s2 . o re luc rat e EL SE 0 EN
NVL2, ce evalueaz nulitatea unei expresii i returneaz D AS Ore _L ucr_ aug ,
o valoare a
CASE WH EN si. o re luc rat e IS N OT N UL L
unei alte expresii. Sintaxa este: NVL2(expresie_de_test, valoare
TH EN si. o re lucr at e EL SE 0 EN D +
retumat cnd expre- sie de test este nenul, valoare returnat cnd
CASE WH EN s2 . o re luc rat e IS N OT N ULL
expresie de test este nul).
TH ENAstfel, calculm
s2 . o re salariul
luc rat e EL SE 0 de baz pe lunile
iulie i august, ca produs
EN Dntre orele lucrate i salariul tarifar orar:
AS "Ore _L ucr_I ul- Aug "
FROM
SEL p e rsorc
ECT p.ma n al
a, pnume p re n,
L EFT
COAL OUTESERCE JOIN
(s l.osrealar
lucr iiats ie ,0) AS Ore _L _Iul,
ON (s
N VL2 p l.o
.mar cacrat
re lu = sei ,.ma
s l.orc rea luc
ANrat
D si.
e *san=
alo r2ar,
00 3
0)AN D s i. lun a= 7
L EFT OUTAS ER Sal_
JOINBaz s alar ii s 2
a_Iul,
ON ES
COAL p . mar
CE {sca2=. s2 o re.mar
luc rat caeAN , 0D
) ASs 2 Ore
. an=__L 2_aug
00 3 AN
, D s 2 . lun a= 8
N VL2 (s 2 .o re lucr at e , s2 .o re lucr at e *s alo ra r, 0 )
s au o f unc ieAS DESal_
CODE: Baz a_Aug ,
COAL ES CE( s l.o re lucr at e , 0) + COAL ES CE (s 2.o re luc rat e ,0 )
SEL ECT p.AS ma"Ore
rc a, _Iul-
nume Augp re ",n,
DECODE (s i.o re lucr
N VL2 (s l.o re lu crat e , s l.o at ere, N ULL
luc , e
rat 0 *s
, si.o
alo rre luc
ar, 0}rat+e )
AS Ore _L ucr_I ul,
N VL2 (s 2 .o re lucr at e , s2 .o re lucr at e *s alo ra r, 0 )
DECODE (s 2.o
AS "Sal re luc
Baz a_Iul-ratAuge , N"UL L , 0 , s2 .o re lucr at e )
FROM p e rso nAS al p Ore _L ucr_ aug ,
DECODE
L EFT OUT ER (s i.o
JOINre lucr
s alaratiie ,sN l ULL , 0 , si.o re luc rat e ) +
ON DECODE
p .mar ca {s=2 .o s lre lucr at
.marc a eAN
, N DUL L , 0 , s 2.o re luc rat e )
s l.
an= 20 0 3 AS AN"Ore
D s l._L ucr_I 7
luna= ul-LAug
EFT "OUTER JOIN
FROM
s alarp ii
e rso
s 2 n al p
L EFT ONOUTpER JOINa s=alar
. marc s2 ii si
. marc a
ONAN p .Dmar
s2 ca. a= n=2s i 0.ma
03 rc
AN a DAN s2D .si. an=82 00 3 AN D s i.
luna=
luna= 7 L EFT OUTER JOIN s alar ii s 2
ON p . mar ca = s2 .mar ca
Pentru prima funcie ANNVL2
D s2 .an= din 20 interogarea
0 3 AN D s 2.1 deuna=
mai8sus, logica este
urmtoarea: cnd valoarea sl. orelucrate este nenul, funcia
returneaz
Oracle produsul
9i a preluat
sl. din standardele
orelucrate SQLnfuncia
* salorar; caz contrar, zero care,
COALESCE, - vezi
figura 6.41.
pentru problema de fa, se poate aplica identic:

SEL ECT p.ma rc a, nume p re n,


COAL ES CE (s l.o re luc rat e ,0) AS Ore _L uc r_Iul,
COAL ES CE {s 2 .o re lucr at e , 0) AS Ore _L ucr_ aug ,
COAL ES CE (s l.o re luc rat e ,0) + COAL ESC E ( s2 .o re lucr at e ,0)
AS Ore _L ucr_Iu l- Aug "
FROM p e rso na l p
L EFT OUT ER JOIN s alar ii s l
ON p .mar ca = s l .marc a AN D s l. an= 20 03 AN D s l.
luna= 7 L EFT OUTER JOIN s al arii s2
ON p .mar ca = s 2 .mar ca AN D s 2 . an= 2 00 3 AN D
Figura 6.40. Substituirea valorilor NULL
s2 . luna= 8
Trebuie s recunoatem, fr a cunoate funcia NVL, problema
este rezolvabil.
Fo rmat ul Cea mai
ge ne lastndemn
r al e e mai put eerni o cstructur
de c t ce lCASE:
al func ie i N VL , n
se ns ul c arg ume nt ul f unc ie i es t e o lis t d e o ric t e valo ri,
reECT
SEL t urn nd u-
p.ma rcsa,
e prim
numeapva
relo
n,are
CASE WH EN s l. o re luc rat e IS N OT N ULL
TH EN sl.o re luc rat e EL SE 0 EN D AS Ore L ucr Iul,
102 Angajat 2 40 2300000 16 920000 56 3220000
183 Angajat 3 40 2700000 24 1620000 64 432 0000
18<i Angajat <i 72 5400000 32 2400000 104 7800000
105 Angajat 5 72 4500000 32 2000000 104 6500000
106 Angajat 6 72 5148000 32 2208000 104 7436000
107 Angajat 7 40 246 0000 16 904000 56 3444000
108 Angajat 8 72 3924000 32 1744000 104 5668000
109 Prlnul Angajat Nou 24 1332000 0 0 24 1332000
110 Al Doilea Angajat Nou 24 1212000 0 0 24 1212000
Oracle. Ghidul dezvoltrii aplicaiilor profesionale 191

6.6. Funcii-agregat: COUNT, SUM, VG, MIN,


MAX
Intrm abrupt n cteva exemple.

Ci angajai mimar firma ?

Funcia COUNT contorizeaz valorile nenule ale unei coloane sau


numrul de linii dintr-un rezultat al unei interogri, altfel spus, n
rezultatul unei consultri, COUNT numr cte valori diferite de NULL
are o coloan specificat sau cte linii sunt n tabela (tabelele)
enunate n clauza FROM i, eventual, filtrate" n WHERE:

SEL ECT COUN T ( *} AS N r_Ang a j


at i FROM pe rs o nal

Prezena asteriscului ca argument al funciei COUNT are ca efect


numrarea liniilor tabelei - figura 6.42.

SQL> SELECT QOUHT(*) AS Nr_Angajati


2 FROM personal
3 /

NR ANGAJAT!
10
Figura 6.42. Numrul angajailor
Tabela PERSONAL are drept cheie primar atributul Marca, atribut
ce nu poate avea valori nule; de aceea, la fel de corect este i
soluia:

SEL ECT COUN T ( marc a) AS N r_Ang a jat i


FROM p e rso n al

Ba chiar locul atributului Marc poate fi luat de orice atribut


declarat cu restricia NOT NULL la creare.

Cte linii are produsul


Figura 6.41.cartezian
Funcia NVL2 al tabelelor PERSONAL i
PONTAJE ?

Simpla enumerare a celor dou tabele n clauza FROM determin


efectuarea produsului cartezian al acestora, funcia COUNT
numrndu-i liniile:

SEL ECT COUN T ( *)


Ci angajai au lucrat pe 10 iulie 2003 ?
192 Interogri SQL

SEL ECT COUN T ( * )


FROM p o nt a j e
WH ERE d at a = DAT E' 20 03 - 07 -1 0'

Cte compartimente are firma ?

Dup cum se observ n partea stng a figurii 6.43, interogarea:

SEL ECT COUN T ( co mp a rt )


FROM p e rso n al

furnizeaz eronat rspunsul, deoarece se numr toate valorile


nenule ale atributului compart, n timp ce problema privete numrul
de valori distincte nenule ale acestui atribut, lucru posibil prin
ntrebuinarea clauzei DISTINCT (partea dreapt a figurii 6.43):

SEL ECT COUN T ( DISTIN CT co mp art )


FROM p e rso n al

SQL> SELECT COUNT(compart) SqL> SELECT COUNT(DISTINCT compart}


2 FROM personal 2 FROM personal
3 t 3/
COUNT(COMPORT) COUNT(DISTINCTCONPORT)

Figura 6.43. Funcia COUNT, fr i cu DISTINCT

Cte ore de noapte are pe luna iulie 2003 angajatul cu marca


104 ?
Intr n scen funcia SUM (rezultatul n figura 6.44):
SEL ECT SUM ( o re no ap te )
FROM p o nt aje INN ER JOIN p e rso na l
ON p o nt aje .ma rc a=p e rs o nal .mar ca WH ERE
TO_CH AR( d at a, ' MM / YYY Y') = ' 07 /2 00 3' AN D
nume p re n= ' Ang ajat 4 f

SQL> SELECT SUH (orenoapte)


2 FROM pontaje INNER JOIN personal
3 ON pontaje.marca-personal.narea

r
U WHERE T0_CHAR(data, ,MM/VVW ) = '07/20831 AND
5 numepren = 'Angajat 4'
6 /

SUM(ORENOAPTE)

m
5
Figura 6.44. Funcia SUM
Oracle, Ghidul dezvoltrii aplicaiilor profesionale 193

Ca i n cazul funciei precedente, funcia SUM poate lua n calcul


o singur dat fiecare valoare distinct - vezi figura 6.45.

SQL> SELECT SUM (orenoapte) FROM pontaje


2 WHERE TO_CHAR(data, *MM/YVVV*) = *87/2003 *
3 /

SUM(ORENOAPTE)

11*

SQL> SELECT SUM (DISTINCT orenoapte) FROM pontaje


2 WHERE TO_CHAR(data, *MM/YYYY*)=*07/2003*
3 /

SUM(DISTINCTORENOfiPTE)

Figura 6.45. Funcia SUM, cu i fr DISTINCT

Care este salariul mediu al angajailor din compartimentul IT ?

Funcia cea mai nimerit este AVG (de la AVeraGe, adic medie
aritmetic). Pentru comparabilitate, interogarea urmtoare (figura
6.46) extrage i numrul angajailor IT, i suma salariilor orare ale
acestora:

SEL E CT COUN T ( *) AS N r_I T, SUM (s alo r ar) AS Sum a_IT,


AVG( s alo r ar) AS M ed ie _Sa l_IT
FROM p e rso n al WH ERE co mp a rt = '

SQL> SELECT C0UNT(*) OS Nr_IT, SUM(salorar) AS Suma_IT,


2 AUG(salorar) AS Medie_Sal_IT
3 FROM personal
4 WHERE compart = 'IT*
5 /

NR IT SUMA IT MEDIE SAL IT

4 241500 60375

Figura 6.46. Funcia AVG


Funcia AVG ia n considerare numai valorile nenule. Pentru a
sesiza diferena, interogarea urmtoare calculeaz o medie a orelor
lucrate pe luna iulie 2003 n dou moduri: prin mprirea sumei
orelor lucrate la produsul dintre numrul
194 Interogri SQL

zilelor lucrtoare din iulie i cel al angajailor (coloana Mediel Ore),


iar n al doilea mod, se folosete funcia AVG (AVG Ore):

SEL E CT COUN T (DISTIN C T Dat a) AS N r_Z ile ,


COUN T (DISTIN C T M arc a) AS N r_Ang aj at i,
SUM (o re lu crat e ) AS Sum a_Ore ,
SUM (o re lu crat e ) /
( COUN T ( DISTIN CT Dat a) * COUN T (DISTIN C T mar ca) )
AS Me d ie l_Ore ,
AVG( o re lucr at e ) AS AVG_O re
FROM po nt a je
WH ERE TO_CH AR( d at a, ' MM / YYY Y') = ' 07 /2 00 3'

Diferena dintre valorile celor dou medii (vezi figura 6.47) se


datoreaz faptului c pentru calculul Mediel Ore suma orelor lucrate
(528) se mparte la produsul nr zile * nr angajai (90), rezultatul fiind
5,8666..., n timp ce AVG Ore reprezint raportul dintre 528 i 78,
deoarece o parte dintre angajai nu au pontaje pentru toate zilele
lucrtoare din iulie.

NR ZILE NR ANGAJAI SUNA ORE HEDIE1 ORE AUG ORE

9 10 528 5.86666667 6.76923077


Figura 6.47. Dou medii
n funcie de ceea ce se dorete efectiv a se calcula, se poate
alege una dintre cele dou metode.

Care este cel mai mare i cel mai mic salariu orar ?
A so s it mo me nt ul f o los iri i f unc iilo r M AX i M IN :
SEL E CT M AX ( SalOr ar) AS Sa l_M AX, M IN ( SalO rar) AS
Sa l_M IN FROM pe rs o nal

SAL_MAX SALMIN
75000 50500
Figura 6.48. Funciile MAX i MIN
Care este ultima zi lucrtoare a lunii iulie 2003 ?
SEL E CT M AX ( Dat a) AS Ult im a_Z i_L ucr at o are _Iul
FROM po nt aje
WH ERE TO_CH AR( d at a, ' MM / YYY Y') = '0 7/ 2 00 3'

Care sunt cele mai mari dou salarii orare?


Cu nivelul de SQL de care dispunem putem formula o soluie
interesant prin joncionarea a dou instane ale tabelei PERSONAL,
dup condiia: salariul orar
Oracle. Ghidul dezvoltrii aplicaiilor profesionale 195

din prima tabel s fie mai mare dect cel din a doua. Rezultatul
jonciunii conine 45 de linii (dac nu ne credei, calculai !), ns
graie funciei MAX, va fi selectat numai prima, cea care ne
furnizeaz rspunsul (vezi figura 6.49):

SEL ECT M AX (
' Pe lo cul I ' | |
TO_CH AR( PI.S alOr ar, '9 99 99 99 ' ) | |
', ia r p e lo cul al II- le a ' | |
T0 _CH AR( P2 .SalOr ar, '9 99 99 99 ' )
) AS Tip _To p _M ini_ To p FROM
pe rs o nal p l IN N ER JOIN pe rs o nal p 2 ON
p l.s alo r ar > p 2.s alo r ar

TIP TOP MINI TOP


Pe locul I 75000, iar pe locul al II-lea 71500

Figura 6.49. Primele dou salarii orare

6.7. Gruparea tuplurilor. GROUP BY i HAVING


Clauza GROUP BY formeaz grupe (grupuri) de tupluri ale unei relaii,
pe baza valorilor comune ale unui atribut, iar HAVING permite
selectarea anumitor g r u p u r i d e t u p l u r i ce ndeplinesc un
criteriu, criteriu valabil numai la nivel de grup (nu i la nivel de
linie).

Ci angajai lucreaz n fiecare compartiment?

Atributul de grupare este Compart, iar funcia ce determin


numrul angajailor este COUNT (vezi i figura 6.50):

SEL ECT co mp a rt , COUN T ( *) AS N r_Ang aj at i FROM pe rs o nal GROUP


BY co mp a rt

COMPORT NR 0NG0J0TI

CONTO 3
IT il
PROD 3
Figura 6.50. Numrul angajailor din fiecare compartiment
Oracle. Ghidul dezvoltrii aplicaiilor profesionale 197
196 Interogri SQL
UNION
S se SELECT
afieze compart,
situaia orelor lucrate de
RPAD(CHR(123 ] 1fiecare angajat -pecompart
[ ' Subtotal luna iulie
' |2003.
| Ordinea
afirii
este cea a compartimentelor,
compart,32,'-') , n cadrul fiecrui compartiment
angajaii
SUM(orelucrate * salorar) fiind ordonai
FROM personal pe LEFT OUTER JOIN ponta j e po ON
alfabetic.
pe.marca=po.marca
De data aceasta, avem dou atribute de grupare, Compart i
NumePren, plus AND TO CHAR{data,'MM/YYYY' )=' 07/2003'
GROUP BY compart, CHR(254) | | 'Subtotal - compart '
funcia SUM. Dispunerea liniilor n rezultat este asigurat prin clauza
| | compart
ORDER BY:
UNION
SELECT RPAD (CHR (123) , 8,'='),
TO CH AR ( d at a,'M M/ Y YY Y') = '0 7/ 2 00 3'
COMPORT NUMEPREN RPAD (CHR (123) ! 1 ' TOTAL General
UENITBAZA ' , 32, ' = ') ,
GROUP BY co mp art , nume p re n ORDER BY co mp a rt , nume p re n
SUM(orelucrate * salorar)
Angajat
FROM2 personal pe LEFT OUTER JOIN ponta 2300000 j e po ON
CONTA pe.marca=po.marca
CONTA Angajat
Iat6 i rezultatul - figura 6.51. 5148000
AND TO_CHAR(data,'MM/YYYY')=*07/2003'
CONTA Angajat 7 2460000
ORDER BY 1, 2
CONTA { Subtotal - compart CONTA--- 9908000
IT Angajat 1 COMPART NUMEPREN 1*032000 NR ORE L
Celor trei tipuri de nregistrri le corespund trei fraze SELECT,
IT Angajat 3 2700000
conectate prin operatorul UNION. Clauza ORDER BY se plaseaz dup
CONTA
IT Angajat 5 1*500000
IT ultimul SELECT,
CONTA
Primul Angajat Nou coloanele fiind indicate prin poziia (numrul) lor.
1332000
IT Pentru a
< Subtotal asigura ordonarea
CONTA
- compart IT------ corespunztoare,
12561*000 s-a recurs la
PROD Al caracterul
Doilea Angajat IT
ce areNoucodul ASCII, imediat superior lui z, adic 123.
1212000
PROD Rezultatul
Angajat i* IT
este cel din figura 6.52. 5400000
PROD Angajat 8 IT 3921*000
PROD IT
{ Subtotal - compart PROD---- 10536000
PROD
< ------ < TOTAL General------ !
== 33008000
PROD
PROD

Figura 6.51. Orele lucrate de fiecare angajat pe luna iulie 2003

S se afieze venitul de baz corespunztor orelor lucrate de


fiecare angajat pe luna iulie
2003, calculndu-se subtotaluri pe compartimente, precum i un
total general.
Practic, rezultatul conine trei tipuri de nregistrri:
pe nt ru fi e c are ang a jat , d at e le s unt ob inut e ca n int e rog a re a
ant e rio a r, prin g rup a re a d up at rib ut e le Co mp art i
N umep re n;
pe nt ru fi e c are co mp art ime nt func i a SUM es t e id e nt ic , ns
g rup a re a s e re alize az numa i d up im at rib ut - Co mp a rt ;
to t al ul g e ne ral p re s up une ap l ica re a f unc ie i SUM f r grup a re .

Iat int e rog a re a:

SEL ECT co mp a rt , nume p re n,


AN D TO_CH AR( d at a,' MM / YYY Y' )
=' 07 /2 0 03 ' GROUP BY co mp a rt , nume p re n
198 Interogri SQL
Oracle. Ghidul dezvoltrii aplicaiilor profesionale 199
FROM p e rso n al p e L EF T OUTER JOIN p o nt a j e po
Din produsul cartezian de mai sus se extrag numai liniile care, n
ON p e .marc a= po .m arc a AN D TO_CH AR( d at a,' MM / YY YY' ) = ' 07 /2 00 3'
aGROUP
doua instan
BY nume pPERSONAL-PONTAJE,
re n privesc Primul Angajat Nou, i
apoi se face o grupare dup 18 marca i numele3 primei instane i
102 Ongajat 2 marca celei de-a doua instane.12 Clauza HAVING asigur 3 extragerea n
UENIT BAZA MAX
103 Ongajat 3 rezultat numai a grupurilor (angajailor)
13 3
pentru care numrul zilelor
104 Ongajat 4 de pontaj este mai mare dect cel 18 al Primului Angajat 3 Nou.
105 Ongajat 5 5406000
18 3
SEL ECT po l .ma rca, pe l. nume p re n,
106 Ongajat 6 Figura 18 funcii agregat 3 n alta
107 Ongajat 7 COON T 6.53. Includerea
( DISTIN unei
CT p o l. d at a) AS Z ile _L uc rat e
12 3,
108 Ongajat 8 COUN T ( DISTIN CT po 2 .d at a) AS
18 3
Z ile _L uc rat e _ PAN FROM (p o nt aje p o l IN N ER JOIN
n pe
cers o
zile din
nal p iulie
e l ON au fost
p o l.mar ca= pprezeni
e l.ma rca) ,la lucru mai mult de 8
angajai? (p o nt aje p o2 INN ER JOIN p e rso n al p e2 ON
po 2 .marc a= p e2 .ma rca)
Condiia
WH ERE(8p oangajai la elucru)
l. o re lu crat > 0 ANnu
D se
p o2poate aplica
. o re lucr at e la nivel
> 0 AN D de linie,
ci la nivel de grup, grup constituit la nivelul unei zile prin
pe 2 .nume p re n= ' Primul Ang ajat No u'
GROUP angajailor
numrarea BY p o l.marc a, cup e l.nume
ore p re n, n
lucrate p o2 .mar ca
data respectiv. Pentru
H AVIN G COUN T (DISTIN C T po l. d at a) > COUN T ( DISTIN CT po 2.d at a)
acest gen de probleme, a fost creat clauza HAVING:
Atributele afiate (vezi figura 6.56) sunt: marca, numele, numrul
SEL ECT d at a, COUN T ( *) AS
zilelor lucrate de angajatul de pe linia (grupul) respectiv i numrul
N r_Pe rs FROM p o nt aje
zilelor
WH ERElucrate
TO_CH ARde (d
persoana
at a, 'M M/etalon.
YY YY' ) = ' 07 /2 00 3' AN D o re lucr at e
> 0 GROUP BY d at a H AVIN G COUN
SQL> SELECT pol.marca, pel.numepren, T ( * ) > 8
2 COUNT(DISTINCT
rezultatul pol.data)
fiind cel din OS Zile Lucrate,
figura 6.54.
3 G0UNT(DISTINCT po2.data) OS Zile_Lucrate_PON
4 FROM (pontaje DATA pol INNERNR PERS
JOIN personal pel ON
pol,marca=pe1.marca),
5 (pontaje po2 INNER9- JUL-03
JOIN personal pe2 9 ON po2.marca=pe2.marca)
6 WHERE pol.orelucrate
10- >JUL-03
0 OND po2.orelucrate
9 > 0 OND
7 pe2.numepren - 11- PrimulJUL-03
Ongajat Nou* 9
8 GROUP BV pol.marca, pel.numepren, po2.marca
Figura 6.54.
9 HOUING COUNT(DISTINCT Clauza
pol.data) > HAVING
COUNT(DISTINCT po2.data)
10 /
Care sunt angajaii cu un numr de zile lucrate peste cel al
Primului
MORCO Angajat
NUMEPRENNou? ZILE_LUCR0TE ZILE_LUCROTE_PflN
Ideea soluiei care urmeaz ine de efectuarea produsului
cartezian a dou instane ale cuplului PERSONAL-PONTAJE
(joncionate intern, selectndu-se totui numai zilele pentru care
OreLucrate > 0). Rezultatul acestui produs cartezian este
impresionant - 17689 de linii - vezi figura 6.55.
SQL> SELECT C0UNT(*)
2 FROM (pontaje Figura
pol6.52. Subtotaluri
INNER i total general personal
J01N pe 0N
pol.marca=pe1.marca),
3 (pontaje
Care po2 mare
este cel mai INNER venit JOIN
de baz personal
pe luna pe2 0N po2.narca-
iulie 2003 ?
pe2.narea) |
n WHERE
4 Oraclepol.orelucrate
se poate include > 0 ANDfuncia SUM n >
po2.orelucrate MAX,
0 aa nct
interogarea
17689 urmtoare este funcional (vezi figura 6.53):

Figura
SELECT 6.55. (orelucrate
MAX (SUM Numrul de linii ale produsului
* salorar) cartezian
) AS Venit Baza MAX
200 Interogri SQL

SEL E CT d at a AS Ziu a
FROM po nt aj e p o IN N ER JOIN pe rs o nal p e ON p o .marc a =
p e .marc a
WH ERE nume p re n IN ( ' Ang aj a i' , ' Pri mul Ang a j at N o u' )
GROUP BY Dat a H AV IN G COUN T ( *) = 2

6.8. Subconsultri. Operatorul IN


Nucleul SQL din Oracle este unul deosebit de generos i n privina
subconsultrilor i, cnd spunem acest lucru, ne gndim n primul
rnd la numrul aproape nelimitat de niveluri pe care pot fi incluse
frazele SELECT. Majoritatea interogrilor incluse fac apel la
operatorul IN.

Care sunt colegii de compartiment ai lui Angajat 2 ?


Dac n paragraful dedicat jonciunii interne am apelat la
artificiul joncionrii a dou instane ale tabelei PERSONAL dup
atributul compart i filtrarea liniilor pentru una din instane
(numepren = 'Angajat 2'), lucrurile pot fi simplificate recurgnd la o
subconsultare:
SEL E CT nume p re n
FROM pe rs o nal
WH ERE nume p re n <> ' Ang aj at 2 f AN D co mp a rt IN ( SEL EC T
co mp art FROM p e rs o nal
WH ERE nume p re n = ' Ang aj at 2 ' )
Mai nti, se execut subconsultarea, obinndu-se un rezultat
intermediar ce conine o singur linie i o singur coloan -
compartimentul Angajatului 2. n pasul al doilea se execut SELECT-
ul principal care extrage din PERSONAL liniile n care NumePren este
diferit de cel al angajatului etalon, iar valoarea atributului Compart
este una din rezultatul intermediar. .

Care sunt zilele n care au lucrat simultan Angajat 1 i Primul


Angajat Nou ?
Celor trei soluii bazate pe jonciune, intersecie i grupare le
adugm o alta care folosete o subconsultare:
SEL E CT d at a AS Ziu a
FROM po nt aj e p o IN N ER JOIN p e rs o nal pe ON p o .marc a = pe .ma rc a
WH ERE nume p re n = ' Ang aj at 1 ' AN D d at a IN ( SEL ECT d at a
FROMFigura
po6.56.
nt Persoanele
a j e p o cu
INmai multe
N ER zile lucrate
JOIN pe rsdect
o nalPrimul Angajat Nou Care
p e ON p o.ma rc a = p e .mar ca WH ER E
sunt zilele n care au lucrat simultan Angajat 1 i Primul
nume p re n = ' Primu l Ang aj at No u' )
Angajat Nou?
Constituim
Interesant esteuncgrup pentru fiecare
subconsultarea zi lucrtoare,
poate extrgnd
substitui de multe ori numai
liniile referitoare
jonciunea. la unulcudintre
Astfel, echivalent cei doi
fraza SELECT angajai.
de mai sus, seDatele
poate care
intereseaz corespund grupurilor ce conin dou linii:
scrie:
Oracle. Ghidul dezvoltrii aplicaiilor profesionale 201

SEL E CT d at a AS Ziu a FROM p o nt a j e WH ERE mar ca


IN
( SEL EC T mar ca FROM pe rs o nal
WH ERE nume p re n = ' Ang aj at 1 '
)
AN D d at a IN
( SEL EC T d at a
FROM po nt a j e
WH ERE mar ca IN
( SEL EC T mar ca FROM
p e rso na l
WH ERE nume p re n = ' Prim ul Ang a jat N o u'
))

Care sunt zilele din iulie 2003 n care a lucrat Angajat 1, dar NU a
lucrat Primul Angajat Nou ?

Dac varianta precedent de rezolvare a acestei probleme fcea


apel la operatorul diferen (EXCEPT/MINUS), folosind o
subconsultare, lucrurile stau aproape identic interogrii de mai sus,
numai c IN se nlocuiete cu NOT IN:
SEL E CT d at a AS Ziu a
FROM po nt a j e po IN N ER JOIN pe rs o nal p e ON p o .
ma rc a = p e . marc a WH ERE nume p re n = ' Ang aj at 1 '
AN D TO_CH AR (d at a, MM / YYYY' ) = 0 7/ 20 03 '
AN D d at a NOT IN
( SEL EC T d at a
FROM po nt a j e po IN N ER JOIN personal
pe ON po .ma rca = pe.ma rc a WHERE nume p re n
= 'Primul Ang aj at No u' )

Care este (sunt) angajatul (angajaii) cu cel mi mare salariu


orar?

Una dintre greelile cele mai frecvente ale nceptorilor n SQL


este folosirea unei soluii de genul celei din figura 6.57, n care
clauza SELECT conine numele angajatului i funcia MAX.

SQL> SELECT numepren, MflX(salorar)


2 FROM personal
3 /
SELECT numepren, MAX(salorar)
*
ERROR at line 1:
ORA-00937: not a single-group group function

Figura 6.57. Tentativ euat de aflare a angajatului cel mai bine pltit
202 Interogri SQL

Varianta corect presupune utilizarea funciei intr-o


subconsultare. Informaia furnizat este corect, dup cum reiese
din figura 6.58.
SEL ECT nume p re n,
s alo rar FROM p e rso na l
WH ERE s alo r ar IN
(SEL E CT M AX ( s alo rar)
FROM p e rso n al)

NUMEPREN SftLORAR
Angajat H 75000

Figura 6.58. Angajatul care are cel mai mare salariu orar
Care sunt angajaii cu cele mai mari dou salarii orare?

Trei fraze SELECT incluse de maniera urmtoare rezolv problema:


SEL ECT nume p re n, s alo rar
FROM p e rso n al
WH ERE s alo r ar > =
(SEL E CT M AX ( s alo rar)
FROM p e rso n al
WH ERE s alo r ar <
(SEL E CT M AX ( s alo rar)
FROM p e rso n al ) )

Mai greu este cu explicatul. De aceea, figura 6.59 conine cele trei etape
ale execuiei. SELECT-ul cel mai de jos" extrage cel mai mare salariu orar, n
timp ce SELECT-ul intermediar determin penultimul salariu orar.

Fraza principal ndeplinete o simpl formalitate, extrgnd toi


angajaii cu salariul mai mare sau egal cu penultima valoare
furnizat de subconsultarea median.
204 Oracle. Ghidul dezvoltrii aplicaiilor profesionale Interogri SQL 203

Care sunt angajaii


SQL>cuSELECT
un numr de zile lucrate peste cel al
MAX(salorar)
Primului Angajat Nou?
2 FROM personal
3 /
Prin grupare, fiecrei persoane i se numr zilele de lucru.
Clauza HAVING asigur extragerea numai a acelor grupuri la care
MAX(SALORAR)
numrul zilelor este mai mare dect al angajatului etalon, numr
ZILEJ-UCRATE
calculat printr-o subconsultare:
75000
101 Angajat1 18
SEL ECT po .mar ca, nume p re n, CO UN T (DIST IN CT d at a)
102 Angajat2
AS Z ile _L ucratSQL>
e SELECT MAX(salorar) 12
103FROM
Angajat3
po nt a j e 2p oFROM personal
INN ER 13 .mar ca= p e
JOIN p e rs o na l p e ON p o
104 Angajat4
.mar ca 3 WHERE salorar < 18
105WHAngajat5
ERE o re luc rat e 4> 0
(SELECT MAX(salorar) 18
106GROUP
Angajat6
BY p o.m arc5a, FROM
numepersonal
p re n 18
)
107H AVIN
Angajat7
G COUN T (DISTIN
12
108 Angajat8 6 / C T d at a) > 18
(SEL E CT COUN T (DISTIN CT d at a)
8 rows FROM
selected.
p o nt aje p o IN N MAX(SALORAR)
ER JOIN pe rs o nal p e ON p o .ma rca= p e .mar ca
WH ERE o re luc rat e > 0 AN D nume p re n = ' Primul Ang aj at No u' )
SQL>
Figura 6.60 ilustreaz modul de derulare al interogrii.
71500

SQL> SELECT COUNT(DISTINCT data)nunepren, salorar


SQL> SELECT
2 FROM pontaje po INNER
2 FROM personal JOIN personal pe ON
po.marca=pe.marca
3 WHERE salorar >=
3 UHERE orelucrate > 0 AND numepren = 'Primul Angajat Nou'
4 (SELECT MAX(salorar)
3 5 FROM personal
6 WHERE
SQL> SELECT po.marca, salorar
numepren, <
COUNT(DISTINCT data) AS
ZileLucrate 7 (SELECT MAX(salorar)
2 FROM 8 FROM
pontaje po personal
INNER ) JOIN ) personal pe ON
po.marca=pe.marca 9 /
3 UHERE orelucrate > 0
4 GROUP BV po.marca, numepren
NUMEPREN SALORAR
5 HAUING COUNT(DISTINCT data) >
6 (SELECT COUNT(DISTINCT data)
7 FROM Angajat
pontaje po 4 INNER JOIN 75000 pe
personal ON
po.marca=pe.marca Angajat 6 71500
8 UHERE orelucrate > 0 AND numepren = 'Primul Angajat Nou'
SQL>
Figura 6.59. Angajaii cu cele mai mari dou salarii

6.9. Subconsultri n clauza HAVING.


Operatorii ALL, SOME, ANY
Posibilitatea folosirii subconsultrilor ca termeni ai clauzei HAVING este un
mare atu n rezolvarea unor probleme informaionale cu un grad de dificultate
ceva mai pronunat. Predicatele clauzei conin, pe lng clasicii operatori de
comparaie, i trei ceva mai speciali, ALL, SOME i ANY.
Oracle. Ghidul dezvoltrii aplicaiilor profesionale 205

Care dintre angajai a fost la lucru n toate zilele lucrtoare?

Lucrurile nu sunt att de complicate cum par la prima vedere.


Avem nevoie de o subconsultare care s calculeze numrul zilelor
lucrtoare. Fraza SELECT principal va calcula numrul zilelor lucrate
de fiecare angajat pe care l va compara cu rezultatul subconsultrii
- vezi figura 6.61.

SEL ECT po .mar ca, nume p re n, CO UN T(d at a) AS Z ile _L uc rat e


FROM p o nt aje p o IN N ER JOIN pe rs o nal p e ON p o .ma rca= p e .mar ca
WH ERE o re luc rat e > 0
GROUP BY p o.m arc a, nume p re n
H AVIN G COUN T (d at a) -
(SEL E CT COUN T (DISTIN CT d at a)
FROM p o nt aje WH ERE
o re lucr at e > 0 )

SQL> SELECT COUNT(DISTINCT data)


2 FROM pontaje
3 WHERE orelucrate > 8 *i /

COUNT(DISTINCTDATA)

18

SQL> SELECT po.marca, numepren, COUNT(data) AS Zile_Lucrate


2 FROM pontaje po INNER JOIN personal pe ON
po.marca=pe.marca
3 WHERE orelucrate > 8
4 GROUP BY po.marca, numepren
5 HAUING COUNT(data) =
6 (SELECT COUNT(DISTINCT data)
7 FROM pontaje
8 WHERE orelucrate > 8 )
9 /

MARCA NUMEPREN ZILE LUCRATE


181 Angajat1 18
184 Angajat 4 18
185 Angajat 5 18
186 Angajat 6 18
188 Angajat8 18

Figura 6.61. Persoanele prezente la munc n toate zilele lucrtoare

Figura 6.60. Persoanele cu mai multe zile lucrate dect Primul Angajat Nou - varianta 2
206 Interogri SQL

Care este angajatul (sunt angajaii) cu cel mai mare venit


(obinut din orele lucrate, plus eventualele concedii de odihn)?

Ne gndim la o subconsultare care s calculeze veniturile de baz


pentru fiecare angajat, subconsultare pe care s o folosim ca
element de comparaie ntr-un SELECT principal ce grupeaz
veniturile pe angajai. Zis i fcut:

SEL E CT p o.m arc a, nume p re n,


SUM (o re luc rat e * s alo r ar + o re co * s alo rar co)
AS Ve nit _B aza
FROM po nt a je p o IN N ER JOIN p e rs o nal pe ON p o .marc a= pe .ma rc a
GROUP BYp o .ma rca, nume p re n
H AV IN G SUM ( o re lucr at e * s alo rar + o re co * s alo ra rco )
> = AL L
( SEL EC T SUM ( o re lucr at e * s alo ra r + o re co * s alo r arco )
FROM po nt a je p o IN N ER JOIN p e rs o nal pe ON
p o .marc a= pe .m arc a GROUP BY p o .marc a)

Dup cum se observ i n figura 6.62, subconsultarea extrage


zece linii (cte una pentru fiecare angajat) i o singur coloan -
venitul de baz. Spre deosebire de interogrile precedente, pentru
funcionarea corespunztoare a clauzei HAVING este necesar
folosirea operatorului ALL, astfel nct rezultatul va conine numai
linia/liniile cu valori mai mare sau egale tuturor valorilor furnizate
de subconsultare.

Prezena operatorului ALL este indispensabil, deoarece


rezultatul subconsult- rii este multi-linie. n lipsa acestuia, mesajul
de eroare este cel din figura 6.63.
Oracle. Ghidul dezvoltrii aplicaiilor profesionale 207

SQL> SELECT SUM (orelucrate * salorar oreco * salorarco)


2 FROM pontaje po INNER JOIN personal pe ON po.narca=pe.narea
3 GROUP BV po.narea
4 /
SUM(0RELUCRATE*SAL0RAR+0REC0*SAL0RARC0)

8064000
8208000
9660000
1080000
0
9000000
10296
000
8784000
7848000
1332000
10 rows selected.
SQL> SELECT po.narca, numepren,
2 SUM (orelucrate * salorar + oreco * salorarco) AS UenitBaza
3 FROM pontaje po INNER JOIN personal pe ON po.narca=pe.marca
4 GROUP BV po.narca, nunepren
5 HAUING SUM (orelucrate * salorar + oreco * salorarco) >= ALL
6 (SELECT SUM (orelucrate * salorar + oreco * salorarco)
7 FROM pontaje po INNER JOIN personal pe ON po.narca=pe.narca
8 GROUP BV po.narca)
9 /
MARCA NUMEPREN UENIT BAZA

104 Angajat 4 1 08 00000

SQL>
Figura 6.62. Persoana cu venitul cel mai mare
MARCANUMEPREN COMPA UENIT_BAZA

103Angajat 3 IT 9660000
104Angajat 4 PROD 10800000
105Angajat 5 IT 9000000
Oracle. Ghidul dezvoltrii aplicaiilor profesionale 209
208 Interogri SQL
(SEL E CT M IN (SUM (o re luc rat e * salorar +
SQL> SELECT po.marca,
o re co numepren,
* s alo r arco ) )
2 SUM (orelucrate
FROM p o* ntsalorar
aj e po IN +Noreco
ER JOIN* pe
salorarco)
rso n al p e RS
ON UenitBaza
3 FROM pontaje
po .mapo
rca=INNER JOIN WH
p e . marca personal pe art
ERE co mp ON = po.marca=pe.marca
' CON TA'
4 GROUP BV GROUP
po.narea,
BY pnumepren
o.m are a)
5 HAUING SUM (orelucrate * salorar + oreco * salorarco) >==
6 (SELECT SUM (orelucrate
SQL> SELECT SUM (orelucrate * salorar + oreco
* salorar * salorarco)
+ oreco * salorarco)
7 FROM
2 FROM pontaje po INNER JOIN personal pe po.marca=pe.marca
pontaje po INNER JOIN personal pe ON ON po.marca=pe.marca
8 GROUP BV po.marca)
3 WHERE compart = aCONTAa
9 / 4 GROUP BV po.marea
(SELECT
5 / SUM (orelucrate * salorar + oreco * salorarco)
*
ERRORSUM(0RELUCRATE*SAL0RAR+0REC0*SAL0RARC
at line 6:
ORA-01427: single-row subquery returns more 0) than one row
Figura 6.63. Clauz HAVING incorect n condiiile unei subconsultri multi-linie
82 08 000 10296000 8784000

SQL>
Ce SELECT po.marea,
persoane au venitul numepren, compart,mcar unui angajat al
de baz superior
2 SUM (orelucrate * salorar + oreco * salorarco) AS Uenit_Baza
compartimentului
3 FROM pontajeContabilitate?
po INNER JOIN personal pe ON po.marca=pe.marca
4 WHERE compart <> aCONTAa
De data aceasta,
5 GROUP pentru
BV po.marea, ca un angajat
numepren, comparts fie inclus n rezultat,
venitul su trebuie
6 HAUING s fie superior
SUM (orelucrate sau egal
* salorar mcar* cu
+ oreco al unuia dintre
salorarco) >= ANY
oamenii muncii
7 (SELECT SUM de la contabilitate,
(orelucrate * salorar ceea+ orecoce *reclam folsirea
salorarco)
8 FROM pontaje
operatorului ANY: po INNER JOIN personal pe ON po.marca=pe.narca
9 WHERE compart = CONTA*
10 GROUP
SEL BV. mar
ECT po po.marea)
ca, nume p re n, co mp art ,
11 / SUM ( o re lucr at e * s alo ra r + o re co * s alo ra rco )
AS Ve n it _Baz a
FROM po nt a j e p o INN ER JOIN pe rs o nal pe ON p o .mar ca= p e
.mar ca
WH ERE co mp art < > ' CON TA'
GROUP BY p o .marc a, nume p re n, co mp art
H AVIN G SUM (o re luc rat e * s alo r ar + o re co * s alo rar co) > = AN Y
(SEL E CT SUM (o re luc rat e * s alo r ar + o re co * s alo rar co)
FROM p o nt aj e po INN ER JOIN p e rso na l pe ON
po .ma rca= p e .mar ca WH ERE co mp art - ' CON TA'
GROUP BY p o .marc a)

Lucrurile ar decurge identic i dac locul operatorului ANY ar fi


luat de un altul nrudit - SOME. Cum la contabilitate sunt trei
angajai, subconsultarea se va materializa n trei valori (linii) - vezi
figura 6.64 - din care cea minim este 8 208 000. Cele trei persoane
extrase n rezultatul final au mcar veniturile de 8 208 000 lei, aa
c se poat^ formula o variant i fr operatorul ANY:

SEL ECT po .mar ca, nume p re n, co mp art ,


SUM ( o re lucr at e * s alo ra r + o re co * s alo ra rco )
AS Ve n it _Baz a
FROM p o nt aje po IN N ER JOIN pe rs o nal p e ON p o .marc a= pe .m arc a
WH ERE co mp art < > ' CON TA'
GROUP BY p o .marc a, nume p re n, co mp art
212 Interogri SQL avansate

SQL> ZILE1 SQL> SQL> 2ILE2 SQL>


SELECT data SELECT data
2 FROM pontaje po INNER JOIN personal pe

Capitolul 7
Interogri SQL avansate
Dac precedentul capitol a fost unul de introducere n
mecanismul de interogare al bazelor de date folosind nucleul SQL al
Oracle, n continuare zbovim pre de cteva pagini pentru cteva
delicatese specifice, n general, serverelor de baze de date de
categorie grea. Astfel, vom parcurge: subconsultri declarate n
clauza FROM, interogri simplu i dublu corelate, subconsultri
a ON po.narea
scalare,
pe.Furca
expresii tabel, 3funcii analitice i interogri ierarhice.
ON po.narca - pe.narca
H WHERE nunepren 'Angajat 1* k WHERE nunepren * 'Primul Angajat Nou'
5/ S/

DATA
7.1. Subconsultri
DATA
n clauza FROM
61 -JUL-63 09-JUL-83
Sun paradoxal din partea unor autodeclarai veterani SQL", dar
02-JUL-03 18JUL-03
83-JUL-83 multe din soluiile altminteri 11-JUL-03 interesante se pierd n SQL din pricina
M-JUL-03
07- JUL-63 acestei faciliti care e att de confortabil nct uneori mbie la o
08-JUL-83
89-JUL-03
oarecare lene SQL-ist". Noroc c unele SGBD-uri nu o au
18-JUL-83 implementat... Lsnd gluma la o parte, trebuie recunoscut c i
11-JUL-03 SQL> SELECT 2ILE1.data AS Ziua
81-AUG-63 problemele2 FROHcele mai sngeroase" i pot afla naul n
04-AUG-03 3 (SELECT data
07-AUG-03 subconsultrile definite
FR0H pontaje n clauza
po INNER JOIN personal pe FROM. r
08-AUG-03 5 ON po.narca pe.narca
61-SEP-03 6 WHERE nunepren - 'Angajat 1'} ZILE1 II
02-SEP-83 Care sunt
1 zilele n care au lucrat simultan Angajat 1 i Primul
INNER JOIN
63-SEP-03
80-SEP-83
Angajat Nou?
9
8 (SELECT data
FR0H pontaje po IFttiLR J0IN personal pe
08-SEP-03 Probabil
10 c cele patru soluii din capitolul precedent nu sunt
ON pe.narea - pe.narca
11 WHERE nunepren - 'Primul Angajat Nou') ZILE2
18 rows selected. suficiente,
12 aa c formulm una care s valorifice subconsultri
0N ZILE1 .data *= Z1LE2 .data
13 /
definite n clauza FROM:
ZIUA
SEL ECT ZIL EI. d at a AS Figura
Z iua6.64. Operatorul ANY
89-JUL-63
FROM18-JUL-63
(SEL
11-JUL E
-83CT d at a
FROM p o nt a j e po INN ER JOIN p e rso na l
pe ON po .mar ca = pe .m arc a WH ERE
nume p re n = ' Ang aj at 1 ' ) ZIL EI IN N ER
JOIN
(SEL E CT d at a
FROM p o nt a j e po INN ER JOIN p e rso na l
pe ON po .mar ca = pe .m arc a
WH ERE nume p re n = ' Primu l Ang aj at No u' )
ZIL E2 ON Z IL EI.d at a = Z IL E2 .d at a
Prima subconsultare se materializeaz printr-o tabel temporar
ad-hoc numit ZILEI ce conine zilele lucrate de primul dintre
Oracle. Ghidul dezvoltrii aplicaiilor profesionale 213

Care sunt angajaii cu numrul de zile lucrate peste cel al Primului


Angajat Nou?
In clauza FROM, definim dou subconsultri, ZILEJTOTI ce conine
mrcile, numele i numrul zilelor lucrate de fiecare angajat, i
ZILE_A1, a crei singur linie (i coloan) conine numrul zilelor de
lucru pentru Primul Angajat Nou. Cele dou, s Ie zicem, tabele ad-
hoc sunt joncionate dup condiia
Z IL E_TOTI.Z ile _L uc rat e > ZIL E_A1 .Z ile _L ucr at e :

SEL E CT ma rca, nume p re n, Z IL E_TO TI.Z ile _L ucr at e ,


Z IL E_A1 .Z ile _L ucrat e AS Zile _A l FROM
( SEL EC T po .ma rca, nume p re n, COUN T( d at a) AS
Z ile _L ucr at e FROM p o nt aj e po INN ER JOIN p e rso na l p e ON
p o .marc a= pe .m arc a WH ERE o re lu crat e > 0
GROUP BY po .mar ca, numep re n) Z IL E_TOTI,
( SEL EC T COUN T ( d at a) AS Z ile _L ucrat e FROM p ont a j e p o IN N ER
JOIN p e rs o nal pe ON po .mar ca= p e .marc a
WH ERE o re lucr at e > 0 AN D numep re n = ' Prim ul Ang a jat N o u'
GROUP BY po .mar ca, numep re n) Z IL E_A1
WH ERE ZIL E_TO TI.Z ile _L ucr at e > Z IL E_A1 .Z ile _L uc rat e

Care este angajatul (sunt angajaii) cu cel mai mare venit


(obinut din orele lucrate, plus eventualele concedii de odihn) ?
Definim dou subconsultri, una care grupeaz veniturile
obinute de angajai i o alta care determin venitul de baz
maxim;
Figuran
7.1.fraza a doucele
SELECT,
Joncionarea dou definite
subconsultri se compar dup cum urmeaz:
n clauza FROM
CareSELsunt
E CTorele
* lucrate de fiecare angajat n lunile iulie i august
2003, att
FROM pe luni, ct i nsumat?
n clauza( SEL EC Tvom
FROM po .mar ca,cte
defini numep re n, SUM ( o re lucr
o subconsultare at e * fiecare
pentru s alo ra r +
o re co * s alo ra rco ) AS Ve nit _ Baz a FROM po nt a je p o IN N ER JOIN
lun, iar apoi le vom jonciona extern cu tabela PERSONAL:
p e rso na l pe ON po .mar ca= p e ,mar ca
GROUP BYp o .ma rca, nume p re n) V EN ITURI1 INN ER JOIN
( SEL EC T M AX (SUM (o re lu crat e * s alo r
SEL E CT p .mar ca, nume p re n, N VL ( Ore _L ucr_Iu l, 0) ar + o re co * s alo rar co) )
AS AS
Ve nit _B aza_M ax
Ore _Iulie , N VL ( Ore _L ucr_Aug ,0 ) AS Ore _Aug , N VL ( Ore _L uc r_Iul,0 )
FROM
+ N VL( po nt _L
Ore a uc
j er_Aug
p o IN N ER JOIN pe rs o nal p e ON p o.m arc a=p e .ma rc a
,0)
GROUP BYAS po "Ore
.mar_L ca) VEN I TURI2
ucr_Iul- Aug "
ON VEN ITURI1 . Ve nit _B
FROM pe rs o nal p L EFT OUTER JOIN aza= VEN ITURI2 . Ve nit _B aza_M AX
( SEL EC T mar ca, SUM (o re lu crat e ) AS Ore _L uc r_Iul
Care
FROMsuntpo ntangajaii
aje prezeni la lucru mcar n zilele n care a fost Angajat
3? WH ERE TO_CH AR( d at a, 'M M/ YYY Y' ) = '0 7/ 20 03 '
GROUP la
Simpl BYformulare,
M arca) IULproblema
IE ridic destule probleme, deoarece
ON p.m arc a = IUL IE.ma rca L EFT OUTER JOIN
nu e vorba de un numr, ci de un set de date. Pentru a ndeplini
( SEL EC T mar ca, SUM (o re lu crat e ) AS
condiia, setul
Ore _L ucr_ Aug de FROM zilepode lucru ale fiecrui angajat trebuie s
nt aje
conin
WH ERE setul
TO_CHzilelor
AR( Angajatului
d at a, ' MM / YYY3.Y')
Soluia
= '0 8/pe care
20 03 ' v-o prezentm ia
n
GROUPcalculBY o zi pentru un angajat oarecare numai dac n data
M arca)
respectiv
AUG UST ON p. Angajat
ma rca 3 = a fost i el la lucru:
AUG UST . mar ca ORDER BY
ma rc a
Oracle. Ghidul dezvoltrii aplicaiilor profesionale 215
214 Interogri SQL avansate

SEL E CT ma rca, nume p re n, Z IL E_G EN .Z ile _L uc rat e ,


Z IL E_A3 .Z ile _L ucrat e AS Zile _A3
FROM
{SEL E CT p o .marc a, nume p re n, COUN T (d at a) AS
Z ile _L ucr at e FROM p o nt aje po IN N ER JOIN pe rso n al p e ON
p o .marc a= pe .m arc a WH ERE o re lu crat e > 0 AN D d at a IN

MARCA NUMEPREN (SEL E CT d at a FROM p o nt aje


ZILELUCRATE ZILE_A3
Figura 7.3. Numrul de zile n care rca
WH ERE o re luc rat e > 0 AN D ma IN angajat a lucrat simultan cu
fiecare
101 Angajat 1 13
Angajat 3 (SEL E CT m arc a FROM pe rs o nal 13
103 Angajat 3 WH ERE
Singurul lucru rmasnume p re n 13
nefcut = ' Ang
este ajat
13 3' ) din rezultat a nsui
eliminarea
104 Angajat 4 13 13
105 Angajatangajatului-
5 -reper,
) dar aceasta13 e deja floare13 la ureche.
106 Angajat 6 GROUP BY p o.m arc a, nume 13p re n) 13
108 Angajat 8 C a r e e s t eZILan g a
E_GEN
j a t u l c u n
13u m r u l de zile lucrate imediat
13
( SEL EC T COUN T ( d at a) AS Z,ile _L ucrat e
p e s t e c e l a l A n g a j a t u l u i 7? Interogarea urmtoare ne permite s
FROM po nt a j e p o IN N ER JOIN pe rs o nal p e
ON potestm
.ma rca=niveluri
p e .mar decasubconsultare n clauza FROM, cu att mai interesant
cu ct
WH ERE o recentrul
lucr at e > de0 interes
AN D numepse situeaz
re n = 'n
Angclauza HAVING a SELECT-ului
aj at 3'
GROUPprincipal:
BY po .mar ca) Z IL E_A3
WH ERE ZIL E_GEN .Z ile _L ucr at e = ZIL E_A3 .Z ile _L ucr at e
SELECT po.marca, numepren, COUNT (data) AS Zile_Lucrate FROM
ZILE_GEN
ponta jare
e poconinutul
INNER JOINdin figurape7.2
personal ONiponumr
.marca=pe cte sunt zilele
. marca
WHERE numepren <> 'Angajat 1' AND orelucrate
n care angajatul de pe linia respectiv a fost lucru n acelai > 0 GROUP BYtimp
po.marca, numepren HAVING COUNT (data) - (
cu Angajat 3, fapt pentru care s-a folosit o nlnuire de
SELECT MIN(Zile_Lucrate)
subconsultri.FROM
NUMEPREN ZILE_LUCRATE
SQL> -- ZILE_GEN (SELECT ZILE_L_TOTI. Zile_Lucrate FROM
103Angajat 3 13(SELECT
SQL> SELECT po.marca, numepren, po.marca,
COUNT(data) numepren, COUNT (data)
OS Zile_Lucrate
2 FROM pontaje po INNER JOIN personal AS pe ON po.marca-pe.marca
Zile_Lucrate
3 WHERE orelucrate > 0 OND dataFROM IN ponta j e po INNER JOIN personal pe
4 (SELECT data FROH pontaje ON WHERE orelucrate > 0 AND WHERE
po.marca=pe.marca marca INnumepren
5 (SELECT marca FROM personal WHERE numepren = Angajat 3) )
<> 'Angajat 1 '
6 GROUP BV po.marca, numepren
7 / AND orelucrate > 0
GROUP BY po.marca,
MARCA NUMEPREN numepren ) ZILE_L_TOTI,
ZILE LUCRATE
(SELECT COUNT (data) AS Zile_Lucrate FROM
101 Angajat 1pontaje po INNER JOIN personal pe13ON
102 Angajat 2po.marca=pe.marca 7
103 Angajat 3WHERE orelucrate > 0 AND numepren 13 = 'Angajat 7'
104 Angajat GROUP BY po.marca) ZILE_A7 13
4 13
WHERE ZILE_L_TOTI.Zile_Lucrate > ZILE_A7.Zile_Lucrate
105 Angajat 13
)
5 7
106 )
Angajat 13
6
Figura 7.2. Numrul de zile n care fiecare angajat a lucrat simultan cu
Angajat 3
ZILE_A3 conine numrul zilelor de lucru ale Angajatului 3 (13),
iar fraza SELECT principal extrage prin condiia ZILE GEN. Zile
Lucrate = ZILE A3. Zile Lucrate toi angajaii pentru care numrul
zilelor lucrate simultan cu Angajat 3 este 13 - vezi figura 7.3.
216 Interogri SQL avansate

Care sunt cele mai mari dou salarii orare?


La aceast interogare se poate formula una dintre cele mai
simple soluii, folosind o subconsultare i pseudo-coloana ROWNUM.

SELECT salorar
FROM
(SELECT DISTINCT salorar
FROM personal ORDER BY
salorar DESC )
WHERE ROWNUM <= 2

SQL> SELECT DISTINCT salorar


2 FROM personal
3 ORDER BY salorar DESC SQL> SELECT salorar
4 / 2 FROM
3 (SELECT DISTINCT salorar
SALORAR 4 FROM personal
5 ORDER BY salorar DESC
7500 6 )
0 * 7 WHERE ROWNUM <= 2
7150 8 /
0
SALORAR
6750
0
6250 75000
0 71500
6150
0
5750
Figura 7.5. Primele dou salarii orare - soluie bazat pe ROWNUM i
subconsultare
Avantajul acestei soluii ine de generalitatea ei. Astfel, dac ne-
ar interesa Pr i m i i c i n c i c l a s a i n t o p u l a n g a j a i l o r c u c e l e
m a i m a r i v e n i t u r i , nu ar trebui s umblm prea mult la logica
SELECT *
FROM
(SELECT po.marca, numepren, SUM i orelucrate * salorar +
oreco * salorarco) AS Venit_Baza FROMpontaje po INNER JOIN
personal pe ON po.marca=pe.marca GROUP BY po.marca,
numepren ORDER BY 3 DESC)
WHERE ROWNUM <= 5

Figura 7.4. Angajat 3 este cel care are numrul de zile lucrate imediat
peste cel al
Angajatului 7
Oracle. Ghidul dezvoltrii aplicaiilor profesionale 217

MARCA NUMEPREN UENIT BAZA

104 Angajat 4 10800000


106 Angajat 6 10296000
103 Angajat 3 9660000
105 Angajat 5 9000000
107 Angajat 7 8784000

Figura 7.6. Primele cinci poziii din topul celor mai bine pltii angajai

7.2. Interogri corelate. Operatorul EXISTS


Interogrile corelate reprezint una dintre cele mai greu de deprins
faciliti ale SQL-ului. Detalii semnificative despre corelarea simpl
i dubl sunt prezentate n lucrarea unuia dintre autorii crii de
fa, lucrare pe care ne tot strduim s nu o eclipsm, aa c vom
discuta sumar doar cteva exemple.

Care sunt colegii de compartiment ai lui Angajat 2?


Tot o subconsultare constituie miezul soluiei, ns una special -
corelat:

SELECT *
FROM personal pel
WHERE numepren <> 'Angajat 2' AND EXISTS (SELECT marca
FROM personal pe2 WHERE numepren = 'Angajat 2'
AND pe2 . compart = pel. compart )

Pentru a include o linie din PE1 n rezultat trebuie ca, pentru


aceasta, s existe n PE2 cel puin o linie n care numele s fie
'Angajat 2 ' , iar compartimentul s fie identic cu cel al liniei curente
din PE1. Ceva mai rar, corelarea se realizeaz i prin operatorul IN:

SELECT *
FROM personal pel
WHERE numepren <> 'Angajat 2' AND compart IN (SELECT compart
FROM personal pe2 WHERE numepren = 'Angajat 2'
AND pe2.compart = pel.compart )

Care sunt zilele n care au lucrat simultan Angajat 1 i Primul


Angajat Nou?
Condiia este: zilele n care a lucrat primul angajat-reper s fie
aceleai ca i zilele n care a venit la lucru al doilea, aa nct
corelarea se realizeaz dup atributul Data. Pentru simplificare,
subconsultarea extrage doar valoarea (constanta) 1:
218 Interogri SQL avansate

SELECT data AS Ziua


FROM pontaj e pol INNER JOIN personal pel ON pol.marca = pel.marca
WHERE numepren = 'Angajat 1' AND EXISTS (SELECT 1
FROM pontaj e po2 INNER JOIN personal pe2
ON po2.marca = pe2.marca WHERE
numepren = 'Primul Angajat Nou'
AND po2 . data = pol. data)

Care sunt angajaii care, n total, au exact 12 zile de lucru?


Ar fi prea simplu s recurgem la:

SELECT po.marca, numepren, COUNT (data) AS Zile_Lucrate


FROM pontaje po INNER JOIN personal pe ON po.marea=pe.marca
WHERE orelucrate > 0
GROUP BY po.marca, numepren
HAVING COUNT (data) = 12

Aa c o s ne complicm cu o soluie care ar merita totui un premiu de


frumusee:
SELECT marca, numepren FROM personal WHERE 12 =
(SELECT COUNT (data)
FROM pontaj e
WHERE orelucrate > 0 AND
pontaje.marca = personal.marca)

Care dintre angajai a fost la lucru n toate zilele lucrtoare?


Subconsultarea corelat conine o clauz HAVING, n care se calculeaz
numrul zilelor lucrtoare, numr comparat cu cel al datelor lucrate de
angajatul de pe linia
curent din PE:

SELECT marca, numepren FROM personal pe WHERE EXISTS (SELECT 1


FROM pontaj e po
WHERE orelucrate > 0 AND po.marca = pe.marca
GROUP BY marca HAVING COUNT (data) =
(SELECT COUNT (DISTINCT data)
FROM pontaje WHERE
orelucrate > 0 )
)

Care sunt angajaii cu cele mai mari trei salarii orare?


Tot la categoria delicatese SQL ncadrm i varianta urmtoare:
Oracle. Ghidul dezvoltrii aplicaiilor profesionale 219

SELECT *
FROM personal pel
WHERE 3 >
(SELECT COUNT (DISTINCT salorar)
FROM personal p e 2
WHERE pe2 . salorar > pel. salorar)
ORDERBY salorar DESC

Scenariul este urmtorul: se parcurge, linie cu linie, prima


instan a tabelei PERSONAL - PE1. Orice linie i este inclus n
rezultat numai dac rezultatul subconsultrii corelate numr n a
doua instan PERSONAL - PE2 mai puin de 3 linii pentru care
salariul orar este mai mare dect cel de pe linia curent din PE1.
Logica este un pic curioas: dac pentru o linie dat sunt mai puin
de trei nregistrri n care salariul orar este peste cel din linia dat,
nseamn c linia respectiv se nscrie n primele trei.

Extragei primii cinci clasai n topul angajailor cu cele mai mari


venituri.
Prin comparaie cu problema precedent, elementul suplimentar
de dificultate ine de corelarea la nivel de grup, i nu linie:

SELECT pol .marca, numepren, SUM (pol.orelucrate *


pel.salorar + pol.oreco * pel.salorarco) AS Venit_Baza FROM
ponta j e pol INNER JOIN personal pel ON pol.marca=pel.marca
GROUP BY pol.marca, numepren HAVING 5 >
(SELECT COUNT (SUM (po2 . orelucrate * pe2 . salorar +
po2.oreco * pe2.salorarco))
FROM ponta je po2 INNER JOIN personal pe2 ON
po2.marca=pe2.marca GROUP BY po2.marca
HAVING SUM (po2.orelucrate * pe2.salorar + po2.oreco *
pe2.salorarco) >
SUM (pol.orelucrate * pel.salorar +
pol.oreco * pel.salorarco)
)
ORDERBY 3 DESC

Care dintre angajai a fost la lucru n toate zilele lucrtoare?


Revenim la aceast problem, ncercnd, de data aceasta, o
soluie care s valorifice d u b l a c o r e l a r e :

SELECT DISTINCT pol .marca, numepren


FROM personal pel INNER JOIN pontaje pol
ON pel,marca=pol.marca WHERE orelucrate
> 0 AND NOT EXISTS (SELECT 1 FROM pontai
e po2
220 Interogri SQL avansate

WHERE orelucrate > 0 AND NOT EXISTS (SELECT 1


FROM pontaje po3 INNER JOIN personal pe3 ON
po3.marca=pe3.marca WHERE orelucrate > 0
AND.pe3 .marca=pel .marca AJD po3 . data-poZ.
data)
)

Care sunt angajaii prezeni la lucru mcar n zilele n


care a fost Angajat 3? Iat un al doilea exemplu de
dubl corelare:

SELECT DISTINCT pel .marca, numepren FROM personal pel


INNER JOIN ponta j e pol ON pel.marca = pol.marca WHERE
orelucrate > 0 AND NOT EXISTS (SELECT 1
FROM personal pe2 INNER JOIN pontaje po2 ON
pe2.marca=po2.marca
WHERE orelucrate > 0 AND numepren = 'Angajat 3' .
AND NOT EXISTS
(SELECT
1
FROM personal pe3 INNER JOIN pontaje po3
ON pe3.marca=po3.marca WHERE orelucrate
> 0
AND pe3. marca=pel
.jnaroa AND op3. dat
a=po2. aata

Credem c aceste ultime dou interogri constituie nn foarte


nimerit promo l a cartea de SQL de care pomeneam...

7.3. Subconsultri scalare n clauza SELECT


O subconsultare scalar este cea care furnizeaz o igur valoare
(o sigur linie/coloan). Definiia sun ct se poate de simplu, ns
Oracle abia n versiunea 9 a introdus aceast facilitate spumoas
(urmnd exemplul standardelor SQL i caprei" DB2 a vecinului
IBM).
Care este totalul venitului de baz pentru fiecare angajat?
Putem ncerca o variant n care clauza SELECT conine o
subconsultare scalar ce returneaz venitul pentru angajatul de pe
linia curent. Interogarea scalar este corelat prin atributul Marc
de liniile din PERSONAL (PE):
SELECT marca, numepren,
(SELECT SUM (pol.orelucrate * pel.salorar +
pol.oreco * pel.salorarco)
FROM ponta j e pol INNER JOIN personal pel ON
Oracle. Ghidul dezvoltrii aplicaiilor profesionale 223

WHERE pe.marca=pel.marea) AS Venit_Baza


FROM personal pe ORDER BY numepren

Bazndu-ne pe corelare, putem renuna la jonciunea intern din


subconsultarea scalar:

SELECT marca, numepren,


(SELECT SUM (po.orelucrate * pe.salorar +
po.oreco* pe.salorarco)
FROM pontaj e po
WHERE po. marca-pe . marca) AS Venit_Baza
FROM personal pe ORDER BY numepren

S se calculeze, la nivelul firmei, urmtoarele date:


total ore lucrate;
total ore concediu;
total ore noapte;
total venit de baza.

Rezultatul va conine o singur linie - vezi figura 7.7. Fiecare dat


cerut va fi furnizat de o subconsultare scalar. Deoarece nu avem
o tabel principal", folosim surogatul" DUAL.

SELECT
(SELECT SUM (orelucrate) FROMpontaje)
AS Total_Ore_Lucrate,
(SELECT SUM (oreco) FROMpontaje) AS Total_Ore_Concediu,
(SELECT SUM (orenoapte) FROMpontaje) AS Total_Ore_Noapte,
(SELECT SUM (po.orelucrate * pe.salorar + po.oreco *
pe.salorarco)
FROM pontai e po INNER JOIN personal pe
ON po.marca=pe.marca) AS Total_Venit_Baza
FROM DUAL

SQL> SELECT
2 (SELECT SUM (orelucrate) FROM pontaje) AS Total_Ore_Lucrate,
3 (SELECT SUM (oreco) FROM pontaje) AS Total_Ore_Concediu,
4 (SELECT SUM (orenoapte) FROM pontaje) AS Total_Ore_Noapte,
5 (SELECT SUM (po.orelucrate * pe.salorar + po.oreco * pe.salorarco)
6 FROM pontaje po INNER JOIN personal pe
7 ON po.narca=pe.marca) AS Total_Uenit_Baza
8 FROM DUAL
9 /
TOTAL ORE LUCRATE TOTAL ORE CONCEDIU TOTAL ORE NOAPTE TOTAL UENIT BAZA

1064 136 14 75204000

Figura 7.7. Informaii sintetice obinute cu interogri


scalare
222 Interogri SQL avansate

Care sunt zilele n care au lucrat simultan Angajat 1 i Primul Angajat


Nou?
Declarm dou interogri scalare n clauza SELECT, una
referitoare la zilele lucrate de primul angajat, iar cealalt, similar,
privitoare la cel de-al doilea angajat. Corelarea se realizeaz cu
liniile tabelei PONTAJE (fiecare zi de lucru):

SELECT
(SELECT data
FROM ponta je po INNER JOIN personal
pe ON po.marca = pe.marca WHERE
numepren = 'Angajat 1'
AND po.data=p oO.data) ZILEI,
(SELECT data
FROM ponta j e po INNER JOIN personal pe ON po.marca = pe.marca
WHERE numepren = 'Primul Angajat Nou'
AND po. data=poQ. data ) ZILE2
FROM ponta je poO WHERE zilel=zile2

Intenia noastr este, de fapt, s testm dac rezultatele a dou


interogri corelate n clauza SELECT pot fi folosite i n clauza
WHERE. Ei, bine, nu se poate - vezi figura 7.8.

SQL> SELECT (SELECT data


2 FROM pontaje po INNER JOIN personal pe ON po.narea = pe.narea
3 WHERE nunepren - Angajat 1 ANO po.data-po0.data) ZILE1,
4 (SELECT data
5 FROM pontaje po INNER JOIN personal pe ON po.narea - pe.narea
6 WHERE numepren - Primul Angajat Nou AND po.data-poO.data) ZILE2
7 FROM pontaje poB
8 WHERE zile1=zile2
9 /
WHERE zile1=zile2 *
ERROR at line 8:
ORA-00904: "ZILE2": invalid identifier

Figura 7.8. Atributele obinute prin interogri scalare nu pot fi folosite n clauza
WHERE

Varianta ctigtoare se obine copiind subconsultrile n clauza WHERE,


unde vor fi comparate:

SELECT DISTINCT
(SELECT data
FROM pontaje po INNER JOIN personal
pe ON po .marca = pe .marca WHERE
numepren = 'Angajat 1'
AND po.data=poO.data) ZILEI,
224 Oracle. Ghidul dezvoltrii aplicaiilor profesionale Interogri SQL avansate223
DATA NR ANGAJATIT0TAL PREZENI PR0CENT_PREZENT A
FROM(SELECT data
01-JUL-03 10 8 80
FROM ponta
(SELECT + j e po INNER JOIN personal pe ON po.marca =
02-JUL-03 pe.marca
FROM pontaWHERE
16 numepren 6= 'Primul Angajat Nou'
je 60
03-JUL-03 AND po.
WHERE TO^CHAR(10 data,'MM/YYYY')
data=poO. data)
6 ZILE2 FROM pont a j e poO WHERE
=' 07/2003') 60
P_IULIE
GROUP BY (SELECT
data data
FROM ponta j e po INNER JOIN personal pe ON po.marca =
pe.marca
Rezultatul este cel din figura 7.9.
WHERE numepren = 'Angajat 1' AND po. data=poO. data) =
(SELECT data
FROM ponta j e po INNER JOIN personal pe
ON po.marca = pe.marca WHERE
numepren = 'Primul Angajat Nou'
AND po.data=poO.data)

Soluia pare totui prea brutal, aa c o mai ndulcim printr-o


subconsultare n clauza FROM, ce filtreaz din PONTAJE numai zilele
referitoare la primul angajat, iar singura subconsultare scalar este
mutat n clauza WHERE:

SELECT data FROM


(SELECT data
FROM ponta je po INNER JOIN personal pe ON po. marca =
pe. marca WHERE numepren = 'Angajat 1'
) poO
WHERE data =
(SELECT data
FROM ponta j e po INNER JOIN personal pe ON po. marca =
pe.marca WHERE numepren = 'Primul Angajat Nou'
AND po.data=poO.data)

Care este procentul de prezen la lucru n fiecare zi din luna iulie


2003?
Pentru fiecare zi lucrtoare din iulie 2003, ne intereseaz raportul
dintre numrul angajailor prezeni la lucru i numrul total de
angajai ai firmei, aa nct recurgem la dou subconsultri scalare,
pe care le mprim:

SELECT data,
(SELECT COUNT (*) FROM personal) AS Nr_Angajati_Total,
(SELECT COUNT ( * ) FROM pont a j e po WHERE orelucrate
>0 AND po. data = p_iulie. data) AS Prezeni,
( (SELECT COUNT (*) FROM ponta j e po WHERE orelucrate
>0 AND po.data = p_iulie.data) /
(SELECT COUNT (*) FROM personal) ) * 100 AS Procent
Prezenta
Oracle. Ghidul dezvoltrii aplicaiilor profesionale 225
A.

01I-JUL- 10 6 60
03
07-JUL-03 10 6 60
08-JUL-03 10 7 70
09-JUL-03 10 9 90
10-JUL-03 10 9 90
11-JUL-03 10 9 90

Figura 7.10. Procentul fiecrui angajat din totalul veniturilor de baz

Care este evoluia zilnic a prezenei n iulie 2003, prin raportare


la ziua calendaristic anterioar?
Cheia soluiei ine de corelarea celor dou subconsultri scalare la
data de pe linia curent din P_IULIE:

SELECT data,
(SELECT COUNT (*) FROM pontaje po WHERE orelucrate
Figura 7.9. Procentul de prezen
>0 AND po . pentru
datafiecare zi lucrtoare
= p_iulie din iulie 2003
. data)
AS Prezenti_Zi_Crt,
S se calculeze
(SELECT parteaCOUNT (*) fiecrui
FROM angajat
ponta j edin totalul orelucrate
po WHERE veniturilor de baz.
>0 AND po . data = p_iulie. data - 1)
Dup calapodul exemplului precedent, folosim dou
AS Prezenti_Zi_Anter,
subconsultri scalare, una care calculeaz totalul general al
(SELECT COUNT (*) FROM pontaj e po WHERE orelucrate >0
veniturilor AND de po. baz
data i o alta
= p_iulie. data)pentru
- (SELECT determinarea
COUNT (*} FROM venitului
angajatuluiponta de pe j e linia curent
po WHERE a tabelei
orelucrate >0 AND PERSONAL
po. data (rezultatul
= p_iulie . se
prezint ca n figura 7.10):
data - 1)
AS Diferena
SELECTFROMmarea, numepren,
(SELECT
(SELECTSUM*(orelucrate
FROM ponta * salorar
j e + oreco * salorareo)
FROM pontaTO_CHAR(data,'MM/YYYY
WHERE j e po INNER JOIN personal r
) ='pe ON
07/2003') P_IULIE
GROUP BY po.marca=pe.marea)
data Total_Venituri,
(SELECT SUM (orelucrate * salorar + oreco * salorareo)
AS Venit_Baza
FROM ponta jeTOTAL po INNERUENJOIN
ITURI UEN I TAN
personal peGAJ
ON PROCEN
AT T
1 09 Prim ul Ang a jat Npo.marca=pe.marca
ou 7 52 04 00 0 13 32 00 0 1.7 7
WHERE pe .marca = personal .marca ) VenitAnga j at,
1 10 Al Do ile a Ang aj at No u ( (SELECT
ROUND 7 52 04
SUM00 (orelucrate
0 12 12 00 0
* salorar + 1.6 1 *
oreco
1 01 Ang aj at 1 7 52 04 00 0 80 64 00 0 1 0.7 2
salorareo) ASVenit_Baza FROM ponta j e po INNER
1 02 Ang aj at 2 7 52 04 00 0 82 08 00 0 1 0.9 1
JOIN personal pe ON po.marca=pe.marca WHERE
1 03 Ang aj at 3 7 52 04 00 0 96 60 00 0 1 2.8 5
1 04 Ang aj at 4 pe .marca = personal 7 52 04 00.marca
0 ) / 00 00 0
1 08 1 4.3 6
1 05 Ang aj at 5 7 (SELECT
52 04 00 0SUM (orelucrate
90 00 00 0 * salorar
1 1.9 7+
1 06 Ang aj at 6 7 52 04 00oreco
0 1*02 salorareo)
96 00 0 1 3.6 9
1 07 Ang aj at 7 7 FROM
52 04 00ponta
0 j e
87po 84INNER
00 0 JOIN personal
1 1.6 8
1 08 Ang aj at 8 7 52 04 00pe0 ON po.marca=pe.marca)
78 48 00 0 1 0.4 4 * 100, 2)
DATA PREZENTI_ZI_CRT PREZENTI_ZI_ANTER AS Procent DIFERENA
01-JUL-03 FROM personal 8 0 8
02-JUL-03 6 8 -2
03-JUL-03 6 6 0
04-JUL-03 6 6 0
07-JUL-03 6 0 6
08-JUL-03 7 6 1
09-JUL-03 9 7 2
10-JUL-03 9 9 0
11-JUL-03 9 9 0
DATA PREZENTI_ZI_CRT PREZENTI_P0NTAJ_ANTER DIFERENTA
226 Interogri SQL avansate
01-JUL-03 8 0 8
02-JUL-03 Pentru prima 6zi din iulie, atributul Prezenti
8 -2 are valoarea
Zi Anter
03-JUL-03 zero, 6 6 0
04-JUL-03 deoarece nu intereseaz
6 eventualele 6pontaje de pe 0 iunie - vezi
07-JUL-03 figura 6 7.11. 6 0 Situaia
08-JUL-03 7 de 7 iulie, deoarece6ziua precedent,
este similar zilei 1 6 iulie, a
09-JUL-03 fost 9 o 7
duminic 2 (zi
10-JUL-03 9
mai nelucrtoare dect celelalte). 9 0
11-JUL-03 Problema este9 mult mai interesant dect
9 0
precedenta, deoarece
raportarea se
face la ziua calendaristic anterioar, dar numai dac aceasta a
fost lucrtoare. De
aceea, a doua subconsultare scalar apeleaz la o subconsultare
SELECT data,
(SELECT COUNT {*) FROM pontaj e po WHERE orelucrate >0
AND po. data = p_iulie . data) AS Prezenti_Zi_Crt,
(SELECT COUNT (*) FROM pont a j e po WHERE orelucrate >0
AND po. data = (SELECT MAX (data) FROM pontaje po2
WHERE orelucrate > 0
AND po2 . data < p_iulie. data)
) AS Prezenti_Pontaj_Anter,
(SELECT COUNT (* ) FROM pontaj e po WHERE orelucrate >0
AND po. data = p_iulie. data) -
(SELECT COUNT (*) FROM pontaje po WHERE orelucrate >0
ANDpo.data= (SELECT MAX (data) FROM pontaj e po2
WHERE orelucrate > 0
AND po2 . data < p_iulie . data) ) AS Diferenta
FROM
(SELECT * FROM pontaje
WHERE TO_CHAR(data,'MM/YYYY')='07/2003') P_IULIE
GROUP BY data

Figura 7.11. Comparaie zi curent - precedent n privina prezenei


Oracle. Ghidul dezvoltrii aplicaiilor profesionale 227

7.4. Expresii tabel


Expresiile tabel constituie o alt facilitate SQL introdus n Oracle 9i, prin care o tabel poate fi definit
ad-hoc nainte de clauza SELECT. Principalul atu este posibilitatea de a folosi atributele sale n clauza
WHERE.

Care sunt angajaii cu venitul de baz total mai mare de 8


milioane lei?
Prin clauza WITH declarm tabela VENITURI ce calculeaz venitul
de baz al fiecrui angajat, iar n clauza WHERE apare o condiie
formulat asupra unui atribut din aceast tabel:

WITH venituri AS
(SELECT po.marca, numepren, SUM (orelucrate * salorar +
oreco * salorarco) AS Venit_Baza FROM ponta je po INNER
JOIN personal pe ON po.marca=pe.marca GROUP BY po.marca,
numepren)
SELECT *
FROM venituri
WHERE venit baza >= 8,000000
Care este angajatul (sunt angajaii) cu cel mai mare venit
(obinut din orele lucrate, plus eventualele concedii de odihn)?
Ciudat, dac dorim s joncionm dou instane ale tabelei ad-
hoc VENITURI, obinem un mesaj de eroare de genul celui din figura
7.13, pe care nu ni l-am putut explica:
WITH venituri AS
(SELECT numepren, SUM (orelucrate * salorar +
oreco * salorarco) AS Venit_Baza FROM pontaj e
po INNER JOIN personal pe ON po.marca=pe.marca
GROUP BY numepren)
SELECT vl. *
FROM venituri vl INNER JOIN
(SELECT MAX (venit_baza) AS venit_baza FROM venituri) vraax
ON vl.venit_baza = vmax.venit_baza

SQL> WITH uenituri AS


2 (SELECT numepren, SUM (orelucrate * salorar oreco * salorarco) AS Uenit_Baza
3 FROM pontaje po INNER JOIN personal pe ON po.marca*pe.marca
4 GROUP BV numepren)
5 SELECT u1.*
6 FROM venituri v1 INNER JOIN
7 (SELECT MAX(ueni'tbaza) AS venit_baza FROM uenituri) vmax
8 0N u1.uenit_baza - vmax.venit_baza
9 /
(SELECT numepren, SUM (orelucrate * salorar + oreco * salorarco) AS Uenit_Baza
*
ERROR at line 2:
Figura 7.12. Comparaie
ORA-086OU: zi curent
error occurred - zi lucrtoare
at recursive SQLprecedent
level 1 n privina prezenei
ORA-80984: ,from$_subquery$_003"."NUMEPREN_7_7": invalid identifier
Dup aceste exemple n care subconsultrile scalare i-au artat
virtuile, nu ne
mai rmne dect s regretm c nu le putem include nici n
Figura 7.13. Ciudenii Oracle - episodul 1
clauzele DE FAULT ale
atributelor, nici n reguli de validare (CHECK) la nivel de
228 Interogri SQL avansate

Remediul vine de la o alt tabel ad-hoc, VMAX, ce conine


numai venitul de baz maxim la nivelul firmei - vezi figura 7.14:

WITH venituri AS
(SELECT numepren, SUM (orelucrate *
salorar+ oreco * salorarco) AS Venit_Baza
FROM ponta j e p o INNER JOIN personal pe
ON po.marca=pe.marca GROUP B Y numepren),
vmax AS
(SELECT MAX (SUM (orelucrate *
salorar + oreco * salorarco)) AS
Venit_Max FROM ponta j e po INNER
JOIN personal pe ON
po.marca=pe.marca GROUP BY numepren)
SELECT numepren, venit_baza
FROM venituri INNER JOIN vmax ON venit_baza = venit_max
SQL> WITH
2 venituri AS
3 (SELECT nunepren, SUM (orelucrate * salorar + oreco * salorarco) AS Uenit_Baza
4 FROM pontaje po INNER JOIN personal pe ON po.marca-pe.narea
5 GROUP BV nunepren),
6 vnax AS
7 (SELECT MAX(SUN (orelucrate salorar + oreco * salorarco)) AS Uenit_Max
8 FROM pontaje po INNER JOIN personal pe ON po.marca-pe.narea
9 GROUP BV nunepren)
1 0 SELECT nunepren, uenit_baza
11 FROM venituri INNER JOIN vnax ON uenit_baza - venit max
12 /

NUNEPREN UENIT BAZA

Angajat k 18800000

Figura 7.14. Dou tabele definite n clauza WITH


Care sunt angajaii cu un numr de zile lucrate peste
c e l a l Pr i m u l u i A n g a j a t N o u ? Ideea ar fi s definim o tabel
ad-hoc ZILE ce conine numrul zilelor n care a fost la lucru fiecare
angajat:

WITH zile AS
(SELECT po .marca, numepren, COUNT (data) AS Zile_Lucrate FROM
ponta j e po INNER JOIN personal pe ON po.marca=pe.marca WHERE
orelucrate > 0 GROUP BYpo.marca, numepren)
SELECT *
FROM zile
WHERE zile_lucrate >
(SELECT zile_lucrate FROM zile
WHERE numepren = 'Primul Angajat Nou' )
Oracle. Ghidul dezvoltrii aplicaiilor profesionale 229

Din pcate, Oracle ne trateaz cu acelai mesaj nltor - vezi


figura 7.15. Ei,
bine, dac n subconsultare se folosete o alt tabel ad-hoc,
scpm de mesajul de
eroare:

WITH zile AS
(SELECT po .marca, numepren, COUNT(data) AS ZiIe_Lucrate
FROM ponta je po INNER JOIN personal pe
ON po.marca=pe.marca
WHERE orelucrate > 0
GROUP BY po.marca, numepren) ,
Zilei AS
(SELECT COUNT (data) AS Zile_Lucrate
FROM pontaj e po INNER JOIN personal pe
ON po.marca=pe.marca
WHERE orelucrate > 0 AND numepren = ' Primul Anga j at Nou' )
SELECT * FROM zile WHERE zile^lucrate >
(SELECT zile_lucrate FROM zilei)

SQL> WITH zile OS


2 (SELECT po.narea, nunepren, COUNT(data) OS ZileLucrate
3 FROM pontaje po INNER JOIN personal pe ON po.narca=pe.marca
4 WHERE orelucrate > 0
5 GROUP BV po.marca, numepren)
6 SELECT *
7 FROM zile
8 WHERE zilelucrate >
9 (SELECT zile_lucrate
10 FROM zile
11 WHERE numepren = Primul Ongajat Nou*)
12 /
(SELECT po.marca, numepren, COUNT(data) OS ZileLucrate
*
ERROR at line 2:
ORO-0Q6Q4: error occurred at recursive SQL level 1
QR0-OO9O4: *from$_subquery$_003* .NUMEPREN_7_7*: invalid
identifier

7.5.
/
Funcii OLAP
De la versiunea 8i, din care au fost introduse aa-numitele funcii
analitice, este din
ce n ce mai greu de inventariat tot ceea ce ofer Oracle n materie
de SQL dedicat
procesrii analitice on-line (On Line Analytical Processing). Fiecare
nou variant
vine cu exotismul su n materie de funcii din aceast categorie.
COMPART NUMEPREN UENIT_BAZA

CONTA Angajat 2 2300000


CONTA Angajat 6 5148000
CONTA Angajat 7 2460000
230 t Interogri SQL avansate
CONTA 9908000
IT Angajat 1 4032000
IT 7.5.1. Subtotaluri
Angajat 3 2700000
IT Angajat 5 4500000
IT Reamintim o problem
Primul Angajat Nou care, la momentul
1332000formulrii, nu era chiar din
IT cale-afar de simpl: 12564000
PROD Al Doilea Angajat Nou 1212000
PROD S se afieze
Angajat 4 venitul de baz corespunztor
5400000 orelor lucrate de
PROD fiecare angajat
Angajat 8 pe luna iulie 2003, calculndu-se
3924000 i subtotaluri pe
PROD compartimente, precum i un total10536000
general.
Paragraful 6.7 este cel n care am lansat problema subtotalurilor
33008000
pe compartimente i totalului general pentru orele lucrate.
Interogarea al crei rezultat era reprezentat n figura 6.52 avea
nevoie de trei fraze SELECT conectate prin operatorul UNION. Cu
funcia analitic ROLLUP, lucrurile se simplific vizibil:

SELECT compart, numepren, SUM(orelucrate * salorar)


AS Venit_Baza
FROM personal pe LEFT OUTER JOIN ponta je po ON pe.marca=po.marca
AND TO_CHAR(data,'MM/YYYY')=' 07/2003'
GROUP BY ROLLUP(compart, numepren)
ORDER BY compart, numepren

Cum funcia ROLLUP are dou argumente, vor fi calculate dou


(sub)totaluri. Ceea ce putem reproa rezultatului din figura 7.16
s u n t spaiile n spatele crora ghicim subtotalurile i totalul
general. De fapt, spaiile afiate n SQL*Plus sunt valori NULL.
Oracle. Ghidul dezvoltrii aplicaiilor profesionale 231

SELECT
CASE
WHEN compart IS NULL THEN READ (CHR(123) , 8, ' =' )
ELSE compart END AS compart,
CASE
WHEN compart IS NULL THEN RPAD(CHR( 123) i |
' TOTAL General 32, ' = ')
WHEN numepren IS NULL THEN RPAD{CHR( 123) | |
'Subtotal - compart ' | | c o m p a r t , 3 2 , ' - ' )
ELSE numepren END AS numepren,
SUM(orelucrate * salorar) AS Venit_Baza FROM
personal pe LEFT OUTER JOIN pontaje po
ON pe.marca=po.marca AND TO_CHAR(data, ' M M / Y Y Y Y ' ) = ' 0 7 / 2 0 0 3 '
GROUP BY ROLLUP(compart, numepren)
ORDER BY compart, numepren

7.5.2. Clauzele ROLLUP i GROUPING


Funcia GROUPING poate fi inclus n clauza SELECT, argumentul
acesteia fiind coloana de grupare. Rezultatul ntors este 1 atunci
cnd coloana respectiv este inclus ntr-un grup de agregare
superior sau 0 pentru liniile normale" (din afara subtotalurilor).
Pentru a complica un pic lucrurile, dorim ca venitul de baz s fie
calculat pe angajai, compartimente, luni calendaristice i pe total
firm.
Testarea NULLitii atributelor de grupare este nlocuit cu
verificarea valorii retumate de funcia GROUPING:
SELECT
CASE
WHEN GROUPING (EXTRACT (MONTH FROM data) ) = 1 THEN RPAD(CHR(
123) , 4,'=')
ELSE CAST (EXTRACT (MONTH FROM data) AS CHAR (4) )
END AS Luna,
CASE
WHEN GROUPING (compart) =1
THEN RPAD(CHR( 1 2 3 ) , 8 , ' = ' )
ELSE compart END AS compart,
CASE
WHEN GROUPING (EXTRACT (MONTH FROM data) ) = 1
THEN RPAD(CHR( 1 2 3 ) || ' TOTAL General ', 37, ' = ')
WHEN GROUPING (compart) =1
THEN RPAD(CHR( 1 2 3 ) || ' SUBTOTAL - LUNA ' ||
Figura 7.16.
EXTRACT (MONTHROLLUP - primul
FROM d a texemplu
a ) , 3 7 , )
WHEN GROUPING (numepren) -1
Aa nct
THEN prin
R PA D dou
( C H R ( 1secvene CASE - compart
2 3 ) || ' subtotal ameliorm' || afiajul",
aducndu-1 la standardul
c o m p a r t ,figurii
3 7 , ' - '6.52:
)
ELSE numepren END AS numepren,
SUM(orelucrate * salorar) AS Venit Baza
I NUHEPREN UENITBAZA
A
7 81 Doilea Angajat Nou 1212006

234 Interogri SQL avansate


232 Interogri SQL avansate

FROM personal pe LEFT OUTER JOIN ponta j


e po ON pe.marca=po.marca
GROUP BY ROLLUP(EXTRACT (MONTH FROM data) , compart,
numepren) ORDER BY EXTFACT (MONTH FROM data) , compart,
numepren

LUNA COMPART NUMEPREN UENITBAZA


7 CONTA Angajat 2 2300000
7 CONTA Angajat 6 5148000
7 CONTA Angajat 7 2460000
7 CONTA { subtotal - compart CONTA----- 9908000
7 IT Angajat 1 4032000
7 IT Angajat 3 2700OOO
7 IT Angajat 5 4 50 00 00
7 IT Primul Angajat Nou 1332000
7 IT < subtotal - compart IT 12564000
7 PROD Al Doilea Angajat Nou 1212000
7 PROD Angajat 4 540000O
7 PROD Angajat 8 3924800
7 PROD { subtotal - compart PROD------- 10536000
7 {======= { SUBTOTAL - LUNA 7------------------- 33OO8O0O
8 CONTA Angajat 2 920000
8 CONTA Angajat 6 2288000
8 CONTA Angajat 7 984000
8 CONTA < subtotal - compart CONTA----- 4192000
8 IT Angajat 1 1792000
8 IT Angajat 3 162OO0O
8 IT Angajat 5 200O000
8 IT { subtotal - compart IT 5412000
8 PROD Angajat 4 24OO0OO
8 PROD Angajat 8 1744000
8 PROD < subtotal - compartPROD 4144O0O
8 {======= { SUBTOTAL - LUNA 8------------------- 13748000
9 CONTA Angajat 2 230OO00
9 CONTA Angajat 6 286OO00
9 CONTA Angajat 7 246OOO0
9 CONTA < subtotal - compart CONTA----- 762OO0O
9 IT Angajat 1 224OO0O
9 IT Angajat 3 27000OO
9 IT Angajat 5 25OOO00
9 IT < subtotal - compart IT 744OO00
9 PROD Angajat 4 3 00 00 00
9 PROD Angajat 8 2180000
9 PROD < subtotal - compartPROD 5180000
9 <======= { SUBTOTAL - LUNA 9------------------- 20240000
{=== {======= { TOTAL General ===================== 66996000

Figura 7,17. Trei niveluri de (sub)totalizare

Din scanarea" figurii 7.17, deducem c lucrurile par


a fi n regul.
7 Angajat 1 4032000
7 Angajat 2 2300000
7 Angajat 3 2700000
7 Angajat 4 5400000
7 Angajat 5 4500000
7 Angajat 6 5148000
7 Angajat 7 2460000
7 Angajat 8 3924O00
7 Primul Angajat Nou 1332000
7 { - - Subtotal luna - - - 7 33008000
8 Angajat 1 17920O0
8 Angajat 2 9200O0
8 Angajat 3 1620000
8 Angajat 4 2400000
8 Angajat 5 2000000
8 Angajat 6 2288000
8 Angajat 7 984000
8 Angajat 8 1744O0O
8 < Subtotal luna 8 13748000
9 Angajat 1 2240000
9 Angajat 2 2300000
9 Angajat 3 2700000
9 Angajat 4 3000000
9 Angajat 5 2500000
9 Angajat 6 2860000
9 Angajat 7 2460000
9 Angajat 8 2180000
9 {- - Subtotal luna - - - 9 20240000
{ * Subtotal * Al Doilea Angajat Nou 1212000
{ * Subtotal * Angajat 1 8064000
{ * Subtotal * Angajat 2 5520000
< * Subtotal * Angajat 3 702000O
< * Subtotal * Angajat 4 10800000
{ * Subtotal * Angajat 5 9000000
{ * Subtotal * Angajat 6 10296000
{ * Subtotal * Angajat 7 5904000
< * Subtotal * Angajat 8 7848000
< * Subtotal * Primul Angajat Nou 1332000
{TOTAL GENER A L 66996000
236 Oracle. Ghidul dezvoltrii aplicaiilor profesionale Interogri SQL avansate
235

CUBE. Dac ns am fi dorit o analiz mai fin, dup trei sau mai
multe criterii, complexitatea rezultatului ar fi crescut simitor.
Atunci cnd se dorete excluderea rndurilor de detaliu" din
rezultat sau a unora dintre subtotaluri, se poate folosi clauza
GROUPING SETS:

SELECT
EXTRACT (MONTH FROM data) AS Luna,
CASE GROUPING (numepren)
WHEN 1 THEN
CASE GROUPING (EXTRACT (MONTH FROM data) )
WHEN 1
THEN CHR ( 1 2 3 ) | |
' T O TA L G E N E R A L '
ELSE CHR ( 1 2 3 ) || '-----Subtotal luna---------'
I | EXTRACT (MONTH FROM data)
END
ELSE
CASE GROUPING (EXTRACT (MONTH FROM d a t a ) )
WHEN 1
THEN CHR ( 1 2 3 ) || ' * Subtotal *' | |
numepren ELSE numepren
END
END AS Numepren,
SUM(orelucrate * salorar) AS Venit_Baza
FROM personal pe LEFT OUTER JOIN pontaj e po
ON pe.marca=po.marca
GROUP BY GROUPING SETS (EXTRACT (MONTH FROM data) , numepren )
ORDER BY EXTRACT (MONTH FROM data) , numepren

Dup cum se observ n figura 7.19, rezultatul conine numai 13


linii, trei pentru c pontajele au fost introduse pentru iulie, august
i septembrie 2003, plus 10, cte una pentru fiecare angajat. Dac
am fi dorit s obinem i o a 14-a linie dedicat totalului general, ar
fi trebuit s modificm argumen lele clauzei GROUPING SETS astfel:

SELECT
GROUP BY GROUPING SETS (EXTRACT (MONTH FROM
data) , numepren, () )
ORDER BY. . .

LUNANUMEPREN UENIT_BAZA

7<- - luna----7 33008000

Subtotal Figura 7.18. Un CUBE
8<- - luna----8 13748000
9<-

Clauza GROUPING
Subtotal
- luna----9 se poate folosi dup20240000
aceeai logic expus la
< * exemplul dedicat
Subtotal 81 Doileaoperatorului
Angajat Nou ROLLUP. Pentru a pstra o
1212000
< * dimensiune
Subtotal rezonabil
* Angajat 1 a rezultatului (40 de linii), interogarea
8064000
< * folosete doar
Subtotal dou atribute
* Angajat 2 n clauza GROUP
5520000
BY
< * Subtotal * Angajat 3 7020000
< * Subtotal * Angajat 4 10800000
Oracle. Ghidul dezvoltrii aplicaiilor profesionale 237
{ *
Subtotal * Angajat 5 9000000
< -
*
Subtotal * Angajat
aplicate 6 n fiecare partiie.10296000
linie cu linie Pasul 3 este operaional numai dac
<
Subtotal * Angajat 7 5904000
interogarea prezint la sfrit o clauz ORDER BY, ceea ce atrage ordonarea
< *
Subtotal * Angajat 8 7848000
final a rezultatului n conformitate cu criteriile specificate. Part i iile
< *
Subtotal * Primul Angajat Nou 1332000
reprezint seturi de linii create dup delimitarea grupurilor prin GROUP BY,
SALORAR P0ZIT1E_RANK P0ZITIE_DENSE_RAN
astfel nct pot constitui subiectul oricrei funcii de agregare (SUM,
K
Angajat 4 75000
AVG...). Constituirea 1
unei partiiile realizeaz n funcie 1de valorile unuia
Angajat 6 sau mai multor atribute
71500 sau expresii de 2 atribute. 2
Angajat 3 67500 3 3
Angajat 5 67500
POZIIE NUMEPREN 3 3
SALORAR
Angajat 7 61500 5 4
Angajat 2 57500 6 5
Angajat 1 1 56000
Angajat 4 7 675000
Primul Angajat Nou 2 Angajat
55500 6 8 771500
.Angajat 8 3 54500
Angajat 3 9 867500
Al Doilea Angajat Nou 4 50500
Angajat 5 10 967500
5 Angajat 7 61500
Figura 7.19.
6 Angajat Clauza GROUPING
2 SETS 57580
7 Angajat 1 56800
8 Primul Angajat Nou 55500
7.5.4. Clasamente: RANK i DENSE_RANK
9 Angajat 8 54588
10 Al Doilea Angajat Nou 50500
Numai n acest capitol au fost formulate cel puin trei soluii pentru
extragerea primelor dou, Figuratrei
7.20. Clasamentul
.a.m.d.salariilor
valori orare
dintr-un clasament.
S ne oprim
Interogarea urmtoare pune n eviden orare.
momentan asupra topului salariilor modul Dar, nainte
de lucru al celor
de toate, s presupunem c Angajat 5 primete o mrire
dou funcii - vezi figura 7.21. Valorile egale au acelai ordin n de salariu
orar ambele
cifrat la 5000 dens,
variante, lei, astfel
n timp nct ajunge
ce RANK la nivelul
atribuie Angajatului
n continuare poziiile
3: lund n calcul numrul valorilor egale,
DENSE_RANK nu.
UPDATE personal
SELECT numepren, salorar,
SET salorar = 6 7 5 0 0
RANK{) OVER (ORDER BY salorar DESC) AS Pozitie_RANK,
WHERE numepren = 'Angajat 5' ;
DENSE_RANK() OVER (ORDER BY salorar DESC)
COMMIT ;
AS Pozitie_DENSE_RANK
FROM personal
La modul cel mai simplu, clasamentul salariilor orare se obine
apelnd la o subconsultare n clauza FROM i pseudo-coloana
ROWNUM:

SELECT ROWNUM AS P o z i i e , numepren, salorar


FROM
(SELECT *
FROM personal ORDER
BY salorar DESC )
Locurile 3-4 sunt pe poziie de egalitate, ns varianta SQL
prezentat nu sesizeaz" acest lucru. Mult mai indicate pentru
acest gen de probleme sunt dou funcii OL AP, RANK i DENSERANK.
Ca pentru orice funcii analitice, procesarea interogrilor cu RANK i
DENSE RANK se deruleaz n trei etape.
Mai nti, se opereaz jonciunile, se constituie grupurile i se
efectueaz selecia asupra grupurilor. Apoi se aranjeaz rezultatul
Oracle. Ghidul dezvoltrii aplicaiilor profesionale
238 239
Interogri SQL avansate

Care sunt cele mai mari trei salarii orare i care sunt fericiii
angajai?
Funciile analitice nu pot fi incluse n clauze WHERE - vezi figura
7.22.

SQL> SELECT numepren, salorar,


2 RANKO OUER (ORDER BV salorar DESC) AS Poziie
3 FROM personal
Figura
h WHERE7.23. Funcia
RANKO OVERRANK pentru
(ORDER BVaflarea celor
salorar mai bine
DESC) <= 3pltii
5 / cinci
angajai
WHERE RANKO OUER (ORDER BV salorar DESC) <= 3 *
S se afieze,
ERROR at linepentru
hz fiecare compartiment, primii doi plasai n
topul veniturilor.
ORA-30483: window Functions are not allowed here
DeFigura
data aceasta, topul trebuie ntocmit difereniat pe fiecare
7.22. Clauza WHERE nu poate conine funcie analitic
compartiment, ceea ce nseamn c este necesar partiionarea
Lucrurile se rezolv prin includerea SELECT-uIui ce conine funcia analitic
dup atributul Compart (vezi figura 7.24):
ntr-o subconsultare i aplicarea predicatului de selecie n fraza principal.
SELECT *
SELECT *
FROM
FROM (SELECT compart, numepren, SUM (orelucrate *
(SELECT numepren, salorar,
salorar + oreco * salorarco) AS Venit_Baza,
RANKO OVER (ORDER BY
RANK() OVERsalorar DESC) AS
{PARTITION BYPoziie
compartFROM personal)
WHERE poziie <= 3
ORDER BY SUM (orelucrate * salorar
+
Rspunsul ar fi fostoreco
identic dac am fi folosit
* salorarco) DENSE_RANK.
DESC) AS
Poziie FROM personal INNER JOIN pontaje
Care sunt primii cinci
ON clasai n topul angajailor
personal.marca = cu cele mai mari
venituri?
De data aceasta, funcia RANK se folosete n condiiile jonciunii
PERSONAL- PONTAJE i gruprii dup nume, criteriul de ordonare fiind
specificat prin funcia
SUM:

SELECT *
FROM
(SELECT numepren, SUM (orelucrate * salorar +
oreco* salorarco) AS Venit_Baza,
RANK() OVER (ORDER BY SUM (orelucrate * salorar+
oreco * salorarco} DESC) AS Poziie FROM personal INNER
JOIN pontaj e
ON personal.marca = pontaje.marca
GROUP BY numepren)
WHERE poziie <= 5

NUMEPREN UENITBAZA POZIIE

Angajat 4 10800808 1
Angajat 6 10296000 2
Angajat 5 9720000 3
Figura 7.21. Funciile RANK i DENSE_RANK
Angajat 3 9660000 4
Angajat 7 8784000 5
C0MPA NUMEPREN UENITBAZA POZIIE
CONTA Angajat 6 10296000 1
CONTA Angajat 7 8784000 2
IT Angajat 5 9720000 1
IT Angajat 3 9660000 2
PR0D Angajat 4 10800000 1
PR0D Angajat 8 7848000 2
240 Oracle. Ghidul dezvoltrii aplicaiilor profesionale 241
Interogri SQL avansate

Specificaiile unei ferestre privesc trei componente:


partiionarea, ordonarea i grupurile de agregare. Orice funcie de
agregare poate fi utilizat n cadrul unei ferestre: SUM, AVG, MIN,
MAX, STDDEV, VARIANCE, COUNT. Pe lng acestea, Oracle, de la
versiunea 8i2, mai ofer suport pentru alte cteva funcii statistice:
VAR_SAMP, VAR_POP, STDDEV_SAMP .a.m.d. Valorile agregate pot fi
cumulative, mictoare sau centrate.

S se afieze, difereniat pe luni calendaristice, valoarea


cumulat, dup fiecare angajat, a veniturilor de baz ctigate de
angajaii firmei.
Partiionarea se realizeaz dup luni, numrul de linii al fiecrei
partiii fiind egal cu numrul angajailor cu minimum un pontaj pe
luna respectiv. Ordonarea liniilor n partiie se realizeaz dup
nume i prenume, iar fereastra pentru care se face calculul
cuprinde toate liniile de la primul angajat pn la angajatul curent
din luna-partiie:

SELECT luna, numepren, Venit_Baza_Angajat_Luna AS


Venit_Angaj_Crt,
SUM (Venit_Baza__Angaj at_Luna) OVER (PARTITION BY luna
ORDER BY numepren ROWS UNBOUNDED PRECEDING)
AS Venit_Luna_Cumulat
FROM
(SELECT EXTRACT (MONTH FROM data) AS luna, numepren,
SUM (orelucrate * salorar + oreco * salorarco)
AS Venit_Baza__Angaj at_Luna FROM personal
INNER JOIN pontaj e
ON personal.marca = pontaje.marca GROUP BY
EXTRACT (MONTH FROM data) , numepren )

Pentru comparaie, n rezultat (figura 7.25) au fost incluse


coloanele veniturilor lunare ale fiecrui angajat (Venit Angaj Crt),
precum i cea calculat prin fereastr/partiionare (Venit Luna
IA NUMEPREN
Cumulat) care UENIT_ANGAJ_CRT
se reseteaz dup LUNA_CUMULAT
Figura 7.24. UENT_ ultima
Clasament linie
pe partiii (angajat)

7 Al Doilea Angajat Hou 1212000 1212000


7 Angajat 1 4032000 5244080
7 7.5.5.
Angajat 2 Ferestre pentru funcii
4092000 analitice 9336000
7 Angajat 3 4812000 14148000
7 Angajat 4 Fereastra se definete 5400000n cadrul unei partiii
19548000 i se refer la
7 Angajat 5 intervalul liniilor luate n4860000
calcul pentru l i n2448800O
i a c u r e n t . Mrimea
7 Angajat 6 ferestrei se poate specifica 5148000 fie fi z i c , 29556000
printr-un numr de
7 Angajat 7 nregistrri, fie 4380000
logic, printr-un 33936080
interval de tip dat
7 Angajat 8 calendaristic/timp sau interval
3924000 de valori. Calculele
37860000 se efectueaz
7 Primul Angajat Hou 1332000 39192000
8 Angajat 1 pentru fiecare linie din cadrul
1792000ferestrei, fereastr
1792000mictoare ntre
8 Angajat 2 o poziie de start i una de final.
1816000 Rndul curent
36 08 008 servete ca punct
8 Angajat 3 de referin pentru determinarea
2148000 nceputului 5756000
i sfritului ferestrei.
8 Angajat 4 2400000 8156000
8 Angajat 5 2160000 10316008
8 Angajat 6 2288000 12604000
242 Interogri SQL avansate

FROM
(SELECT d a t a , C O U N T ( * ) AS Prezeni FROM
ponta je WHERE orelucrate > 0
AND T O _ C H A R ( d a t a , ' M M / YYYY' ) = '
0 7 / 2 0 0 3 ' GROUP BY d a t a )

Liniile rezultatului seamn izbitor cu cele din figura 7.12.


8 Angajat 7 1944000 14548000
8 Angajat Atunci
8 1744000 16292000
cnd, ntr-o partiie, se dorete raportarea valorilor liniei curente
9 Angajat 1 2240000 2240000
la cele din prima sau ultima linie, se pot folosi funciile FIRST VALUE i LAST
9 Angajat 2 2300000 4540000
VALUE.
9 Angajat 3 2700000 7240000
9 Angajat 4 3000000 10240000
S se calculeze, pentru fiecare angajat, raportul dintre venitul
9 Angajat 5 2700000 12940000
9 Angajatsu 6 de baz i venitul celui 2860000 mai mic venit de15800000 baz din firm,
9 Angajatprecum
7 i raportul fa de cel mai mare venit de baz
2460000 18260000din firm.
9 Angajat Am 8 formulat astfel problema pentru a putea
2180000 folosi ambele
20440008
NUMEPREN
funcii iar, pe de alt parte, am definit diferit ferestrele necesare
UEN1T_BAZA UENIT_MINIM UENITJ1AXIM RAPORTJMIIN RAP0RT_U_MAX

01 Doilea Angajat Nou 1212000 1212000 10800000 1 .11


SELECT numepren, venit_baza,
Angajat 1 8064000 1212000 10800000 6.65 .75
Angajat 2
FIRST_VALUE8208000
(venit_baza) OVER (ORDER
1212000 10800000
BY venit_baza
6.77
ASC)
.76
Angajat 3 AS Venit_Minim,
9660000 1212000 10800000 7.97 .89
Angajat 4 LAST_VALUE10800000
(venit_baza) OVER 10800000
1212000 8.91 1
Angajat 5 9720000 1212000 10800000 8.02 .9
Angajat 6
(ORDER BY venit_baza
10296000 1212000
ROWS BETWEEN 8.5
10800000 .95
Angajat 7 UNBOUNDED
8784000 PRECEDING
1212000 AND UNBOUNDED
10800000 7.25 .81
Angajat 8 FOLLOWING)
7848000 1212000 10800000 6.48 .73
Primul Angajat Nou 1332000 1212000 10800000 1.1 .12
AS Venit_Maxim,
ROUND ( venit_baza / FIRST_VALUE (venit_baza) OVER (ORDER
BY venit_baza ASC} ,2)
Figura 7.25. Venituri lunare ale angajailor, curente i cumulate
AS Raport_V_Min,
ROUND(venit_baza / LAST_VALUE (venit_baza) OVER (ORDER
BY venit_baza ROWS BETWEEN UNBOUNDED
7.5.6. PRECEDING
Comparaii AND UNBOUNDED FOLLOWING) ,2)
i ponderi
AS Raport_V_Max
FROM i n aceast categorie sunt nscrise funcii cu un larg evantai de
(SELECT numepren, SUM (orelucrate * salorar + oreco *
faciliti, n timp ce noi vom rezuma discuia la doar cteva
salorarco) AS Venit_Baza FROM ponta j e po INNER JOIN personal
pe ONexemple.
po.marca=pe.marca GROUP BY numepren)
ORDER BY numepren
Care este evoluia zilnic a prezenei n iulie 2003, prin raportare
la ziua lucrtoare anterioar?
Problema a mai fost rezolvat n acest capitol, ns acum vom
apela la funciile LAG prin care extragerea valorii unei coloane de pe
linia precedent devine o formalitate:

SELECT data,
Prezeni AS Prezenti_Zi_Curenta,
NVL (LAG (Prezeni, 1) OVER (ORDER BY data) , 0)
AS Prezenti_Zi_Anterioara,
Prezeni - NVL(LAG (Prezeni, 1) OVER (ORDER BY d a t a ) , 0 )
AS Diferena
Oracle. Ghidul dezvoltrii aplicaiilor profesionale 243

Care este cel mai bine pltit angajat din fiecare compartiment?
Funcia FIRST VALUE se plaseaz intr-o subconsultare ce extrage,
pentru fiecare angajat, venitul su de baz i cel mai mare venit de baz
din compartimentul din care face parte. Fraza SELECT principal extrage
numai liniile n care cele dou venituri sunt egale:

SELECT compart, numepren, venit_baza


FROM
(SELECT compart, numepren, venit_baza,
FIRSTJVALUE ( v e n i t b a z a ) OVER
(PARTITION BY compart ORDER BY venit_baza DESC)
AS Venit_Maxim
FROM
(SELECT compart, numepren,
SUM (orelucrate * salorar + oreco *
salorarco) AS Venit_Baza FROM ponta je po
INNER JOIN personal pe ON
po.marca=pe.marca GROUP BY compart,
numepren)
)
WHERE venit_baza = venit_maxim

Care este angajatul cu numrul de zile lucrate imediat peste cel al


Angajatului 7?
Ideea problemei anterioare st la baza unei noi soluii pentru acest
enun ceva mai vechi:

-SELECT numepren, Zile_L FROM


(SELECT numepren, Zile_L,
FIRST__VALUE (ZileJL) OVER (ORDER BY Zile_L ASC)
AS ZilejDK FROM
(SELECT numepren, COUNT (*) AS Zile_L FROM ponta
je po INNER JOIN personal pe ON po.marca=pe.marca
WHERE orelucrate > 0 AND numepren <> 'Angajat 1'
GROUP BY numepren HAVING COUNT (*) >
(SELECT COUNT ( d a t a ) AS Zile_A7 FROM ponta j e
po INNER JOIN personal pe ON po.marca=pe.marca
WHERE orelucrate > 0 AND numepren = 'Angajat 7' )
)
)
WHERE Zile_L = Zile_OK

S se calculeze partea fiecrui angajat din totalul veniturilor de


baz.
Nu c am fi nemulumii de aportul subconsultrilor scalare la
rezolvarea situaiilor de acest gen, dar merit un pic de atenie i funcia
RATIO TO REPORT

Figura 7.26. Folosirea funciilor FIRSTJVALUE i LAST_VALUE


Oracle. Ghidul dezvoltrii aplicaiilor profesionale 245
244 Interogri SQL avansate

ce calculeaz raportul dintre


Listing o i
7.1. Crearea valoare (atribut/expresie)
popularea tabelei IERARHIE i suma
total a valorii respective pentru
DROP TABLEtoate liniile
ierarhie ; din terestr:

n i t , ROUND
S E L E C T n u m e p r e n , v eCREATE (RAT(
IO__TO_RE PORT (venit)
TABLE ierarhie
OVER () * IOC, 2) AS marca INTEGER
Pondere FROM CONSTRAINT nnjerarhiejnarca NOT NULL CONSTRAINT pkjerarhie
PRIMARY KEY
(SELECT numepren, SUM (orelucrate * s a l o r a r +
CONSTRAINT fk_ierarhie_personal REFERENCES personal (marca)
oreco l o r a r c o ) AS Venit FROM ponta j e po
* s aINTEGER
, marca_sef
INNER JOIN personal
CONSTRAINT pe ON po.marca=pe.marca
fk_ierarhie_personal2 REFERENCES personal (marca)
WHERE pe . marca = po . marca GROUP BY
);
numepren )
ORDER BY numepren
INSERT INTO ierarhie VALUES (104, NULL);
INSERT INTO ierarhie VALUES (108, 104);
INSERT INTO ierarhie VALUES (106, 104);
INSERT INTO ierarhie VALUES (105, 104);
INSERT INTO ierarhie VALUES (110, 108);
INSERT INTO ierarhie VALUES (102, 106);
7.6. Interogri ierarhice
INSERT INTO ierarhie VALUES (107, 106);
INSERT INTO ierarhie VALUES (103, 105);
INSERT INTO ierarhie VALUES (101, 105);
Problema structurii
INSERT ierarhice
INTO ierarhie sau103);
VALUES (109, a arborilor este una care a
COMMIT;__________________________________
suscitat discuii cel puin interesante n comunitatea SQL. Din acest
punct de vedere, Oracle s-a plasat lejer, de ani buni, n faa
S lum
concurenei. n discuie
Cum aproapecteva probleme.
ntotdeauna cnd spunem ierarhie ne
referim la organigram, s analizm structura personalului firmei
aa cumCare este nivelul
se prezint ierarhic
n figura 7.27.al fiecrui salariat?
Din parcurgerea figurii 7.27 deducem c sunt patru niveluri
ierarhice: primul este cel al managerului general (Angajat 4), al
doilea, al efilor de compartimente (Angajat 8 - Producie, Angajat 6
- Contabilitate, Angajat 5 - IT), al treilea, pentru plmai (Al Doilea
Angajat Nou, Angajaii 2, 7 i 1) i un ef mai mititel (Angajat 3), iar
pe ultimul nivel, al patrulea, apare un singur om al muncii (probabil
pentru a echilibra singurtatea managerului general) - Primul
Angajat Nou. Altfel spus, ne intereseaz o situaie asemntoare
MARCA NUMEPREN C0MPA NIUEL

104 Ang PROD 1


ajat
Figura 4 Organigrama firmei
7.27. CONTA 2
106 Ang IT 2
Nu recomandm nici unei
ajat 6 firme s-i organizeze PROD de2 aceast
manier personalul, 105
ns pentru Ang binele exemplelor CONTA am diminuat
3 din
pretenii. Ct privete ajat
structura 5 bazei de date, pentru CONTA reflectarea
3
subordonrii angajailor 108se poate aduga n tabela PERSONAL IT 3 IT
atributul Marca ef pentru care s-ar declara o restricie
Angajat 3 PROD
referenial,
110 Marc
atributul printe fiind Al8 Doilea Angajat
din aceeai Nou
tabel. 3 IT 4
109 Primul
Noi ns vom crea i popula Angajat Nou special, pe care o vom
o tabel
denumi IERARHIE - vezi listing
Figura 7.1. ierarhic al fiecrui angajat
7.28. Nivelul
246 Interogri SQL avansate

Persoanele de pe fiecare nivel vor fi furnizate de un SELECT


distinct, aa c, n final, vom reuni consultrile celor patru niveluri:

SELECT p . m a r c a , numepren, compart, '1' AS Nivel FROM personal p


INNER JOIN ierarhie i ON p.marca = i .marca WHERE marca_sef IS NULL
UNION
SELECT marca, numepren, compart, '2' AS Nivel FROM personal WHERE
marca IN
(SELECT marca FROM ierarhie
WHERE marca_sef IN (SELECT
marca FROM ierarhie WHERE
marca_sef IS NULL )
)
UNION
SELECT marca, numepren, compart, '3' AS Nivel FROM personal WHERE
marca IN
(SELECT marca FROM ierarhie WHERE
marca_sef IN (SELECT marca FROM
ierarhie WHERE marca_sef IN (SELECT
marca FROM ierarhie WHERE marca_sef
IS NULL )
)
)
UNION
SELECT marca, numepren, compart, M' AS Nivel
FROM personal WHERE marca IN
(SELECT marca
FROM ierarhie WHERE marca sef
IN (SELECT marca FROM ierarhie
WHERE nirca_sef IN (SELECT
marca FROM ierarhie WHERE
marca_sef IN (SELECT marca
FROM ierarhie WHERE marca_sef
IS NULL )
248 Interogri SQL avansate
Oracle. Ghidul dezvoltrii aplicaiilor profesionale 247
COMPA
ON p .mar ca = i.ma rcNIUEL
a
107 Angajat 7 WH )
ERE nume p re n
CONTA = ' Ang ajat 1
1' ) )
106 Angajat 6
Pentru varianta) bazat
CONTA pe interogri2 ierarhice, schimbm ordinea
104 Angajat 4 ORDERBY 4 , 3 , 2
PROD 3
atributelor din START WITH astfel nct piramida se construiete
nspre"Este
sus, greu
ncepnd
de cu Angajatsenzaia
reprimat 7. Interogarea:
de disconfort provocat de
ntinderea interogrii. Ca s nu ne mai stricm ziua gndindu-ne ce
SEL ECT marc a, nume p re n, co mp art , L EV EL AS
interesant ar fi fost ca firma s aib vreo apte-opt niveluri
N ive l FROM
ierarhice.
(SEL E CT p .mar ca, nume p re n, co mp art ,
Princa_s
mar comparaie,
ef FROM pesoluia
rs o nal p urmtoare
INN ER JOIN este mai mult dect bine
ie r arhie
venit,
i ON avnd
p .mar caacelai rezultat:
= i . mar ca)
STA RT WI TH nume p re n = ' Ang aj at 7'
CON N ECT
SELECT BY PRIORm
marca, ar ca_s
numepren, ef = mar
compart, ca AS Nivel
LEVEL
FROM
obine rezultatul dinp figura
(SELECT .marca 7.29, deci toi
, numepren, efii angajatului
compart, marca_sef reper
(plus el nsui).
FROM personal p INNER JOIN ierarhie i ON p. mar ca
= i .marca)
START W I T H marca_sef IS NULL
CONNECT BY PRIOR marca =marca_sef
ORDERBY 4 , 3 , 2

Construirea structurii ierarhice ncepe cu nregistrarea


(nregistrrile) care ndeplinete condiia din clauza START WITH.
Aceast nregistrare (nregistri) printe va fi legat de
nregistrarea sau nregistrrile copil prin condiia Marca = Marca ef.
Clauza PRIOR, plasat n stnga condiiei, semnific: valoarea
atributului Marca din printe trebuie s fie egal cu valoarea Marca
ef din nregistrrile copil. Prin CONNECT BY sunt selectate toate
generaiile succesive de linii-copil (copii, nepoi, strnepoi etc.).
Dup construirea ierarhiei, se elimin tuplurile ce nu ndeplinesc
condiia formulat n clauza WHERE. Este important de notat c
selecia se aplic linie cu linie, iar eliminarea unei linii-printe nu
atrage automat eliminarea copiilor, nepoilor .a.m.d. n lipsa clauzei
de ordonare, nregistrrile sunt dispuse n funcie de ordinea
parcurgerii arborelui.
Un avantaj major al interogrilor ierarhice ine de folosirea pseudo-
coloanei LEVEL ce semnific tocmai nivelul ierarhiei, relativ la
nregistrarea/nregistrrile rdcin" care ndeplinete/ndeplinesc condiia
din START W I T H . Ca principale restricii trebuie amintit c SELECT-ul care
execut o interogare ierarhic nu poate efectua o jonciune i nici extrage
date dintr-o tabel virtual creat printr-o jonciune. Alt atu al interogrilor
ierarhice ine de faptul c nu exist o limit n privina nivelurilor de
subordonare.

Cum se numete eful Angajatului


7? ncepem cu o variant clasic:

SELECT
Oracle. Ghidul dezvoltrii aplicaiilor profesionale 249

STA RT WI TH nume p re n = ' Ang aj at 5 '


CON N ECT BY PRIOR marc a = mar ca_s ef
5

Rezultatul din figura 7.30 arat att numele, ct i nivelul ierahic


inferior al fiecruia dintre subordonai.

MARCA NUMEPREN COMPA NIUEL

105 Angajat 5 IT 1 103 Angajat 3 IT 2 109


Primul Angajat Nou IT 3 101 Angajat 1 IT 2

Figura 7.30. Subordonaii Angajatului 5

Care sunt subordonaii subordonailor

directorului general?
Practic, liniile care intereseaz sunt cele nepot" ale
nregistrrii-rdcin, Figura
cea 7.29. efii Angajatului
pentru care Marca 7 Sef IS NULL. Dac inem
cont
eful c directorul
imediat general este
al Angajatului 7 este pecel primul nivel
de nivel ierarhic,
2 din figura atunci
de
mainepoii
sus: si sunt plasai pe nivelul 3:
SEL ECT *
SEL ECT *

n
FROM
FROM
(SEL E CT m arc a, nume p re n, co mp art , L EV EL AS
(SEL E CT ma rc a, nume p re n, co mp art , L EV EL AS
N ive l FROM
N ive l FROM
(SEL E CT p .mar ca, numep re n, co mp a rt ,
(SEL E CT p .mar ca, numep re n, co mp a rt ,
mar ca_s ef FROM pe rs o nal p INN ER JOIN ie r arhie

n
mar ca_s ef FROM pe rs o nal p INN ER JOIN ie r arh ie
i ON p . marc a = i . mar ca)
i ON p .mar ca = i.m arc a)
STA RT WI TH nume p re n = ' Ang a j at 7'
STA RT WITH m arc a_s ef IS N UL L
CON N ECT BY PRIORm ar ca_s ef = mar ca
CON N ECT BY PRIOR marc a
) = marc a_s ef )
WHWH
EREEREnive l = l2= 3
nive

Care
Ssunt

semnului
subordonaii
se afieze
Piramida
Pentruse
egal al
indentare
direci
structura
unconstruiete
ai Angajatului
ierarhic
plus de vizibilitate
laCONNECT atributul
stnga;BY dup
a firmei. 5?
de la Angajat
vom 2afia
n jos, plasnd
numele n stnga cu
angajailor
Marca: angajat urmeaz imediat
fiecare
subordonaii si i subordonaii subordonailor - vezi figura 7.31.
n
n
SEL ECT *
Fiecrui nivel ierarhic i va corespunde un nivel de indentare.
FROM
Funcia
(SEL E CTfolosit pentru
m arc a, nume indentare
p re n, co mp art , este
L EV EL LPAD.
AS n rest, lucruri
cunoscute:
N ive l FROM
(SEL E CT p .mar ca, numep re n, co mp a rt ,
SEL ECT Lmar
PADca_s
AS nume
( ' ',
i ON ppre
ef5FROM
* (L EVpe
n, coa
. marc mp= art
ELrs-o1nal
i . ,nj&rc
) , p INN
L EV EL
) | ER
| nume
JOINpie
a) AS N ive l FROM
rernarhie i
(SEL E CT p .mar ca, numep re n, co mp a rt ,
mar ca_s ef FROM pe rs o nal p INN ER JOIN ie r arh ie i ON

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