Sunteți pe pagina 1din 281

Costin Radu BOLDEA

Gestiunea Bazelor de
date DISTRIBUITE în
ORACLE folosind PL/SQL

Joshua Print
Vrsac, Republica SRBIJA
2020
CUPRINS
CAPITOLUL I. BAZE DE DATE ŞI SISTEME DE GESTIUNE A
BAZELOR DE DATE ................................................................................ 6
1.1. CONCEPTE UTILIZATE ÎN STUDIUL BAZELOR DE DATE ŞI AL
SISTEMELOR DE GESTIUNE A BAZELOR DE DATE ........................................ 6
1.1.1. Metoda prelucrării prin fişiere independente ............................ 6
1.1.2. Baze de date ............................................................................... 9
1.1.3. Depozite de date ....................................................................... 16
1.1.4. Proiectarea bazelor de date ..................................................... 21
a.Analiza structurală sau statică ................................................................ 23
b. Integrarea modelelor sistemului ............................................................ 24
c. Proiectarea structurii bazei de date ........................................................ 24
d. Încărcarea datelor în baza de date ......................................................... 28
e. Exploatarea şi întreţinerea bazei de date ............................................... 28
1.2.1 Tipuri de relaţii şi structuri de reprezentare a relaţiilor în cadrul
unei baze de date ................................................................................ 29
1.2.2 Modele de organizare a datelor în bazele de date .................... 31
1.3 SISTEME DE GESTIUNE A BAZELOR DE DATE ...................................... 43
2.4. PROTECŢIA ŞI SECURITATEA BAZELOR DE DATE ............................... 51
SECURITATEA BAZEI DE DATE ................................................................. 54
CAPITOLUL II. MEDIUL INTEGRAT DE GESTIUNE ŞI
PROGRAMARE ORACLE ..................................................................... 60
2.1 CE ESTE ORACLE ............................................................................ 60
2.2 INSTALAREA SISTEMULUI ORACLE 11G EXPRESS EDITION ................ 64
2.3. ORACLE FORMS BUILDER................................................................. 74
2.4. OBIECTELE ŞI TIPUL ACESTORA ÎN FORMS BUILDER ......................... 76
2.4.1. Forme (Forms) ......................................................................... 76
2.4.2. Declanşatoare (Triggers) ......................................................... 76
2.4.3. Ferestre de Avertizare (Alerts) ................................................. 77
2.4.4. Blocuri de date (Data Blocks) .................................................. 77
2.4.5. Elemente (Items) ...................................................................... 78
2.4.6. Relaţii (Relations) .................................................................... 78
2.4.7. Canvas-uri (Canvases) ............................................................. 78
2.4.8. Editoare (Editors) .................................................................... 78
2.4.9. Parametrii (Parameters) .......................................................... 79
2.4.10. Unităţi de program (Program Units) ..................................... 79
2.4.11. Ferestre (Windows) ................................................................ 80

1
2.5. ORACLE11G: DATABASE / APPLICATION SERVER / DEVELOPER
SUITE ...................................................................................................... 80
2.5.1. Oracle11g Database ................................................................ 80
2.5.2. Oracle11g Application Server .................................................. 82
2.5.3. Oracle11g Developer Suite ...................................................... 83
CAPITOLUI IV. LIMBAJUL DE DEFINIRE, INTEROGARE ŞI
MANIPULARE A BAZELOR DE DATE SQL ..................................... 86
3.1. EVOLUŢIE ŞI PERFORMANŢE ............................................................. 86
3.2. COMENZI PENTRU DESCRIEREA DATELOR. LIMBAJUL DDL (DATA
DESCRIPTION LANGUAGE) ...................................................................... 93
3.3. COMENZI PENTRU INTEROGAREA BAZELOR DE DATE. FRAZA SELECT
................................................................................................................ 96
3.3.1 Interogări care utilizează operatorii asamblişti din algebra
relaţională .......................................................................................... 99
3.3.2 Interogări care utilizează operatorii relaţionali din algebra
relaţională ........................................................................................ 100
a. Selecţia ................................................................................................ 100
b. Proiecţia. Opţiunea ORDER BY ......................................................... 104
c. Joncţiunea............................................................................................ 105
d. Sub-consultări. Operatorul IN ............................................................. 106
e. Funcţii de agregare (statistice): COUNT, SUM, AVG, MAX, MIN ... 109
f. Gruparea tuplurilor. Clauzele GROUP BY şi HAVING...................... 111
5.4. Comenzi pentru actualizarea bazelor de date ........................... 117
3.4. COMENZI PENTRU MANIPULAREA DATELOR. LIMBAJUL DML (DATA
MANIPULATION LANGUAGE) ................................................................ 118
3.4.1 Adăugarea de înregistrări ....................................................... 118
3.4.2 Ştergerea înregistrărilor ......................................................... 119
3.4.3 Modificarea valorilor unor atribute ........................................ 120
3.5 INTEROGAREA A UNEI BAZE DE DATE ORACLE 11G ........................ 121
CAPITOLUI IV. LIMBAJUL PL/SQL ................................................ 124
4.1. INTRODUCERE ................................................................................ 124
4.2. CREAREA UNUL BLOC DE BAZA PL/SQL ....................................... 126
4.2.1 Tipurile de blocuri .................................................................. 127
4.2.2. Operatori, delimitatori şi variabile ........................................ 128
4.2.3. Atribuirea unei valori variabilei ............................................ 130
4.2.4. Declararea Constantelor ....................................................... 132
4.2.5 Citirea şi afişarea variabilelor în PL/SQL .............................. 132
4.2.6 Atributele de transfer automat a tipului de date ..................... 133
a. Atributul %TYPE ................................................................................ 133
b. Atributul %ROWTYPE ...................................................................... 133

2
4.3. INSTRUCŢIUNI ÎN PL/SQL .............................................................. 135
4.3.1 Instrucţiuni de atribuire .......................................................... 135
4.3.2 Structuri de control ................................................................. 138
a. Instrucţiunea IF ................................................................................... 138
b. Instructiunea IF-THEN-ELSIF ........................................................... 140
c. Instructiunea CASE ............................................................................. 141
4.3.3 Structuri de ciclare.................................................................. 143
a. LOOP .................................................................................................. 143
b. Folosirea comenzii EXIT ................................................................... 143
c. Comanda EXIT-WHEN ..................................................................... 144
d. Etichetarea unei blucle PL/SQL ......................................................... 145
e. Bucla WHILE-LOOP .......................................................................... 145
f. Utilizarea buclei FOR-LOOP .............................................................. 146
4.3.4 Folosirea excepţiilor ............................................................... 148
a. Tratarea excepţiilor predefinite ale Serverului Oracle ......................... 150
b. Tratarea excepţiilor non-predefinite Oracle Server ............................. 152
c. Tratarea excepţiilor definite de utilizator ............................................ 153
CAPITOLUL V. POCEDURI ŞI FUNCŢII ÎN PL/SQL .................... 155
5.1. PROCEDURI STOCATE ŞI FUNCŢII ÎN PL/SQL .................................. 155
5.2. PACHETE DE PROCEDURI ÎN PL/SQL .............................................. 159
5.3. TRIGGERE ÎN PL/SQL..................................................................... 162
5.4. CURSOARE ÎN PL/SQL ................................................................... 170
5.4.1. Cursoare Implicite ................................................................. 170
5.4.2. Cursoare explicite .................................................................. 174
CAPITOLUL VI. PROIECTAREA FIZICĂ A BAZELOR DE DATE
RELAŢIONALE ..................................................................................... 185
6.1. CARACTERISTICI ALE UNEI BAZE DE DATE FIZICĂ ........................... 185
6.2 TRANSFORMĂRI LOGICO-FIZICE DE BAZĂ ........................................ 187
6.2.1 Partiţionarea verticală ............................................................ 188
6.2.2 Partiţionarea orizontală ......................................................... 190
6.2.3 Reuniunea ............................................................................... 191
6.2.4 Aplicabilitatea transformărilor ............................................... 194
6.2.5 Scheme virtuale (vederi utilizator) .......................................... 195
6.3. OPTIMIZAREA PERFORMANŢEI ........................................................ 196
6.3.1 Accesul la atribut .................................................................... 196
6.3.2. Reuniuni preconstruite ........................................................... 199
6.3.3 Buffere ..................................................................................... 201
6.3.4 Gruparea relaţiilor de bază ................................................... 202
6.4 BAZE DE DATE RELAŢIONALE DISTRIBUITE ...................................... 204

3
CAPITOLUL VII. TRANZACŢII ÎN BAZE DE DATE DISTRIBUITE
.................................................................................................................. 206
7.1 INTRODUCERE ................................................................................. 206
7.2 TRANZACŢII .................................................................................... 208
7.2.1 Definiţie................................................................................... 208
7.2.2 Caracterul atomic ................................................................... 208
7.2.3 Caracterul consistent .............................................................. 209
7.2.4 Izolare ..................................................................................... 209
7.2.5 Durabilitatea ........................................................................... 210
7.2.6 Probleme de control ................................................................ 210
7.2.7 Exemplu aplicativ .................................................................... 214
7.3 BLOCARE (LOCK) ............................................................................ 218
7.4 INTERBLOCARE (DEADLOCK) .......................................................... 222
7.5 SERIALIZARE ................................................................................... 224
7.6 BLOCARE IERARHICĂ ...................................................................... 230
CAPITOLUL VIII. ANOMALII DE COMPORTAMENT ŞI
ALGORITMI DE CONTROL A CONCURENŢEI ÎN SGBD
DISTRIBUITE ........................................................................................ 233
8.1. ANOMALII DE INTERFERENŢĂ ÎN BD DISTRIBUITE .......................... 235
8.1.1 Anomalia de actualizare pierdută ........................................... 235
8.1.2. Anomalia dată de citiri improprii .......................................... 236
8.1.3. Anomalia de citire nereproductibilă ...................................... 237
8.2. INTRODUCEREA RESTRICŢIILOR DE COMPORTAMET CONCURENT:
PRIMITIVELE LOCK ŞI UNLOCK ......................................................... 238
8.3. SERIALIZABILITATE: DEFINIRE ŞI EXEMPLU .................................... 242
8.4. FORMALIZAREA CONCEPTULUI DE SERIALIZABILITATE. PLANIFICAREA
OPERAŢIILOR CONCURENTE ÎN SGBDD ................................................ 245
8.5 ALGORITMI DE CONTROL AL CONCURENŢEI ŞI TESTARE A
SERIABILITĂŢII ...................................................................................... 251
8.5.1. Controlul concurenţei prin blocare........................................ 251
8.5.2 Algoritm de testare a serializabilităţii .................................... 253
8.5.3 Protocolul în două faze pentru asigurarea serializabilitătii .. 257
8.6. TRANZACŢII CU ACCESE DE TIP READ-ONLY ŞI READ-WRITE ........... 260
CAPITOLUL IX. PROCESAREA TRANZACTIILOR ÎN PL/SQL 263
9.1 FOLOSIREA COMENZII COMMIT IN PL/SQL .................................. 263
9.2 FOLOSIREA COMENZII ROLLBACK IN PL/SQL ............................. 265
9.3 FOSIREA COMENZII SAVEPOINT IN PL/SQL ................................. 267
9.4 SETAREA PROPRIETĂŢILOR TRANZACŢIILOR CU COMANDA SET
TRANSACTION .................................................................................. 269

4
9.4.1. SET TRANSACTION READ ONLY ........................................ 269
9.4.2. SET TRANSACTION READ WRITE ...................................... 270
9.4.3. Clauza ISOLATION LEVEL ................................................... 270
9.5 Blocări explicite ......................................................................... 271
BIBLIOGRAFIE .................................................................................... 275
ANEXĂ: FUNCŢII PREDEFINITE ÎN PL/SQL ................................ 277

5
Capitolul I. BAZE DE DATE
ŞI SISTEME DE GESTIUNE
A BAZELOR DE DATE

Sistemele de baze de date reprezintă cea mai importantă


dezvoltare în domeniul ingineriei programării, ele devenind din ce în
ce mai accesibile penru o largă varietate de utilizatori.

1.1. Concepte utilizate în studiul bazelor de date şi al


sistemelor de gestiune a bazelor de date
1.1.1. Metoda prelucrării prin fişiere independente
Sistemul bazat pe fişiere reprezintă sistemul anterior bazelor
de date. Modul de lucru bazat pe fişiere independente, demodat
astăzi, are o serie de neajunsuri care limitează eficienţa şi eficacitatea
aplicaţiilor utilizator [1].
Specific metodei prelucrării prin fişiere, ilustrată în fig. 2.1.
[2], este faptul că fiecare dată (Data1, Data2, ..., Datan) este descrisă
în toate fişierele în care apare, iar fiecare fişier trebuie descris în
toate programele în care este utilizat. Nu există nici o posibilitate de
a stabili în mod explicit o relaţie între două fişiere de date.
De asemenea, dacă spre exemplu, Data2 din Fişier1 este
modificată, modificarea nu se face automat şi în Fişier2, ceea ce
determină inconsistenţa datelor.
Dezavantajele organizării datelor în fişiere pot fi sistematizate
astfel:
1. Redundanţa şi inconsistenţa datelor, datorită prezenţei
aceleiaşi date în mai multe fişiere independente;

6
Aceleaşi date sunt înregistrate şi stocate în mai multe fişiere,
ceea ce reclamă programe distincte pentru actualizarea fiecărui fişier.
În plus, duplicarea datelor conduce la un consum mare de memorie şi
incoerenţă la trecerea datelor stocate dintr-un fişier în altul. Aceasta
duce la alterarea integrităţii datelor (datele nu mai concordă),
gestionarea complexă şi actualizarea greoaie a acestora, precum şi la
o monopolizare inutilă a spaţiului de memorie.
2. Complexitatea actualizărilor (adăugarea, ştergerea sau
modificarea datelor);
3. Dificultatea obţinerii de informaţii neplanificate (spontane
sau ad-hoc), chiar şi pentru o simplă interogare fiind
necesară scrierea unui program;

Data1
Data2 Raport
FIŞIER 1 Prelucrare 1 1
Data3 ...
Raport
Data2 FIŞIER 2 Prelucrare 2 2
Data4 Raport
... 3
Data3
FIŞIER 3 Prelucrare 3 Raport
Data1 4
Data2 Data5 ...
DATE FIŞIERE PRELUCRĂRI IEŞIRI

Fig. nr. 1.1.Organizarea datelor în fişiere

Dispersia datelor în diverse fişiere independente complică


accesul utilizatorilor la informaţiile cerute ad-hoc, necesitând crearea
de programe particulare pentru extragerea datelor solicitate. În lipsa
acestor programe, pentru obţinerea informaţiilor dorite utilizatorul
procedează la extragerea manuală.
4. Costul ridicat de exploatare ca urmare a dublării datelor;

7
Exploatarea fişierelor independente presupune un cost ridicat,
atât în ceea ce priveşte resursele informatice (hardware şi software),
cât şi cele legate de personalul utilizat.
5. Separarea şi izolarea datelor;
Atunci când datele sunt izolate în fişiere separate, programatorul
de aplicaţii trebuie să se asigure că sunt extrase datele corecte, fiind
astfel necesară sincronizarea prelucrării datelor din fişiere diferite,
această operaţiune fiind dificilă când sunt solicitate date din mai
mult de două fişiere.
6. Formate de fişiere incompatibile, ceea ce face dificilă
prelucrarea lor simultană
Deoarece structura fişierelor este încorporată în programele de
aplicaţii, ea este dependentă de limbajul de programare în care sunt
scrise acestea. De exemplu, structura unui fişier generat de un
program scris cu limbajul COBOL poate să fie diferită de cea a unuia
generat cu un program în limbajul C. De aceea sunt necesare
programe de transformare a fişierelor într-un format comun.
7. Dependenţa datelor faţă de programele de aplicaţii
Organizarea fişierelor, adresa lor fizică în memorie şi programele
de aplicaţii folosite pentru accesarea fişierelor sunt interdependente.
Astfel, schimbările legate de dispunerea pe suportul de memorie, de
structura datelor şi modificarea înregistrărilor unui fişier presupun
modificări în toate programele în care este referit fişierul respectiv.
Întreţinerea acestor programe este dificilă putând genera incoerenţe
în fişierele de date. Incoerenţa şi lipsa de integritate sunt extrem de
dificil de corectat deoarece nu există un dicţionar central pentru
urmărirea definirii datelor.
Toate aceste probleme care apar în sistemul ce prelucrează
fişiere îşi găsesc rezolvarea prin folosirea bazelor de date şi a
sistemelor de gestiune a bazelor de date. Datele stocate în baze sunt
independente atât faţă de programele de aplicaţii care le folosesc, cât
şi faţă de tipul de memorie utilizat.

8
1.1.2. Baze de date
Pe măsura evoluţiei sistemelor de prelucrare automată a
datelor şi, în mod special, a componentei hardware şi software, dar şi
ca urmare a creşterii volumului datelor de prelucrat s-a dezvoltat un
nou concept, cel al bazelor de date. El îşi face apariţia în a doua parte
a anilor ’60, aducând un element de noutate, respectiv existenţa unui
fişier de descriere globală a datelor, ceea ce asigură independenţa
datelor de programe şi invers, fişier denumit dicţionar de date (vezi
fig. nr. 3.2). La momentul respectiv, în cadrul sistemelor informatice
implementate în întreprinderi, informaţiile erau organizate în fişiere
de date (secvenţiale, indexate etc.) create cu ajutorul unor programe
scrise în limbaje din generaţia a III-a: COBOL, FORTRAN etc.
Principiul fundamental al bazelor de date îl constituie
unicitatea informaţiilor, adică orice informaţie este înregistrată o
singură dată şi poate fi utilizată ori de câte ori este nevoie, de către
diferiţi utilizatori şi în diferite momente.
Baza de date reprezintă un ansamblu integrat de înregistrări
sau de fişiere reunite şi structurate în mod logic. În felul acesta datele
stocate anterior în fişiere independente/distincte sunt concentrate
într-un fond comun de înregistrări cu posibilitatea utilizării lor în
numeroase aplicaţii.
Baza de date este o colecţie partajată de date între care există
relaţii logice şi o descriere a acestor date, proiectată pentru a
satisface necesităţile informaţionale ale unei organizaţii. Ea
reprezintă un depozit de date unic care este definit o singură dată şi
este utilizat simultan de către mai multe departamente şi utilizatori.
În loc de a mai exista fişiere separate cu date redundante, toate datele
sunt integrate, cu o dublare minimă. Baza de date nu mai este
deţinută de un singur departament, ci constituie acum o resursă
comună, partajată. Ea conţine nu numai datele operaţionale ale
organizaţiei, ci şi o descriere a acestora. De aceea ea este definită şi
ca o colecţie autodescrisă de înregistrări integrate. Această descriere
a datelor este cunoscută sub denumirea de catalog de sistem sau
dicţionar de date sau meta-date (date despre date). Natura
autodescriptivă a bazelor de date este cea care determină
independenţa program-date.
9
BAZA DE DATE

Fişier de date 1

Fişier de date 2 Dicţionar


... de
date
Fişier de date n

Aplicaţia 1 Aplicaţia 2 ... Aplicaţia m

Fig. nr .1.2. Structura unei baze de date

Conceptul de bază de date a apărut în 1964 în cadrul


primului raport CODASYL1 prezentat la lucrările unei Conferinţe pe
probleme de limbaje de gestiune a datelor “Development and
Management of Computer – centered date-base”. La această
conferinţă a fost lansată ideea organizării datelor prin intermediul
unui fişier de descriere globală, numit dicţionar de date care are
menirea de a asigura independenţa programelor faţă de date şi a
datelor faţă de programe ă [4].
Atunci când se analizează necesităţile informaţionale ale
unei organizaţii se urmăreşte identificarea entităţilor, a atributelor şi
a relaţiilor dintre entităţi. De aceea, abordarea bazelor de date
presupune şi tratarea următoarelor elemente: entitate (articol,
înregistrare logică), atribut (caracteristică, câmp) şi
valoare/realizare2.

1
COnference on DAta SYstems Languages – Conferinţa despre
Limbajele Sistemelor de Date
2
Aceste elemente sunt numite diferit în literatura de specialitate.
[2],[6],[7]

10
Prin entitate se înţelege un obiect concret sau abstract
(operaţie economică, mijloc economic etc.) reprezentat prin
proprietăţile sau însuşirile sale. Orice proprietate poate fi exprimată
printr-o pereche atribut-valoare sau caracteristică-realizare. O
entitate este identificată printr-un nume şi cuprinde, în general, mai
multe valori sau realizări.
Atributul are rolul de a descrie însuşirile sau proprietăţile
obiectului, stabilind natura valorilor pe care acesta le poate lua.
Valoarea reprezintă mărimea ce se atribuie fiecărei
caracteristici din cadrul unei entităţi.
Relaţia reprezintă o asociaţie între mai multe entităţi.
Aceste elemente sunt prezentate în tabelul nr. 1.1:

Entitate Caracteristici (atribute) Realizări (valori)


Cod_produs 152
Denumire_produs Pantofi
Unit_măs Pereche
Produs Preţ_ unitar 115
Cantitate 100
Nr._factură 2452
Data_recepţiei 24-10-2007
Tabel 1.1. Elemente specifice bazelor de date
O bază de date trebuie să satisfacă cinci condiţii esenţiale3:
 O bună reprezentare a realităţii înconjurătoare, adică
baza de date trebuie să ofere întotdeauna o imagine
fidelă a realităţii prin informaţii fiabile şi actualizate;

3
Moréjon, J., Principes et conception d’une base de données
relationnelle, Les Editions d’organisation, Paris, 1992, p. 20

11
 O non-redundanţă a informaţiei, informaţia conţinută în
baza de date trebuind să fie unică din punct de vedere
semantic şi fizic;
 O independenţă a datelor faţă de prelucrări; datele
constituie imaginea fidelă a lumii reale, programele de
aplicaţii trebuind să fie concepute în raport cu această
structură a datelor;
 Securitatea şi confidenţialitatea datelor; securitatea
datelor trebuie asigurată prin proceduri fizice, iar
confidenţialitatea prin proceduri care să împiedice
accesul utilizatorilor neautorizaţi;
 Performanţe în exploatare, orice cerere de prelucrare
trebuind să fie satisfăcută într-un timp convenabil
utilizatorului, ceea ce presupune folosirea unor tehnici
de optimizare pentru reducerea timpului de prelucrare.

Dicţionarele de date
Accesul utilizatorilor la informaţiile despre structura unei baze
de date se realizează prin intermediul dicţionarului de date.
În principal, un dicţionar îndeplineşte următoarele funcţii:
 definirea şi gestionarea datelor elementare ale întreprinderii (cod,
etichetă, atribute, reprezentare etc.);
 definirea şi gestionarea ansamblurilor de date;
 definirea şi gestionarea relaţiilor, de dependenţă sau ierarhice,
dintre date;
 descrierea din trei puncte de vedere a utilizării datelor:
 administrativ: care sunt posturile de lucru ce vor apela
datele şi care va fi utilizarea acestor date?
 logic: care sunt fişierele sau bazele de date în care intră
elementele descrise?;
 organic: în care unităţi de prelucrare vor fi utilizate
elementele descrise?
În plus dicţionarele de date permit automatizarea operaţiilor
de scriere, de descriere a fişierelor sau ecranelor, de control etc. utile
pentru întreţinerea şi dezvoltarea dosarelor de programe.

12
Bazele de date sunt concepute pentru a prelucra un volum
mare de informaţii. Gestiunea acestora impune nu numai o
structurare riguroasă a datelor, dar şi o raţionalizare a procedurilor de
acces şi prelucrare. Pentru a putea fi exploatată de către utilizatori o
bază de date trebuie să aibă asociat un set de programe, numit
generic sistem de gestiune a bazelor de date care să permită
exploatarea raţională a datelor conţinute. Obiectivul esenţial al unui
sistem de gestiune a bazelor de date este, deci, furnizarea unui mediu
eficient, adaptat utilizatorilor care doresc să consulte sau să
actualizeze informaţiile conţinute în baza de date.
Sistemul de gestiune a bazelor de date reprezintă un
ansamblu coordonat de programe care permite descrierea,
memorarea, manipularea, interogarea şi tratarea datelor conţinute
într-o bază de date. El trebuie, de asemenea, să asigure securitatea şi
confidenţialitatea datelor într-un mediu multi-utilizator.
Principalele beneficii ale bazelor de date constau în:
 integrarea în aceeaşi structură a tuturor datelor pertinente
ale unui sistem;
 gestionarea acestor date printr-un software specializat
(SGBD);
 oferirea unei vederi parţiale asupra ansamblului de date
necesare fiecărui utilizator;
 asigurarea partajării datelor între diferiţi utilizatori.

13
Niveluri de abstractizare a datelor în bazele de date
Abordarea datelor în contextul bazelor de date se face pe trei
niveluri, considerate niveluri de abstractizare:
Nivelul intern este nivelul elementar la care pot fi
considerate datele şi se referă la modul în care sunt stocate datele pe
suporturi - disc magnetic, bandă magnetică, disc optic etc. La acest
nivel structura datelor este foarte detaliată. Nivelul intern cuprinde
structurile de date şi organizările fişierelor utilizate pentru stocarea
datelor pe dispozitivele de stocare. El tratează probleme cum ar fi:
alocarea spaţiului de stocare pentru date şi indexuri, descrierile
înregistrărilor pentru stocare, cu dimensiunile de stocare pentru
articolele de date, plasarea înregistrărilor, tehnicile de comprimare şi
de codificare a datelor. Nivelul intern interacţionează cu metodele de
acces al sistemului de operare (tehnici de administrare a fişierelor,
pentru stocarea şi regăsirea înregistrărilor de date) pentru a plasa
datele pe suporturile de stocare, a regăsi datele, a realiza indexurile.
Nivelul conceptual corespunde administratorului bazei de date
care proiectează structura logică a bazei de date. Asigură o viziune
globală. a bazei de date, descriind ce date sunt stocate în baza de date şi
relaţiile dintre acestea. La acest nivel structura bazei de date se
concretizează în schema conceptuală. Nivelul conceptual asigură atât
transpunerea, cât şi independenţa dorită dintre nivelul extern şi cel
intern.
Nivelul conceptual reprezintă toate entităţile, atributele şi
relaţiile dintre ele, contrângerile asupra datelor, informaţii semantice
despre date, informaţii privind securitatea şi integritatea.
Nivelul extern reprezintă vederea utilizatorului asupra bazei de
date ce descrie acea parte a bazei de date relevantă pentru fiecare
utilizator. Recurgerea la acest nivel de abstractizare se face pentru
simplificarea interacţiunii utilizator-bază de date. Acest nivel
corespunde utilizatorilor care pot avea viziuni diferite asupra bazei de
date pe baza unor subscheme proprii. Vederea externă include numai
acele entităţi, atribute şi relaţii din lumea reală de care este interesat
utilizatorul. Se urmăreşte satisfacarea cerinţelor tuturor utilizatorilor în
condiţiile unei redundanţe minime şi controlate a datelor.

14
Văzută prin prisma celor trei niveluri, baza de date poate fi
reprezentată ca în figura nr.2.3.[7]

Utilizator A1 Utilizator A2 Utilizator B1 Utilizator B2 ...

Aplicaţie Comenzi Comenzi ….


autonome Aplicaţie
autonome

Schema Imagine A Schema


externă A externă B Imagine B ….
(nivel extern) (nivel extern)

INTERFAŢA A INTERFAŢA B

Schema conceptuală Imagine globală Sistem de


(globală) (nivel global) gestiune a
bazei de date

INTERFAŢA

Schema internă
BAZA DE DATE MEMORATĂ P E DISC

Fig. nr.1.3. Nivele de abstractizare a datelor în bazele de date


Includerea în baza de date a descrierii structurii acesteia o
deosebeşte calitativ de fişierele de date, deoarece prin aceasta se
asigură independenţa datelor din bază faţă de programele de aplicaţii
şi invers. Posibilitatea modificării structurii la un nivel, fără a afecta
structura celorlalte niveluri este întâlnită sub numele de independenţa
datelor, prezentă sub două forme:
 independenţa fizică de date, adică posibilitatea modificării
structurii bazei de date la nivel intern (cum ar fi utilizarea unor
organizări ale fişierelor sau structuri de stocare diferite, a unor
dispozitive diferite de stocare, modificarea de indexuri sau de
algoritmi hash), fără a fi necesară schimbarea structurii
conceptuale şi rescrierea programelor de prelucrare a datelor.
Asemenea modificări sunt necesare pentru ameliorarea
performanţelor de lucru (viteză de acces, mărimea fişierelor

15
etc.). Autonomia fizică este cea care asigură şi portabilitatea
bazei de date de pe un sistem de calcul pe altul fără modificarea
schemei conceptuale şi a programelor;
 independenţa logică de date se referă la faptul că modificarea
schemei conceptuale a bazei de date (cum ar fi adăugarea sau
eliminarea unor entităţi, atribute sau relaţii) nu necesită şi
modificarea schemei externe sau rescrierea programelor de
aplicaţii.
Este important să se facă distincţie între descrierea bazei de
date şi baza de date însăşi. Descrierea bazei de date constituie
schema bazei de date. Ea este specificată în timpul procesului de
proiectare a bazei de date şi este schimbată rareori. Setul de date din
baza de date se numeşte instanţa bazei de date. Mai multe instanţe
ale bazei de date pot corespunde aceleiaşi scheme a bazei de date.

1.1.3. Depozite de date


Conceptul de depozit de date a apărut la sfârşitul deceniului
8, dar s-a conturat şi dezvoltat în anii ‘90. Conceptul datawarehouse
(depozit de date) este definit de William Inmon (vicepreşedintele
firmei Prism Solution) ca fiind o “colecţie de date destinate
fundamentării deciziei manageriale, colecţie care este tematică,
integrată, plasată într-un context temporal şi permanentă”.
Depozitul de date reprezintă o altă direcţie de dezvoltare şi
evoluţie a bazelor de date. El desemnează o bază de date special
concepută pentru analiza datelor şi suportul deciziilor, prin
consolidarea tuturor datelor întreprinderii.
Deosebirile faţă de o bază de date sunt următoarele:
 scopul pe care îl au datele stocate - acestea nu sunt utilizate în
scop operaţional, ci pentru sarcini analitice, de la identificarea unui
nou segment de piaţă până la brainstorming;
 dacă o bază de date este utilizată pentru prelucrarea tranzacţiilor
on-line, depozitele de date se bazează pe prelucrarea analitică on-
line, o nouă aplicaţie strategică;
 dacă o bază de date înregistrază şi raportează ce s-a întâmplat, un
depozit de date arată şi de ce.

16
Patru elemente determinante caracterizează depozitul de date:
 datele stocate privesc o funcţiune sau un proces din întreprindere
(sunt orientate pe subiect);
 datele sunt integrate şi redefinite penteu a putea fi exploatate;
 informaţiile sunt conservate mai mulţi ani, acesta reprezentând
un atu al depozitelor de date (se asigură continuitatea şi
comparabilitatea);
 datele nu pot fi modificate sau şterse.
Datele organizate în depozite provin din datele preluate din
sistemul operaţional, din datele de arhivă (în perioada de constituire
a depozitului), precum din surse externe (baze de date publice, date
din recensăminte, date de prognoză economică etc.). Utilizarea
depozitelor de date se concretizează în extragerea unor rapoarte (la
cerere sau pe baza unui abonament cu o anumită periodicitate),
extragerea unor date pentru a putea fi utilizate de aplicaţiile de
birotică (programe de calcul tabelar, procesoare de texte, programe
de prezentare etc.), dar mai ales pentru a putea fi utilizate în aplicaţii
specializate de analiză.
Componentele unui depozit de date sunt următoarele [7]:
1. instrumente pentru modelarea datelor, asociate adesea cu
instrumente de tip CASE;
2. o enciclopedie a metadatelor care păstrează informaţiile
relevante despre fiecare dată a depozitului de date (ce reprezintă,
tipul său, unde se găseşte, cum poate fi accesată, formatul său, etc.);
3. baza de date - nucleu care este centrul depozitului şi ia
forma bazelor de date (foarte rar a fişierelor independente);
4. instrumente pentru transpotul datelor, proiectate pentru a
muta copii ale datelor din sistemul operaţional în baza de date;
5. instrumentele pentru extragerea, rafinarea şi
standardizarea datelor, sarcini foarte dificile în condiţiile în care
informaţiile sunt foarte complexe, iar instrumentele de lucru
eterogene;
6. middleware care asigură conectivitatea în cadrul reţelelor
de calculatoare atunci când datele sunt preluate din mai multe baze
17
de date sau o bază de date este distribuită pe mai multe noduri ale
unei reţele;
7. instrumente pentru accesul utilizatorilor la date şi
furnizarea informaţiilor care cuprind instrumente de tipul interfaţă
grafică utilizator (GUI) sau navigatoare (browsere) Web ce permit
utilizatorilor să acceseze şi analizeze informaţiile din depozitul de
date.
Una din preocuparea actuală a producătorilor de instrumente
de construire a depozitelor de date este integrarea celor şapte
categorii de instrumente prezentate mai sus într-un produs
atotcuprinzător, ceea ce unii au reuşit într-o oarecare măsură.4
Din punct de vedere al ariei de întindere, se întâlnesc trei
modele de depozite de date: depozite de întreprindere, data marts şi
depozite virtuale.
Un depozit de întreprindere colectează toate informaţiile
despre subiecte care privesc întreaga organizaţie. El necesită
cheltuieli mai mari pentru modelare şi ani de zile pentru proiectare şi
realizare. El conţine de regulă date detaliate, dar şi date agregate, iar
ca ordin de mărime porneşte de la câţiva gigabytes până la sute de
gigabytes, terabytes sau mai mult.
Un data marts poate fi considerat un subansamblu al unui
depozit de date, mai uşor de construit şi întreţinut şi mai puiţin
scump. El conţine un subset al volumului de date din organizaţie,
specific unui grup de utilizatori. Domeniul este limitat la subiecte
specifice. De exemplu, un data mats pentru marketing limitează
subiectele la clienţi, articole, vânzări. Un depozit virtual este un set
de viziuni (views) asupra bazelor de date operaţionale. Este uşor de
construit, dar necesită capacităţi suplimentare pe serverele de baze de
date. Pentru eficienţa procesării interogărilor, numai unele din
viziunile de agregare pot fi materializate.

4
Fotache, M., Depozitul de date, în Tribuna economică nr.36 /1998,
p.49

18
Baza de date reprezintă "inima" depozitului. În practică, baza
de date nucleu se poate regăsi sub forma fişierelor independente de
date (mai rar), poate fi o bază de date relaţională sau
multidimensională. În prezent se pune tot mai mult accent pe bazele
de date multidimensionale care sunt concepute pentru optimizarea
analizei indicatorilor (cifră de afaceri, marjă…) în raport cu
dimensiunile care le sunt asociate (timp, produs, regiune…). Ele
simplifică gestiunea volumelor mici sau mijlocii de date, sunt
adaptate la rezolvarea unor probleme concrete (fiind utilizate mai
ales pentru analize sofisticate cum ar fi simulările sau predicţiile),
adaptându-se astfel foarte bine în contexul depozitelor de date.
În ceea ce priveşte instrumentele de analiză şi acces la
informaţii, două categorii, instrumentele de interogare şi cele OLAP
se regăsesc pentru a combina accesul liber la informaţii şi funcţiile
de analiză, fiind concepute pentru a răspunde nevoilor foarte diverse
ale utilizatorilor finali. Astfel, anumiţi utilizatori sunt autonomi şi
doresc un acces liber la informaţii fără a se îngriji de căile de acces la
date. Instrumentele de tip interogare răspund nevoilor lor. Aceste
instrumente favorizează formularea de interogări bazându-se pe
logica asamblistă a bazelor de date relaţionale. Ele permit, de
exemplu, obţinerea listei cu numele şi prenumele clienţilor care au
cumpărat un anumit produs în cursul ultimelor trei luni. Alţi
utilizatori exprimă cerinţe de analiză, ceea ce necesită o informaţie
bine pregătită şi foarte organizată. Instrumentele de tip OLAP (On-
Line Analytical Processing) sunt mai bine adaptate exigenţelor lor.
Prelucrarea analitică on-line este un nou instrument la dispoziţia
managerilor şi analiştilor pentru examinarea interactivă şi
manipularea unui volum mare de date analitice sau agregate sub
diverse forme. OLAP înseamnă analiza relaţiilor complexe între mii
şi chiar milioane de date pentru a descoperi tendinţe, modele şi
excepţii. Operaţiile fundamentale în OLAP sunt consolidarea, forajul
(drill down) şi disecarea (slice and dice). Consolidarea înseamnă
agregarea datelor ce poate fi o simplă sumarizare sau o grupare
complexă, implicând date aflate în legătură. Forajul este operaţiunea
inversă şi se referă la afişarea datelor detaliate, pornind de la cele
consolidate. Disecarea porneşte de la capacitatea OLAP de a privi o
bază de date din mai multe perspective. Ea se realizează cel mai

19
adesea de-a lungul unei axe de timp pentru a analiza tendinţele şi a
descoperi modele de evoluţie.
Alţi utilizatori au nevoie de instrumente de data mining care
permit structurarea informaţiei fără preocuparea pentru modul în care
datele sunt puse în corelaţie, prin punerea în funcţiune a unor
mecanisme de inducţie.
Prelucrarea analitică on-line, referită de regulă ca OLAP (On
Line Analytical Processing) răspunde la întrebări pe care managerii
şi le pun la modul concret. Singura trăsătură comună a acestor
întrebări este caracterul lor multidimensional. Există totuşi câteva
tipuri uzuale de întrebări, care pot arunca o lumină asupra
complexităţii instrumentelor care trebuie să furnizeze răspunsuri:
 Raporturi multidimensionale. De exemplu: Care este
contribuţia la vânzările săptămânale totale a produselor informatice
vândute prin magazinele situate în regiunea Moldova între 10 şi 20
septembrie?
 Comparaţii. De exemplu: Care este media abaterii
procentuale de la planul de vânzări în lunile acestui an comparativ cu
anul trecut?
 Clasificări şi profiluri statistice. De exemplu: Care este
volumul vânzărilor şi media profitului pentru primii 20% dintre
distribuitori şi care este contribuţia acestora la totalul vânzărilor pe
trimestrul trecut?
 Agregări libere. De exemplu: Care sunt veniturile realizate
în ultimele patru trimestre de filialele judeţene din regiunea
Moldova?
 Evaluări What-If. De exemplu: În ce măsură ar influenţa
profitul total o creştere cu 10 procente a vânzărilor în judeţele din
Moldova?
Instrumentele de data mining explorează bazele de date şi
extrag din acestea o multitudine de informaţii asupra tendinţelor şi
previziunilor. Câmpul de acţiune al data mining cuprinde nu numai
analiza datelor, ci şi a textelor.
Depozitele de date nu înseamnă totuşi numai avantaje, ci ele
ridică o serie de probleme înre care menţionăm:

20
 dimensiunile extrem de mari la care pot ajunge, de ordinul
gigaocteţilor, ceea ce ridică problema suporturilor de stocare,
ca şi asigurarea unei viteze rezonabile de acces la date;
 costuri de dezvoltare foarte mari şi timp îndelungat necesar
pentru construirea lor;
 dificultatea integrării diferitelor platforme hardware şi
software existente în cadrul întreprinderii.

1.1.4. Proiectarea bazelor de date


Realizarea unei baze de date presupune parcurgerea
următoarelor etape:
* analiza sistemului (domeniului) pentru care se realizează
baza de date, precum şi a cerinţelor informaţionale asociate;
* proiectarea structurii bazei de date (schema conceptuală,
internă şi externă);
* încărcarea datelor în baza de date ;
* exploatarea şi întreţinerea bazei de date [8].
Activităţile desfăşurate în etapa de proiectare depind în mare
măsură de specificul activităţii pentru care se doreşte realizarea unei
baze de date, dar există şi o serie de elemente cu caracter general.
În literatura de specialitate se întâlneşte şi concepţia potrivit
căreia proiectarea unei baze de date este un proces în doi paşi [6]:
* etapa proiectării conceptuale (independentă de SGBD) - ar
consta în analiza sistemului;
* etapa proiectării fizice (în funcţie de un anumit SGBD) -
grupează activităţile de proiectare a structurii, încărcare, exploatare şi
întreţinere a bazei de date.
Obiectivele proiectării bazei de date pot fi grupate în două
categorii:
cerinţe funcţionale:
* rapoartele (situaţiile de ieşire) necesare;
* cererile, interogările care pot apărea;

21
* alte ieşiri care ar putea fi trimise altor sisteme de
prelucrare a datelor;
* toate actualizările necesare;
* toate calculele necesare;
* toate restricţiile sistemului (de exemplu, restricţii
funcţionale sau restricţii de comportament);
* toate sinonimele utilizate pentru un atribut dat;
restricţiile fizice (volumul prelucrărilor şi evaluarea
performanţelor):
* numărul, dimensiunile şi frecvenţa rapoartelor;
* timpul de răspuns pentru fiecare interogare;
* timpul de răspuns pentru fiecare actualizare;
* măsurile de securitate prin restricţionarea accesului.

a. Analiza preliminară şi identificarea cerinţelor


informaţionale
Activitatea de analiză cuprinde trei laturi importante:
* analiza componentelor sistemului şi a legăturilor dintre
acestea (analiza structurală sau statică)modelul structural sau
static al sistemului;
* analiza stărilor sistemului şi a tranziţiilor posibile între
aceste stări (analiza comportamentală sau temporală)modelul
dinamic (temporal) al sistemului;
* analiza cerinţelor informaţionale, respectiv a transformărilor
de date din cadrul sistemului prin care sunt satisfăcute necesităţile de
informare ale organismului studiatmodelul funcţional al
sistemului;
* integrarea celor trei modele în scopul completării şi corelării
lor.
În urma acestei analize se trece la definirea structurii bazei de
date. Importanţa analizei preliminare pentru definirea structurii diferă
după modelul de organizare a bazei de date. Astfel, pentru modelele
ierarhic şi reţea analiza structurală sau statică este foarte importantă,
pentru modelul relaţional toate etapele au cam aceeaşi importanţă,

22
iar pentru modelul OO trebuie acordat maximum de atenţie analizei
temporale şi celei funcţionale.

a.Analiza structurală sau statică


Această etapă are rolul evidenţierii componentelor (obiectelor)
din cadrul sistemului pentru care se proiectează baza de date, precum
şi a legăturilor dintre aceste componente.
Se cunosc în acest sens mai multe tehnici de analiză:
* modelul canonic (James Martin)
* modelul Entitate-Asociere (Peter Chen);
* tehnica SDM - Semantic Data Model (Michael Hammer,
Dennis McLeod) ş.a.
ii. Analiza dinamică (de comportament)
Are drept scop explicarea comportamentului elementelor
sistemului analizat. Construirea modelului dinamic presupune:
* identificarea stărilor în care se află componentele
sistemului;
* identificarea evenimentelor care determină trecerea unei
componente dintr-o stare în alta;
* stabilirea succesiunii evenimentelor şi construirea unei
diagrame care să descrie fluxul acestora (diagramă a stărilor de
tranziţie, a fluxului de evenimente).

iii. Analiza cerinţelor informaţionale (analiza funcţională)


Urmăreşte determinarea transformărilor pe care le suportă
datele în sistemul studiat, în scopul satisfacerii cerinţelor
informaţionale aferente acestui sistem. Transformările de date se
prezintă sub forma unui flux al prelucrărilor, in care nodurile reflectă
procesele şi arcele fluxurile informaţionale.
Construirea modelului funcţional implică o serie de etape:
* identificarea datelor de ieşire şi a celor de intrare;
* construirea de diagrame de flux;
* identificarea restricţiilor pentru anumite date;

23
* precizarea unor criterii de optimizare a prelucrărilor.

b. Integrarea modelelor sistemului


În etapa de proiectare, modelele static şi dinamic sunt
complet independente de SGBD (aplicaţiile) ce urmează a se folosi,
pe când modelul funcţional este orientat preponderent spre acestea.
Rezultatele cercetării din etapele anterioare sunt supuse unui
proces de integrare, în urma căruia se obţine o viziune de ansamblu a
sistemului studiat. Cu această ocazie se testează completitudinea şi
consistenţa modelelor static şi dinamic, anume dacă informaţiile
dispun de coerenţă şi dacă nu au fost omise la analiză unele elemente
informaţionale. În caz de necesitate, în această etapă se pot aduce
completări modelului.
Ca urmare a integrării, dispare independenţa faţă de aplicaţii a
modelelor static şi dinamic, ca şi orientarea spre aplicaţii a modelului
funcţional. Este un avantaj, deoarece pe de o parte orientarea
excesivă spre aplicaţii complică în mod inutil modelul şi-i scad
adaptabilitatea, iar pe de altă parte efectuarea unei analize complet
independente de aplicaţii presupune un mare consum de resurse de
toate tipurile.

c. Proiectarea structurii bazei de date


În urma analizei sistemului, se obţin aşa-numitele modele
semantice sau conceptuale, care sunt independente de instrumentul
care le va pune în aplicare. Este foarte important ca analiza să nu fie
tributară vreunui SGBD, deoarece:
* în cazul schimbării SGBD ar fi nevoie de reproiectarea BD;
* caracteristicile unui anume SGBD pot limita activitatea de
analiză, făcând modelul foarte puţin flexibil;
* dacă utilizatorul final nu cunoaşte nimic despre un anume
SGBD, este imposibil să-şi formuleze cerinţele de informare în mod
adecvat.
Spre deosebire de analiza preliminară, proiectarea structurii
bazei de date impune focalizarea atenţiei asupra unui SGBD. Astfel,

24
modelul conceptual este transpus într-un model al datelor care are
caracteristicile proprii SGBD-ului ales de proiectant.
Proiectarea structurii bazei de date implică următoarele
activităţi [5]:
* alegerea SGBD utilizat pentru implementarea şi exploatarea
BD;
* proiectarea schemei conceptuale a BD;
* proiectarea schemei externe (subschemei) BD;
* proiectarea schemei interne (de memorare) a BD.
Alegerea sistemului de gestiune a bazei de date
În alegerea unui SGBD, se au în vedere mai multe aspecte:
cerinţele utilizatorilor, sub aspectul:
* tipurilor de aplicaţii;
* timpului de răspuns;
* confidenţialităţii şi securităţii datelor;
* uşurinţei în utilizare;
cerinţele de ordin tehnic:
* portabilitatea SGBD;
* portabilitatea datelor şi programelor de aplicaţii;
* condiţiile de încărcare, exploatare şi întreţinere a
BD;
cerinţe de ordin economic:
* încadrarea în bugetul destinat acestui scop;
* timpul necesar pentru implementarea sistemului
(inclusiv pregătirea utilizatorilor).
În urma analizei acestor cerinţe, ca şi a SGBD-urilor
disponibile şi a modului cum ele oferă răspuns la cerinţele
utilizatorilor, se decide care va fi SGBD utilizat.

Proiectarea schemei conceptuale


În accepţiunea cea mai simplă, schema conceptuală
semnifică descrierea datelor şi a relaţiilor dintre acestea. Elaborarea
schemei conceptuale presupune:
* stabilirea colecţiilor de date şi a conţinutului acestora;

25
* determinarea legăturilor dintre colecţiile de date;
* testarea şi revizuirea eventuală a schemei obţinute;
* descrierea schemei conceptuale în maniera proprie SGBD
ales.
În stabilirea colecţiilor de date şi a legăturilor dintre acestea
se porneşte de la entităţile identificate în etapa de analiză. Astfel, în
cazul unui proces economic oarecare, aceste entităţi vor fi
participanţii la procesul în cauză. Spre exemplu, în cazul unei
activităţi comerciale, putem identifica la prima vedere câteva entităţi:
cumpărător, vânzător, marfă etc.
Pentru aceste entităţi se vor preciza atributele sau
proprietăţile care prezintă interes pentru utilizatorii informaţiei,
eventual şi o serie de atribute auxiliare, utilizate pentru a exprima
legături între entităţi.
Aceste entităţi alcătuiesc modelul semantic. Nu este
obligatoriu ca fiecare componentă a acestui model să atragă
constituirea unei colecţii de date distincte. Ąn practică, pentru
îmbunătăţirea performanţelor aplicaţiilor (în special optimizarea
timpului de acces la date), poate opera o sporire, dar şi o reducere a
numărului de colecţii de date proiectate iniţial.
În realizarea colecţiilor de date se poate porni şi de la
documentele de ieşire (cele care conţin informaţiile de care are
nevoie utilizatorul), caz în care toate atributele identificate concură la
alcătuirea unui dicţionar de date şi urmează a fi grupate în funcţie de
anumite legături identificabile între atribute.
Modul de reprezentare a legăturilor dintre colecţiile de date
identificate diferă în funcţie de modelul datelor pe care-l implică
SGBD utilizat. Spre exemplu, pentru modelele ierarhic şi reţea se
utilizează pointeri, iar pentru modelul relaţional, chei externe
(străine).
Testarea schemei conceptuale presupune verificarea
corectitudinii (a modului în care aceasta ilustrează cerinţele
utilizatorilor) şi consistenţei acesteia (a corespondenţei dintre
legăturile determinate şi lumea reală). De asemenea, trebuie ca
redundanţa datelor să se situeze la un nivel minim. Dacă în această

26
etapă se identifică erori, se poate reveni la etapa de proiectare şi
uneori chiar la cea de analiză a sistemului.
În ceea ce priveşte descrierea schemei conceptuale, aceasta
comportă transpunerea schemei în limbajul de manipulare a datelor
specific SGBD ales. Rezultatul acestui proces îl constituie schema
(în accepţiune CODASYL5) bazei de date.

Proiectarea schemei externe


Prin schemă externă se înţelege forma sub care un utilizator
oarecare percepe schema conceptuală. Prin programele de aplicaţii se
oferă fiecărui utilizator o viziune oarecum "compartimentată" a BD,
în funcţie de necesităţile sale specifice (există aici şi puternice raţiuni
de securitate şi confidenţialitate a datelor). Acest mod de acces
restrictiv la baza de date se materializează prin aşa-numitele view-uri,
ca şi prin drepturi de acces, acolo unde SGBD-ul face posibil acest
lucru.
În general, elementele care compun schema externă sunt
similare elementelor care compun schema conceptuală. Totuşi,
accepţiunea CODASYL defineşte schema externă (subschema) ca pe
o parte componentă a schemei conceptuale, dar care poate înregistra
diferenţe în ceea ce priveşte alcătuirea, faţă de schema conceptuală.

Proiectarea schemei interne


Schema internă, numită de unii autori şi schemă de
memorare, se referă explicit la modul de memorare a datelor pe
suport (purtătorul de informaţie). Acest mod de memorare este
specific SGBD utilizat. Din punctul de vedere al utilizatorului,
această schemă nu trebuie să fie vizibilă.

5
abreviere de la "Conference on Data Systems Languages"

27
d. Încărcarea datelor în baza de date
Aceasta este o etapă inerentă proiectării bazei de date, şi
constă în specificarea conţinutului acesteia (a datelor pe care le va
memora). Deşi activitatea nu este pretenţioasă, ea este destul de
delicată, dat fiind volumul mare de date care trebuie vehiculate.
Un detaliu important este acela al încărcării BD numai cu
date corecte, scop în care sunt necesare proceduri de validare şi
corectare a datelor.
Sursele de date pot consta îndocumente primare,colecţii de
date aflate deja pe suporturi (de exemplu, sisteme de fişiere), date
preluate direct, fără intervenţia documentelor (prin schimb electronic
de date).
Nu trebuie să se exagereze în direcţia procedurilor de
validare utilizate, deoarece productivitatea introducerii datelor poate
scădea în mod drastic.

e. Exploatarea şi întreţinerea bazei de date


Exploatarea bazei de date este de resortul utilizatorilor finali
şi implică utilizarea de către aceştia a datelor din baza de date, în
scopul satisfacerii cerinţelor informaţionale. Pentru aceasta, SGBD-
urile dispun de limbaje de manipulare a datelor, ca şi de alte
instrumente specializate (mai ales cele din categoria generatoarelor).
Întreţinerea bazei de date implică pe de o parte operaţii de
actualizare (modificare a conţinutului), dar şi de reproiectare a
structurii (aceasta din urmă fiind rezervată administratorului bazei de
date).
Ca oricare alt sistem informatic, o bază de date poate ajunge
într-o fază de declin, când întreţinerea sa devine nerentabilă. În acest
caz se poate decide proiectarea unei noi baze de date.

28
1.2 Modele conceptuale de structurare şi
organizare a datelor în baze de date
Pentru descrierea structurii datelor unei baze de date şi a
relaţiilor dintre acestea sunt folosite procedee formale, concretizate
în modele conceptuale. Acestea se particularizează prin terminologia
utilizată şi prin relaţiile dintre date.

1.2.1 Tipuri de relaţii şi structuri de reprezentare a


relaţiilor în cadrul unei baze de date
Entităţile aceluiaşi sistem informaţional sunt rareori izolate
unele de altele, ele antrenând, cel mai adesea, legături sau relaţii.
Între datele diverselor tipuri de entităţi pot exista două categorii de
legături sau relaţii. Prima priveşte relaţiile dintre datele aparţinătoare
aceleiaşi entităţi, iar a doua se referă la relaţiile dintre mai multe
entităţi care pot fi şi de tipuri diferite.
La rândul lor relaţiile pot fi binare şi n-are.
Relaţiile binare presupun existenţa unui domeniu, a unui
codomeniu şi a unei corespondenţe între entităţile acestora. În
practica bazelor de date se utilizează patru tipuri de relaţii binare:
 1-1 (una-la-una) în care unei realizări din domeniu îi
corespunde o realizare şi numai una din codomeniu.
(Figura nr.1.4 )

X1 Y1
X2 Y2
.
.
.
.

Xn Yn

Domeniu Codomeniu

Fig. 1.4 Relaţia de tip 1-1


 1-n (una la mai multe) în care unei realizări din domeniu
îi corespunde 0, una sau mai multe realizări din
codomeniu. (figura nr. 1.5)

29
X1 Y1
Y2
.Y3.

Y4
X2 Y5

Domeniu Codomeniu

Fig. 1.5 Relaţii de tip 1-n

 n-1 (mai-multe-la-una) în care mai multe înregistrări din


domeniu corespund unei realizări din codomeniu.
(Figura nr.1.6)

X1

X2 Y

X3

Domeniu Codomeniu

Fig. 1.6. Relaţia de tip n-1

 n-m (mai-multe-la-mai-multe) în care unei realizări din


domeniu îi corespund 0, una sau mai multe realizări din
codomeniu, iar unei realizări din codomeniu îi corespund
0, una sau mai multe realizări din domeniu (figura nr.
1.7):

X1
Y1
Y2
.Y3.

X2 Y4

Domeniu Codomeniu

Fig. 1.7.Relaţia n-m

30
Relaţiile n-are presupun existenţa unei interdependenţe
logice între realizările unei mulţimi de caracteristici definită pe o
mulţime de tupluri.
Mecanismul de selecţie şi de identificare a componentelor
unei baze de date presupune existenţa unei structuri de date.
Concret o structură de date reprezintă o colecţie de date între care s-
au stabilit anumite relaţii. Structurile de date care au aceeaşi
organizare şi sunt supuse prelucrărilor cu un grup de operatori de
bază cu o semantică predefinită formează un anumit tip de structură.
Principalele tipuri de structuri sunt [14] punctuală, liniară,
arborescentă, reţea, relaţională. Dintre acestea sunt considerate de
bază structurile liniară şi arborescentă. Prin combinarea lor în funcţie
de opţiunile utilizatorilor, pot fi construite şi alte structuri cu grade
diferite de complexitate.

1.2.2 Modele de organizare a datelor în bazele de date

Un model de date este un ansamblu de instrumente


conceptuale care permit descrierea datelor, a relaţiilor dintre ele, a
semanticii lor, ca şi a restricţiilor la care sunt supuse acestea. Se pot
clasifica în: modele orientate pe obiect, modele orientate pe
înregistrare şi modele fizice. Cum ne vom ocupa doar de descrierea
nivelurilor conceptual şi extern, vom trata primele două categorii de
modele.
Modelele de date se caracterizează prin flexibilitate şi
explicitate în reprezentarea structurilor de date şi a restricţiilor pe
care trebuie să le respecte acestea. Cele mai cunoscute sunt: modelul
entităţi-asociaţii, modelul semantic, modelul funcţional şi modelul
orientat pe obiecte.
Modelul entităţi-asociaţii are la bază percepţia lumii reale
sub forma unei colecţii de obiecte, denumite entităţi, unite prin
intermediul unor asociaţii. O entitate este un obiect care poate fi
diferenţiat de alte obiecte printr-un ansamblu de atribute care permit
descrierea precisă a acestuia. O asociaţie reuneşte două sau mai

31
multe entităţi. De exemplu, atributele Număr şi Disponibil descriu
entitatea Cont la bancă. Atributele Nume, Adresă, etc. descriu
entitatea Client. Există o asociaţie care leagă un client de fiecare din
conturile pe care le are deschise la banca respectivă. Ansamblul
entităţilor de acelaşi tip formează o clasă de entităţi, iar ansamblul
asociaţiilor de acelaşi gen reprezintă o clasă de asociaţii.
În reprezentarea unei structuri de baze de date cu ajutorul
modelului E-R se realizează o diagramă, care utilizează simbolurile:
* dreptunghi, pentru clase de entităţi,
* elipse, pentru atribute,
* romburi, pentru clase de asociaţii,
* linii, pentru a lega atribute de clase de entităţi şi
clasele de entităţi de clasele de asociaţii.
Exemplu

Adresa Data
Furnizor Localitate Numar Valoare

FURNIZORI Cumparare FACTURI-PRIMITE

Fig. nr. 1.8. Modelul Entitate-Asociaţie

Modelul de date orientat spre obiecte extinde definiţia


unei entităţi pentru a include nu numai atributele care descriu starea
obiectului, ci şi acţiunile asociate acestuia, respectiv
comportamentul. Se spune că obiectul încapsulează atât starea, cât şi
comportamentul.
Modelul de date orientat pe obiecte reprezintă un model
logic de date care conţine semantica obiectelor, acceptată în
programarea orientată pe obiecte.
Modelarea orientată obiect devine din ce în ce mai populară
datorită abilităţii de a reprezenta relaţii complexe ca şi de a
reprezenta datele şi procesarea acestora cu ajutorul unor notaţii
consistente.

32
Un model al datelor este o abstractizare a lumii reale ce
permite "tratarea" complexităţii inerente în cazul problemelor din
lumea reală prin concentrarea atenţiei asupra caracteristicilor
esenţiale şi interesante ale datelor de care are nevoie o organizaţie.
Un model orientat obiect este construit în jurul "obiectelor" tot aşa
cum modelul E-A are la bază entităţile. Totuşi un obiect încapsulează
atât datele cât şi comportamentul, ceea ce permite utilizarea unei
abordări orientate obiect nu doar pentru modelarea datelor, ci şi
pentru modelarea proceselor. Pentru a modela cu stricteţe o aplicaţie
din lumea reală trebuie să se modeleze atât datele, cât şi procesele ce
acţionează asupra datelor. Modelarea orientată obiect asigură un
mediu puternic pentru dezvoltarea unor sisteme complexe, datorită
posibilităţii de captare a datelor şi a proceselor şi datorită mai ales,
moştenirii şi reutilizării codului.
Ciclul de viaţă al proiectării orientate obiect constă din
reprezentarea progresivă a obiectelor în cadrul a trei faze: analiză,
proiectare şi implementare. Acest ciclu de viaţă este similar cu cel al
dezvoltării sistemelor. În primele etape, modelul pe care îl creăm este
abstract, concentrându-se asupra calităţii externe a sistemului. Pe
măsură ce modelul evoluează, acesta devine din ce în ce mai detaliat,
atenţia deplasându-se spre cum va fi construit sistemul şi mai ales,
cum va funcţiona. Accentul în modelare trebuie pus pe analiză şi
proiectare, în special pe problemele conceptuale front-end, faţă de
problemele de implementare back-end ce restricţionează opţiunile de
proiectare6.
În etapa de analiză este dezvoltat un model al aplicaţiei din
lumea reală ce reprezintă proprietăţile sale importante. Modelul
abstractizează concepte din domeniul aplicaţiei şi descrie ce anume
trebuie să realizeze sistemul mai degrabă decât cum va fi realizat
acest lucru. Modelul specifică în special comportamentul funcţional
al sistemului, independent de problemele legate de mediul în care va
fi implementat în final. Trebuie să se aloce suficient timp pentru
înţelegerea clară a tuturor cerinţelor problemei în discuţie. Modelul

6
Rumbaugh, J., Blaha, M., Premerlani, W., Eddy, F., Lorensen, W.,
Object-Oriented Modelling and Design, Pretice-Hall, 1991

33
de analiză captează aceste cerinţe în mod precis, concis şi cu
acurateţe.
În faza de proiectare orientată obiect se defineşte cum va fi
realizat modelul de analiză orientată obiect în cadrul mediului de
implementare. Există trei motive pentru utilizarea proiectării
orientate obiect:
1. Modelul de analiză nu este suficient de formal pentru a fi
implementat direct într-un limbaj de programare. Pentru a ne
deplasa către codul sursă trebuie să rafinăm mai întâi obiectele
prin adoptarea unei decizii privind operatorii ce vor fi asiguraţi
de un obiect, cum ar trebui să arate comunicaţia între obiecte, ce
mesaje vor fi transmise etc.
2. Sistemul actual trebuie să fie adaptat mediului în care sistemul
va fi implementat. Pentru a realiza acest lucru, modelul de
analiză trebuie să fie transformat într-un model conceptual de
proiectare, luând în considerare diferiţi factori cum ar fi:
cerinţele de performanţă, cerinţele de timp real şi concurenţă,
hardware-ul şi software-ul implicat, SGBD-ul şi limbajele de
programare ce vor fi adoptate etc.
3. Rezultatele etapei de analiză pot fi validate cu ajutorul proiectării
orientate obiect. În acestă etapă putem verifica dacă rezultatele
furnizate de analiză sunt adecvate pentru construirea sistemului
şi dacă este necesar să se efectueze modificări asupra modelului
de analiză.
Pentru dezvoltarea modelului de proiectare trebuie să fie
identificate şi investigate consecinţele pe care le va avea mediul de
implementare asupra proiectării. Toate deciziile de proiectare
strategice (cum va fi implementat SGBD-ul, cum vor fi asigurate
comunicaţiile între procese şi tratarea erorilor, care componente vor
fi reutilizate) vor fi adoptate şi vor fi apoi încorporate într-un prim
model de proiectare adaptat mediului de dezvoltare. În final, modelul
este formalizat pentru a descrie modul în care obiectele
interacţionează unele cu altele pentru fiecare scenariu sau caz.
Rumbaugh separă activitatea de proiectare în două etape:
proiectarea sistemului şi proiectarea obiectelor.

34
La proiectarea sistemulul trebuie propusă o arhitectură
globală a sistemului care îl organizează în componente, numite
subsisteme şi asigură contextul necesar adoptării deciziilor cum ar fi
identificarea concurenţei, alocarea subsistemelor pe procesoare şi
task-uri, asigurarea accesului la resursele globale, selectarea
modalităţilor de implementare a controlului software etc.
În etapa de proiectare a obiectelor va fi construit un model
de proiectare prin adăugarea unor detalii de implementare cum ar fi:
restructurarea claselor pentru eficienţă, structurile interne de date şi
algoritmii pentru implementarea fiecărei clase, implementarea
controlului şi a asociaţiilor (legăturilor), precum şi împărţirea în
module fizice în concordanţă cu strategia adoptată în timpul
proiectării sistemului. Clasele de obiecte specifice domeniului
aplicaţiei din cadrul modelului de analiză vor fi îmbogăţite cu o serie
de elemente specifice procedurilor de calcul în scopul optimizării
performanţelor.
Etapa de proiectare este urmată de o etapă de implementare.
În această fază, proiectul este implementat cu ajutorul unui limbaj de
programare sau a unui SGBD. Translatarea proiectului în cod sursă
este un proces relativ uşor datorită faptului că modelul de proiectare
încorporează deja o serie de aspecte ale limbajului de programare şi
SGBD-ului ales.
Unele din avantajele des citate în favoarea orientării spre
obiecte sunt:
 Definiţia unui sistem prin intermediul obiectelor facilitează
construcţia de componente software care seamănă
îndeaproape cu domeniul de aplicaţie, contribuind astfel la
proiectarea şi înţelegerea sistemelor;
 Datorită încapsulării şi ascunderii informaţiilor,
întrebuinţarea obiectelor şi mesajelor încurajează proiectarea
modulară;
 Implementarea unui obiect nu depinde de structura internă a
acestuia, ci de modul cum acesta răspunde la mesaje;
 Întrebuinţarea claselor şi a moştenirii promovează
dezvoltarea de componente reutilizabile şi extensibile în

35
contrucţia de noi sisteme sau pentru actualizarea celor
existente.
O bază de date orientată spre obiecte este o colecţie de
obiecte persistente şi partajabile care sunt definite de un model de
date orientat pe obiecte. Un sistem SGBD orientat pe obiecte este
administratorul unei baze de date orientată pe obiecte.
Aspecte structurale ale modelului de date orientat pe
obiecte:
* Obiectele sunt entităţi de bază care încorporează structuri de
date şi operaţii;
* Fiecare obiect are un identificator unic, atribuit de sistem;
* Clasele descriu tipuri generice de obiecte;
* Conceptul de clasă este strâns legat de conceptul de
moştenire;
* Clasele formează ierarhii de clase;
* Definirea unei clase este mecanismul de specificare a
schemei bazei de date;
* Schema bazei de date se poate extinde prin definirea de noi
clase;
* Definirea unei clase poate include atribute de tipuri definite
de utilizator (imagine, sunet);
* Se admit referiri recursive.
Operaţii ale modelului de date orientat pe obiecte:
* Obiectele comunică prin mesaje;
* Un mesaj poate fi trimis instanţelor din mai multe clase;
* Metodele pot fi definite, şterse sau modificate;
* Clasele pot fi definite, şterse sau modificate;
* Instanţa unei clase poate fi actualizată prin metode ce
modifică valorile variabilelor propriei instanţe.
Reguli de integritate ale modelului de date orientat pe
obiecte:
* Obiectele trebuie să respecte caracteristicile clasei din care
fac parte;
* Obiectele sunt încapsulate;
* Un obiect nu există fără să aibă un identificator; dacă
obiectul este şters, se şterge şi identificatorul;

36
* Restricţia de integritate cunoscută de la modelul relaţional
nu este implementată (nu există posibilitatea de ştergere în cascadă).

Modelele orientate pe înregistrare sunt utilizate pentru


reprezentarea atât a structurii logice a bazei de date, cât şi a
conţinutului acesteia. Un dezavantaj principal este absenţa
instrumentelor prin care să se specifice restricţiile datelor. Cele mai
utilizate sunt: modelul relaţional, modelul ierarhic şi modelul reţea.
Modelul relaţional reprezintă datele şi legăturile dintre ele
sub forma unor tabele, în care liniile şi coloanele reprezintă un
element distinct al bazei de date. Exemplu –

FURNIZORI FACTURI-PRIMITE
Furnizor Adresa Localita Furnizor Număr Data Valoar
te e
Alfa SRL Unirii 2 Iaşi Alfa SRL 12540 12/02/07 1259.8
Beta SA Apelor 5 Bacău Beta SA 14870 14/02/07 3265
Gama SA Viilor 56 Iaşi Alfa SRL 24550 22/02/07 2987.5
Gama SA 18960 28/02/07 5420

Fig. nr.1.9. Modelul relaţional

Modelul ierarhic reprezintă structura datelor sub forma unui


arbore, alcătuit din mai multe noduri; unele sunt noduri-părinte,
altele sunt noduri-copil. Partea superioară este rădăcina. Un fiu nu
poate exista independent de tatăl său, iar orice fiu poate fi la rândul
său tată, deci poate avea unul sau mai mulţi fii.
Primul model utilizat pentru organizarea datelor în baze de
date, modelul ierarhic se bazează deci pe structura arborescentă şi pe
relaţiile 1-1 şi 1-n, prezentându-se sub forma unui arbore, în care se
regăsesc pe un prim nivel – rădăcina (nodul-părinte), iar pe nivele
următoare diferite elemente subordonate (noduri-copil). Nodul-
părinte poate avea subordonate mai multe noduri-copil în timp ce un
nod-copil poate avea un singur părinte. Rezultă că relaţia părinte-
copil poate fi de tip 1-n, iar relaţia copil părinte poate fi doar de tip 1-
1.

37
Acest model asigură organizarea datelor pe orice tip de
suport magnetic şi reducerea timpului de acces la înregistrări. El are
însă o serie de limite în special în operaţiile de actualizare când
adăugarea de noi înregistrări, cu excepţia celor din colecţia de date
rădăcină, se poate efectua numai cu specificarea colecţiilor de date
superioare, iar ştergerea unei înregistrări duce la eliminarea fizică a
tuturor înregistrărilor subordonate.

Fig. nr.1.10. Modelul ierarhic


În figura nr.1.10 este prezentat un exemplu de model ierarhic:

Modelul reţea este o dezvoltare a modelului ierarhic.


Înregistrările sunt privite în baza de date ca o colecţie de grafuri.
Modelul reţea elimină redundanţele specifice modelului
ierarhic şi se bazează pe structurile reţea şi pe relaţiile de tip 1-1, 1-n
şi n-m. Caracteristica principală a acestui model este că acceptă ca
orice colecţie de date să se situeze pe nivelul 1, astfel fiind permis
accesul direct la realizările colecţiilor superioare (operaţie imposibilă
în modelul ierarhic).

38
În plus, prin acest model este permisă reprezentarea unică a
realizărilor în baza de date.
Legăturile fizice pe suport sunt asigurate prin intermediul
unor caracteristici care exprimă pointer-ul (adresa de pe suport) a
realizării superioare sau a realizării subordonate. Astfel reţeaua este
un graf orientat alcătuit din noduri conectate prin arce. Nodurile
corespund tipurilor de înregistrare, iar arcele pointerilor. În felul
acesta este permisă introducerea înregistrărilor artificiale pentru a
reprezenta legăturile n-are (n>2)

FACTURI-EMISE

Factura 1 Factura 2 Factura 3

Produs A Produs B Produs C Produs D Produs E Produs F

Fig. nr. 1.11. Modelul reţea


După cum se observă din figura nr. 1.12, modelul admite
relaţii de tip n-m, ceea ce are ca efect reducerea redundanţei datelor.
Modelele ierarhic şi reţea nu permit realizarea unei
independenţe logice satisfăcătoare între date şi programe, deoarece
relaţiile dintre date există şi sunt referite în programele de aplicaţii.

Noţiunile de bază ale Modelul ENTITATE– RELAŢII

Definirea entităţii este în acelaşi timp uşoară şi dificilă,


existând o multitudine de opinii. Cel mai simplu, o entitate este un
obiect care poate fi delimitat clar de alte obiecte. Sau: ceva ce are o
existenţă distinctă, concretă sau imaginară.
Pentru o organizaţie, o entitate reprezintă un obiect al
sistemului informaţional, care are existenţă proprie, prezintă
importanţă pentru gestiunea organizaţiei şi este înzestrat cu o serie de
proprietăţi. O entitate se caracterizează prin:

39
* existenţă proprie;
* poate fi abstractă sau concretă;
* aparţine unei familii de obiecte de aceiaşi natură,
numită clasă de entităţi;
* fiecare entitate este identificabilă şi caracterizată
fără ambiguitate.
Clasa de entităţi este deci un ansamblu de entităţi care au
proprietăţi comune. Gruparea entităţilor în clase este arbitrară, iar
clasele nu sunt întotdeauna disjuncte, ceea ce înseamnă că este
posibil ca o entitate care este încadrată într-o clasă să poată face parte
simultan şi din altă clasă de entităţi.
Orice entitate poate fi caracterizată printr-un ansamblu de
atribute. Un atribut este o proprietate comună tuturor entităţilor dintr-
o anumită clasă.
O entitate este legată cu una sau mai multe entităţi dintr-o
altă clasă prin intermediul unei asociaţii. O asociaţie este o relaţie
stabilită între două sau mai multe entităţi care, deşi nu are o existenţă
proprie, poate fi purtătoarea unor proprietăţi. Mai multe asociaţii cu
aceleaşi proprietăţi se reunesc în clase de asociaţii. O clasă de
asociaţii este o relaţie definită pe una sau mai multe clase de entităţi.
Pentru denumirea unei clase de asociaţii se alege un substantiv care
reflectă logica legăturii dintre cele două clase de entităţi.
Funcţia care atrage o entitate într-o asociaţie se numeşte rol.
Clarificarea rolului fiecărei clase de entităţi este esenţială în
proiectarea bazei de date.
Pentru reprezentarea grafică a unei diagrame entităţi-
asociaţii, în literatura de specialitate au fost propuse mai multe
soluţii. Una din cele mai utilizate este prezentată mai în figura nr.
2.13.

În caracterizarea oricărei clase de asociaţii se au în vedere


trei elemente: dimensiunea, cardinalitatea şi caracterul obligatoriu
sau facultativ al asociaţiei.
Dimensiunea (sau ordinul) unei asociaţii reprezintă
numărul claselor de entităţi implicate într-o clasă de asociaţii. Din
acest punct de vedere, există:
* asociaţii unare, care se stabilesc între entităţile
aceleiaşi clase;
40
* relaţii binare, prin care se stabilesc legături între
entităţi din două clase diferite;
* relaţii ternare, în care apar 3 clase de entităţi;
* relaţii de ordinul n, care stabilesc relaţii între n
clase de entităţi.
Cele mai simple, dar şi cele mai utilizate sunt relaţiile binare.
În practică apar deseori şi relaţii ternare.

Fig. nr. 1.12. Diagrama entitate-relaţie

Cardinalitatea defineşte numărul de entităţi dintr-o clasă de


care poate fi legată o entitate dată prin intermediul unei asociaţii.
Considerând cazul unei asociaţii binare, există patru cardinalităţi
posibile
- cardinalitatea de tip 1 la 1, în care unei entităţi din clasa
X îi este asociată o singură entitate din clasa Y şi reciproc. Pentru
exemplul clasei de asociaţii CUMPĂRARE, ar avea o astfel de
cardinalitate dacă fiecare factură ar fi întocmită de un singur furnizor

41
(perfect adevărat) şi fiecare furnizor ar întocmi o singură factură
(nerealist).
- cardinalitatea de tip 1 la n, în care o entitate din clasa X
poate fi asociată la n entităţi din clasa Y, în timp ce fiecare entitate
din clasa Y poate fi asociată unei singure entităţi din clasa X. Clasa
de asociaţii VÂNZARE are o astfel de cardinalitate, pentru că pentru
fiecare client se pot întocmi mai multe facturi, dar o factură are un
singur client (figura 1.17).
Observaţie: Într-o diagramă entităţi-asociaţii, cardinalitatea este
reprezentată prin indicarea, în dreptul clasei de entităţi a numărului
maxim de asociaţii la care poate participa o entitate din clasa
respectivă. Un client poate fi asociat la n facturi emise, dar o factură
poate fi asociată unui singur client. De remarcat că reprezentarea
grafică cardinalităţii se face invers faţă de modul de citire al acesteia.
- cardinalitatea de tip n la 1, în care o entitate din clasa X
este asociată unei singure entităţi din clasa Y, iar orice entitate din Y
poate fi asociată la n entităţi din X. Este inversa cardinalităţii de tip 1
la n.
- cardinalitatea de tip n la n, în care orice entitate din X
poate fi asociată mai multor entităţi din Y, iar o entitate din Y este
asociabilă mai multor entităţi din X.

Caracterul obligatoriu sau facultativ este legat de


conceptul de restricţie de dependenţă. Dacă existenţa entităţii A din
clasa X depinde de existenţa entităţii B din clasa Y se spune că A
este dependentă de B. În acest caz, ştergerea entităţii B din BD atrage
după sine ştergerea şi a entităţii A. Entitatea B este numită entitate
dominantă.
În lucrările de specialitate, restricţia de dependenţă dintre
două clase de entităţi se exprimă prin sintagma “clase de asociaţii
obligatorii sau faculative”.

42
1.3 Sisteme de gestiune a bazelor de date
SGBD-urile reprezintă un software complex care
realizează/asigură independenţa, relaţiile logice între date şi o
redundanţă minimă a acestora. Ele trebuie să permită dezvoltarea
rapidă şi la un cost avantajos a programelor de aplicaţii pentru
exploatarea datelor dintr-o structură complexă, precum şi accesul
rapid la date şi asigurarea securităţii lor.
SGBD-ul reprezintă un sistem de programe care permite
utilizatorului definirea, crearea şi întreţinerea bazei de date şi accesul
controlat la aceasta.
Sistemul SGBD constă în elemente de software care
interacţionează cu programele aplicaţie ale utilizatorului şi cu baza
de date. De obicei, un SGBD oferă următoarele facilităţi
1. Permite utilizatorilor să definească baza de date, de obicei printr-
un limbaj de definire a datelor (DDL). Limbajul DDL permite
utilizatorilor specificarea tipurilor de date şi a structurilor, în
timp ce constrângerile asupra datelor sunt stocate în baza de date
2. Permite utilizatorilor să insereze, să reactualizeze, să şteargă şi să
extragă date din baza de date, de obicei printr-un limbaj de
manipulare a datelor (DML). Faptul că există un depozit central
al tuturor datelor şi descrierilor acestora permite limbajului DML
să ofere o facilitate de interogare generală a acestor date,
denumită limbaj de interogare. Existenţa unui limbaj de
interogare elimină dificultăţile sistemelor bazate pe fişiere unde
utilizatorul este constrâns să lucreze cu un set fix de interogări
pentru a evita proliferarea de programe care creează probleme
majore privind gestionarea acestora. Există două tipuri de
limbaje DML - procedurale şi neprocedurale care se deosebesc în
funcţie de operaţiile de extragere. De obicei, cele procedurale
tratează baza de date înregistrare cu înregistrare, în timp ce cele
neprocedurale operează asupra unor seturi de înregistrări. În
consecinţă, limbajele procedurale specifică cum se obţine

43
rezultatul unei instrucţiuni DML, iar cele neprocedurale descriu
numai ce date vor fi obţinute. Cel mai obişnuit tip de limbaj
neprocedural este limbajul structurat de interogare (SQL) care
reprezintă acum atât limbajul standard, cât şi cel de facto pentru
SGBD relaţionale.
3. Oferă accesul controlat la baza de date. De exemplu, poate
furniza
- un sistem de securitate care previne accesarea bazei de date
de către utilizatori neautorizaţi
- un sistem de integritate care menţine concordanţa datelor
stocate
- un sistem de control al concurenţei care permite accesul
partajat la baza de date
- un sistem de control al refacerii care restaurează baza de date
într-o stare precedentă concordantă ca urmare a unei
defecţiuni în hardware sau software
- un catalog accesibil utilizatorilor care conţine descrieri ale
datelor din baza de date
SGBD-ul prezintă şi o facilitate cunoscută sub
denumirea de mecanism de vizualizare care permite fiecărui
utilizator să-şi definească propriul mod de vizualizare a bazei de
date. Limbajul DML permite definirea de moduri de vizualizare în
care acestea reprezintă un subset al bazei de date.
Avantajele SGBD
- controlul redundanţei datelor
- coerenţa datelor
- mai multe informaţii de la aceeaşi cantitate de date
- partajarea datelor
- integritatea crescută a datelor
- securitatea crescută
- aplicarea standardelor
- economia de scală
- echilibru între cerinţe aflate în conflict
- îmbunătăţirea accesibilităţii datelor şi capacităţii de răspuns

44
- productivitatea crescută
- capacitatea de întreţinere îmbunătăţită, prin independenţa de date
- concurenţa îmbunătăţită
- îmbunătăţirea serviciilor de salvare de siguranţă şi refacere

1.3.1 Arhitectura sistemelor de gestiune a


bazelor de date
Teoria şi practica SGBD-urilor oferă diferite arhitecturi
diferenţiate în funcţie de componentele, limbajele utilizate şi
posibilităţile de prelucrare a datelor, existând totuşi preocupări de
standardizare a cestora.
În general, intră în arhitectura unui SGBD cel puţin 5 clase
de module:
 programe de gestiune a bazei de date;
 limbajul de definire/descriere a datelor (LDD);
 limbajul de manipulare a datelor (LMD);
 utilitare de întreţinere a bazei de date;
 componente de control a programelor de aplicaţii.
Programele de gestiune a bazelor de date (PGBD)
Această clasă de module realizează accesul fizic la date ca urmare a
unei comenzi primite printr-un program de aplicaţii sau interactiv
prin intermediul ecranului.
Limbajul de descriere a datelor (LDD) permite traducerea
(compilare sau interpretare, după caz) şi descrierea naturii datelor şi
a legăturilor lor logice fie la nivelul global (sub forma schemei
conceptuale), fie la nivelul specific fiecărei aplicaţii (sub forma
schemei externe sau sub-schemă).
Limbajul de manipulare a datelor (LMD) permite
gestionarea şi actualizarea datelor dintr-o bază de date.
Utilitare de întreţinere a bazei de date
Un SGBD trebuie să ofere o gamă variată de programe
utilitare care să permită gestionarea de către un operator a bazei de

45
date. Utilitarele variază de la un sistem la altul şi depind de
complexitatea SGBD-ului. Acestea pot efectua următoarele operaţii:
 crearea versiunii iniţiale a bazei de date şi încărcarea
acesteia folosindu-se fie o copie creată anterior, fie date
neorganizate;
 crearea şi actualizarea jurnalelor tranzacţiilor realizate
asupra bazelor de date. Acest utilitar controlează fiecare
tranzacţie reţinând în jurnal următoarele informaţii:
 identificatorii de program, de utilizator şi
terminalul folosit;
 determinarea “timpului-maşină”;
 structura şi conţinutul bazei înainte şi după
tranzacţie;
 natura tranzacţiei (sistem sau aplicaţie);
 înscrierea datelor transmise tampoanelor SGBD-
ului în jurnalul sistemului;
 reorganizarea bazei de date pentru recuperarea spaţiului
vid;
 reorganizarea structurii fizice şi logice după tranzacţie;
 restructurarea bazei de date după un incident logic sau
fizic, cu refacerea stării existente anterior acestuia.
Restaurarea este determinată de existenta în cadrul
SGBD-urilor a aşa-numitelor puncte-de-reluare
(Checkpoint) [7] în cazul unor întreruperi în exploatarea
unei baze de date, reluarea exploatării se va face nu de la
începutul bazei de date, ci de la Checkpointul precedent;
 diverse statistici ce permit cunoaşterea activităţii şi
utilizării bazei de date;
 actualizarea schemei şi sub-schemei fără rescrierea şi
compilarea lor;
 detectarea “spărgătorilor” regulilor de integritate
definite, fără a fi necesară intrarea în baza de date;
 realizarea unei copii permanente a bazei de date în
scopuri de securitate.
Componentele de control

46
Acestea constituie mijloace de prevenire şi corectare a
anumitor erori ce pot să apară în condiţii “multi-utilizator”.
Administratorul
Utilizatori
BD

Programede
Structura BD aplica¡ii

LDD LMD

PGBD

Ut. între¡inere Comp. control


SGBD

Baza
de
date

Fig. 1.13. Structura generală a unui SGBD


Integritatea bazei de date poate fi privită din mai multe
puncte de vedere:
 dacă datele trebuie să fie modificate printr-o aplicaţie,
atunci secvenţa completă a acestei operaţii trebuie
protejată de orice propagare sau interferenţă cu alte
aplicaţii;
 dacă o aplicaţie efectuează doar o citire a datelor, atunci
execuţia acesteia trebuie să interzică modificarea datelor
astfel încât să se evite riscul invalidării datelor citite în
prealabil. Se asigură astfel blocarea actualizării în timpul
operaţiei de citire;
 în cazul în care cel puţin două aplicaţii accesează
concurent aceeaşi dată în cadrul unei operaţii de
actualizare, atunci integritatea bazei de date este
“ameninţată”.

47
Schematic structura unui SGBD pate fi prezentată ca în
figura 2.14 .

1.3.2 Funcţiile unui SGBD


Orice SGBD trebuie să îndeplinească următoarele funcţii: de
descriere, de manipulare, utilizare.
Funcţia de descriere permite definirea structurii bazei cu
ajutorul limbajului special LDD, stabilind criterii de validare a
datelor, metode de acces la date şi de asigurare a confidenţialităţii şi
integrităţii datelor. Toate aceste elemente se regăsesc în ceea ce se
numeşte schema bazei de date. Execuţia definiţiilor limbajului se
materializează într-un ansamblu de tabele, memorate într-un fişier
special denumit dicţionar de date (repertoar de date) [8].
Funcţia de manipulare asigură prin intermediul limbajului
special LMD derularea următoarelor activităţi: încărcarea bazei de
date, adăugarea de noi înregistrări, ştergerea unor înregistrări,
editarea totală sau parţială a unor înregistrări, ordonarea
înregistrărilor, căutarea logică sau fizică a înregistrărilor etc.
Funcţia de utilizare permite comunicarea între utilizatori şi
baza de date prin intermediul unor interfeţe, creându-se astfel un
mediu favorabil utilizatorului care la ora actuală beneficiază de
prelucrarea în timp real, arhitecturile client-server, servicii Internet
etc.
În cadrul realizării acestei funcţii interacţionează diverşi
utilizatori, literatura de specialitate oferind mai multe clasificări sau
grupări. Dintre acestea am selectat doar câteva astfel de grupări.
Raportul ANSI/SPARC 1975 prezintă trei categorii de utilizatori
(roluri umane) ce definesc schemele dintr-o arhitectură de sistem
bazat pe SGBD.
 persoana sau grupul de persoane care defineşte schema
conceptuală a bazei de date. Această schemă furnizează o
viziune pe termen lung şi este baza pentru declaraţiile de
securitate-integritate şi standardizare impuse celorlalte tipuri
de utilizatori;

48
 administratorul bazei de date care are responsabilitatea
definirii schemei interne a bazei de date şi a întreţinerii
acesteia. În acelaşi raport sunt prezentate trei categorii de
administratori:
 administratorul întreprinderii care asigură gestionarea
globală a aplicaţiilor curente şi identificarea celor
viitoare;
 administratorul aplicaţiilor care are rolul de a
dezvolta schemele externe (sub-schemele) pentru
aplicaţiile utilizator;
 administratorul de date care operează la nivelul
schemei de date precizând necesarul şi disponibilitatea
datelor;
 programatorii de aplicaţii şi utilizatorii finali care comunică
cu SGBD-ul prin intermediul limbajului de manipulare sau a
limbajului de interogare.
Într-o altă viziune utilizatorii pot fi structuraţi astfel:
1. utilizatorii liberi sau conversaţionali, reprezintă beneficiarii
(utilizatorii neinformaticieni) a informaţiilor care nu dispun de
cunoştinţe despre structura bazei de date şi nici despre sistemul
de calcul pe care este implementată baza de date. În schimb au la
dispoziţie limbaje de interogare a bazei de date într-o formă
simplistă;
2. utilizatori programatori care utilizează limbaje de manipulare
realizând proceduri complexe de exploatare a bazei de date.
Aceşti utilizatori cunosc atât structura bazei de date cât şi
particularităţile sistemului de operare, ceea ce le dă posibilitatea
să exploateze toate facilităţile oferite de baza de date;
3. administratorul bazei de date care are cel mai important rol în
funcţionarea şi exploatarea optimă a întregului sistem, asigurând
realizarea obiectivelor şi funcţiilor SGBD-ului.
O ultimă clasificare asupra căreia ne-am oprit grupează
utilizatorii în trei mari categorii [13] :
utilizatori finali – care interacţionează cu baza de date prin
intermediul unui limbaj de interogare sau care apelează
programe scrise de programatorii de aplicaţii;

49
programatorii de aplicaţii care au rolul de a crea programele de
aplicaţii ale bazei de date, utilizând limbajul de manipulare a
datelor;
administratorul bazei de date care este o persoană sau un grup de
persoane responsabil cu controlul general al sistemului.
Pe lângă aceste categorii de utilizatori, bazele de date pot fi
accesate fraudulos de persoane cu cunoştinţe de specialitate care
încearcă să sustragă sau să distrugă informaţii, provocând daune
proprietarilor băncilor de date. Aceşti utilizatori sunt cunoscuţi sub
numele de hacker-i.

50
2.4. Protecţia şi securitatea bazelor de date
Prin protecţia bazei de date se înţelege un ansamblu de
activităţi umane şi de facilităti oferite de SGBD prin care se
urmăreşte asigurarea integrităţii datelor (corectitudinii datelor
memorate în baza de date) şi securităţii datelor (restricţionarea
accesului la date). Cu cât aria de cuprindere a SGBD este mai vastă,
cu atât aceste două obiective sunt mai importante şi mai dificil de
realizat.
Cu privire la integritatea datelor, pot să apară trei situaţii
practice:
Asigurarea integrităţii semantice a datelor. Obiectivul
impune de fapt evitarea introducerii de date incorecte sau efectuarea
unor prelucrări incorecte. Erorile trebuie sesizate la un interval de
timp cât mai scurt după apariţia lor.
Controlul accesului concurent la date. Acesta implică
evitarea obţinerii de rezultate neverosimile ale prelucrărilor ca
urmare a execuţiei concurente a mai multor prelucrări în regim
multiutilizator.
Salvarea şi restaurarea bazei de date. În cazul funcţionării
anormale a sistemului, bazele de date trebuie să poată fi readuse la
starea avută înainte ca defecţiunea să survină.

Integritatea semantică se poate asigura atât prin proceduri de


validare incluse în programele de aplicaţii, cât şi prin instituirea unor
reguli de integritate asupra bazei de date. Există restricţii de
integritate implicite şi explicite (acestea din urmă se mai numesc şi
restricţii de comportament). Ca restricţii implicite, la modelul
relaţional avem integritatea entităţii (se referă la valori nenule ale
cheii) şi integritatea referenţială. Restricţiile explicite de integritate
(ex: nici un salariu să nu fie mai mare de 10000000 lei) pot fi definite
în programele de aplicaţii sau, dacă SGBD o permite, pot fi
memorate în dicţionarul de date, sub formă de proceduri stocate,
declanşatori etc. (avantaj considerabil).

51
Controlul accesului concurent la baza de date
În sistemele multiutilizator, sistemul de operare asigură
accesul programelor la resurse după o disciplină internă (uneori
"execuţie întreţesută"). Întreruperea accesului unui program la baza
de date pentru a permite accesul altuia poate avea consecinţe grave
asupra operaţiunii în curs, alterând datele.
Pentru controlul accesului concurent, SGBD multiutilizator
operează cu mecanismul tranzacţiilor. Tranzacţia este o secvenţă de
operatii care din punctul de vedere al SGBD se constituie ca un tot
unitar, acceptându-se fie derularea ei completă, fie anularea tuturor
modificărilor aduse bazei de date (derularea inversă). Orice
tranzacţie are un punct de început şi unul de sfârşit. Tranzacţiile sunt
de două tipuri:
* implicite, care au puncte de început şi de sfârşit automat
definite (de ex., comenzile INSERT, UPDATE, DELETE din SQL);
* explicite, adică acelea care prezintă clauze pentru stabilirea
punctelor de început şi de sfârşit (BEGIN TRANSACTION,
COMMIT/END TRANSACTION, ROLLBACK).
Tranzacţiile nu produc anomalii dacă au loc de o manieră
succesivă (execuţie serială). Cum din motive de performanţă
execuţia seriala nu este posibilă pe sisteme multiutilizator, se
apelează la tehnica blocării pentru a asigura o execuţie serializabilă a
tranzacţiilor. În cea mai simplă formă, blocarea constă în interzicerea
accesului altor procese la datele implicate într-o tranzacţie, până ce
aceasta nu se finalizează. Blocarea poate avea loc la nivel de bază de
date, fişier, grup de înregistrări, înregistrare sau chiar câmp. Totuşi,
blocarea nu este atât de restrictivă, în sensul că:
* se permite citirea de către un utilizator a datelor accesate
spre citire de alt utilizator (blocare partajabilă);
* nu se permite citirea de către alţi utilizatori a datelor
accesate în scopul actualizării de alt utilizator (blocare exclusivă).
Blocarea se realizează prin emiterea de către o tranzacţii a
unei cereri explicite de blocare.

52
Accesul concurent şi complexitatea mecanismului de blocare
sunt influenţate de granularitatea blocării. Se intuieşte uşor faptul că
blocarea întregii baze de date este mai neeconomicoasă decât alte
tipuri de blocare, dar blocarea unui singur câmp complică foarte mult
mecanismul de blocare. În practică, SGBD execută blocarea la nivel
de înregistrare, grup de înregistrări sau fişier.
O problemă specială o constituie interblocarea (deadlock), care
constă în blocarea de către două tranzacţii a anumitor resurse, apoi
fiecare solicită resursele blocate de cealaltă. Există două strategii de
rezolvare a interblocării:
* prevenirea interblocării: fiecare tranzacţie blochează de la
început toate resursele de care are nevoie, astfel că alte tranzacţii nu
le vor putea accesa; cum este imposibil de cunoscut dinainte ce
resurse sunt necesare, metoda are o slabă aplicabilitate practică;
* soluţionarea interblocării: se blochează resursele pe măsura
ce tranzacţia le solicită, deci interblocarea poate surveni, dar apoi se
folosesc metode pentru detectarea şi eliminarea sa. Pentru aceasta,
sistemul poate să ţină evidenţa tranzacţiilor în curs, deci a
înregistrărilor accesate. Dacă survine interblocarea, una dintre părţi
va fi victima, adică tranzacţia sa va fi abandonată. Toate resursele
vor fi deblocate iar utilizatorul va fi anunţat despre acest lucru.
Procesul întrerupt poate fi: cel cu cele mai multe resurse blocate; cel
cu cele mai putine resurse blocate; cel mai vechi; cel mai recent; cel
cu cea mai mică prioritate la execuţie; cel care nu a realizat încă
actualizarea BD etc.
Aceste precizări sunt valabile pentru calculatoarele mari,
SGBD micro având facilităţi mult mai modeste de control al
tranzacţiilor concurente.

Salvarea şi restaurarea bazei de date


Aceste operaţii au ca scop readucerea bazei de date în starea
consistentă în care se afla înainte de unele evenimente care au alterat
consistenţa datelor, precum: funcţionare anormală a SGBD-ului sau
sistemului de operare, defecţiune a suportului fizic pe care este
memorată baza de date.

53
O stare consistentă este una în care sunt reflectate rezultatele
finale ale execuţiei unor tranzacţii, nici o tranzacţie nu este în curs de
execuţie şi sunt satisfăcute restricţiile semantice necesare.
Există mai multe tehnici de restaurare. Una dintre ele constă
în terminarea tranzacţiilor active la momentul defecţiunii.
Informaţiile necesare restaurării pot îmbrăca forma unor copii de
siguranţă, jurnale ale tranzacţiilor (succesiunea cronologică a
prelucrărilor), puncte de control (checkpoints) şi jurnale ale
imaginilor (rezultatele prelucrărilor succesive). Restaurarea se poate
face automat sau manual.

Securitatea bazei de date

Interzicerea accesului neautorizat la date îmbracă forma unui


set de măsuri de protecţie umane, hardware şi software.
Prima şi cea mai simplă măsură este izolarea fizică a
sistemului de calcul de persoanele neautorizate (acolo unde este
posibil).
Accesul la resursele sistemului poate avea loc prin facilităţi
ca parole, profile utilizator sau matrici ale drepturilor de acces
(privilegii, reguli de autorizare).

Utilizator Obiect Acţiune Restricţie


U1 salariati.dbf citire sector="Personal"
U2 furnizori.dbf citire, modificare, -
stergere
U3 salariati.dbf citire Sector="TESA"

Tabel 1.2 Drepturile utilizatorilor


Un alt mecanism este cel al schemelor externe (referite in
literatura de specialitate şi ca view-uri), reprezentând acea parte a
bazei de date care poate fi accesată de un anumit utilizator. De
obicei, privilegiile pentru un view sunt precizate independent de cele
pentru obiectele pe baza cărora este definit.
54
De asemenea, datele pot fi memorate pe suportul extern în
formă criptată, astfel încât citirea lor fără aplicaţia proprietară (de
exemplu cu ajutorul comenzilor sistemului de operare) să fie
imposibilă. Criptarea presupune folosirea componentelor următoare:
* cheie de criptare;
* algoritm de criptare;
* cheie de decriptare;
* algoritm de decriptare.
Mai cunoscute sunt metodele de criptare DES (cheie privată
pe 64 de biţi), RSA, PGP (cheie publică şi cheie privată).

55
1.5. Administrarea datelor şi a bazelor de date
În prezent este larg recunoscută importanţa critică a gestiunii
datelor în cadrul unei organizaţii economice. Datele şi informaţiile
asociate reprezintă o resursă mult prea valoroasă pentru a nu
beneficia de o atenţie sporită în ceea ce priveşte activitatea de
administrare a lor.
Administrarea ineficientă a datelor duce la o slabă
valorificare a acestora şi se poate caracteriza prin:
- definiţii multiple ale aceleiaşi entităţi de date şi/sau reprezentări
inconsistente ale unor aceleaşi elemente de date în baze de date
diferite, conducând la imposibilitatea integrării datelor
- lipsa unor elemente cheie ale datelor, fapt ce determină pierderea
valorii datelor pentru organizaţie
- nivele scăzute ale calităţii datelor datorate unor surse inadecvate
de date sau timpilor prohibitivi de transfer de la un sistem la altul
- lipsa unei familiarizări cu datele existente la dispoziţie, inclusiv
lipsa cunoaşterii locaţiilor şi semnificaţiilor datelor în procesele
de adoptare a deciziilor strategice sau de planificare.
Având în vedere aceste aspecte negative, majoritatea
organizaţiilor au creat două funcţii speciale: pentru administrarea
datelor, respectiv pentru administrarea bazei de date.
Administratorul datelor este custodele datelor organizaţiei,
fiind direct răspunzător de controlarea utilizării şi de protejarea
resurselor de date. De asemenea, administratorul datelor are ca
sarcini:
- determinarea cerinţelor organizaţiei privind datele, estimarea
volumului de date şi a creşterii probabile a acestuia
- dezvoltarea unui model de date general
- realizarea proiectării conceptuale şi logice a bazei de date
- gestionarea dicţionarului de date
- soluţionarea conflictelor cauzate de accesul concurent la o
aceeaşi resursă de date (partajarea unei resurse de date)
- adoptarea deciziilor privitoare la memorarea datelor

56
- impunerea şi menţinerea unor definiţii ale datelor şi a unor
standarde
- îmbunătăţirea performanţelor bazei de date
- asigurarea mijloacelor de instruire a utilizatorilor
- implicarea într-o gamă largă de activităţi ca planificarea, analiza,
proiectarea, implementarea şi asigurarea securităţii bazei de date
- asigurarea unei documentaţii complete care să includă modelul
întreprinderii, standardele, politicile, procedurile, utilizarea
dicţionarului de date şi controlul asupra utilizatorilor finali
- menţinerea contactului cu utilzatorii pentru a determina noile
cerinţe şi a rezolva dificultăţile privind accesul la date sau
performanţele
Administratorul bazei de date este implicat în proiectarea
fizică a bazei de date şi în implementarea efectivă a acesteia pe
suporturile fizice de memorare, în impunerea standardelor de
securitate şi protecţie, precum şi în activităţile de salvare şi restaurare
a bazei de date.
Funcţiile generale ale administrării datelor şi bazelor de date sunt
următoarele:
- stabilirea politicilor, procedurilor şi standardelor
organizaţiei în materie de date, ca măsuri de protecţie a datelor
şi a bazei de date
- politicile datelor sunt reprezentate de o serie de
specificaţii care explicitează scopurile administrării
datelor (de exemlu, "fiecare utilizator trebuie să posede o
parolă"
- procedurile asociate datelor sunt exprimări ale unor
acţiuni ce trebuie întreprinse pentru efectuarea unor
anumite activităţi; de exemplu, procedurile de salvare şi
restaurare a datelor ce trebuie cunoscute de către toţi
utilizatorii
- standardele asociate datelor sunt convenţii explicite ce
trebuie urmate pentru a facilita cunatificarea nivelului de
calitate a datelor şi a bazei de date; de exemplu,
convenţiile de notaţie pentru obiectele componente ale
unei baze de date trebuie standardizate, urmând a fi

57
respectate întocmai de către toţi programatorii de
aplicaţii.
- planificarea ce presupune administrarea eficientă a datelor şi a
bazei de date implică atât înţelegerea cu exactitate a nevoilor
reale ale organizaţiei, cât şi abilitatea de a contribui la
dezvoltarea unei arhitecturi informaţionale care să satisfacă
nevoile organizaţiei
- rezolvarea conflictelor de date. Bazele de date sunt utilizate cu
scopul de a fi partajate; mai mult, de regulă, bazele de date
implică date ce provin de la mai multe departamente din cadrul
organizaţiei. În acest context, administratorilor datelor şi a
bazelor de date le revine misiunea de a media conflictele
generate de asumarea dreptului de proprietate asupra datelor din
partea unor utilizatori
- gestionarea depozitului intern de date al cărui conţinut este
reprezentat de metadatele ce descriu datele şi resursele de
procesare a datelor unei organizaţii. În prezent depozitele de date
înlocuiesc dicţionarele de date în majoritatea organizaţiilor,
constituind instrumente esenţiale de sprijinire a activităţilor de
administrare a datelor şi a bazelor de date
- selectarea componentelor hadware şi software. Evaluarea şi
selectarea componentelor hardware şi software este un factor
cheie în administrarea eficientă a datelor unei organizaţii,
aspectul cel mai important fiind cel al asigurării permanente a
unei compatibilităţi depline între componentele hardware şi cele
software
- gestionarea aspectelor privind securitatea şi
confidenţialitatea datelor. Scopul asigurării protecţiei şi
securităţii datelor este de a preveni apariţia unor ameninţări
intenţionate sau accidentale la adresa integrităţii datelor şi a
accesului la date. Asigurarea protecţiei datelor se concretizează
în elaborarea şi implementarea unor planuri detaliate de
securitate a datelor ce includ:
- politici şi proceduri administrative
- protecţii ale datelor la nivel fizic
- protecţii ale sistemului de gestiune a bazei de date, ce
includ:

58
- perspective sau subscheme care restricţionează
accesul utilizatorilor
- reguli de autorizare care identifică utilizatorii şi
restricţionează acţiunile pe care aceştia le pot
efectua asupra bazei de date
- proceduri definite de utilizatori ce impun restricţii şi
limitări adiţionale asupra utilizării bazei de date
- proceduri de criptare ce conduc la criptarea datelor
din baza de date într-un format neinteligibil
- scheme de autentificare ce identifică fără
ambiguitate persoanele ce intenţionează să acceseze
baza de date
- facilităţi suplimentare de salvare, monitorizare şi
verificare care conduc la uşurarea activităţii de
restaurare.
- asigurarea procedurilor specifice de salvare şi restaurare

59
Capitolul II. Mediul integrat
de gestiune şi programare
Oracle

2.1 Ce este ORACLE

Oracle este cel mai răspândit Sistem de Gestiune a Bazelor


de Date Relaţionale (Relational Database Management System -
RDBMS) din lume. Profesioniştii din domeniul Tehnologiei
Informaţiei (IT) consideră că produsele Oracle satisfac cerinţele de
baze de date din numeroase domenii precum cel industrial, financiar,
farmaceutic şi al telecomunicaţiilor din întreaga lume. Bazele de date
Oracle sunt instalate pe toate tipurile de calculatoare şi rulează sub
principalele sisteme de operare existente. Există versiuni Oracle
pentru platforme de la calculatoarele portabile modeste până la
serverele puternice de baze de date la care sunt conectaţi simultan
mii de utilizatori. Bazele de date Oracle funcţionează ca motoare de
procesare a tranzacţiilor on-line, bănci de date, depozitare pentru
aplicaţii web etc. .
Fiind prima bază de date proiectată pentru calcul în grid,
Oracle Database aduce îmbunătăţiri semnificative faţă de
predecesoarele sale printr-o performanţă superioară, scalabilitate,
disponibilitate mărită. Grid Computing reprezintă utilizarea
coordonată a mai multor servere mici care acţionează ca un singur
sistem foarte puternic. Pentru utilizatorii care lucrează în tehnologia
GC nu mai contează unde sunt stocate datele, unde sunt stocate
aplicaţiile, ce calculatoare procesează cererea de regăsire, ce resurse
sunt folosite în retea. Enterprise Grid Computing - EGC înseamna
procesul de punere la lucru împreuna a mai multor calculatoare

60
existente la nivelul unei organizaţii şi funcţionarea ca un sistem
integrat. Arhitectura GC evidentiază grafic diferitele componente şi
legăturile dintre ele. Structurarea se face pe patru nivele (aplicaţii,
server de aplicaţii, baze de date, echipamente) conectate prin
mecanisme de interfaţă de servicii şi monitorizare (control). Oracle
este prima companie care a promovat tehnologia GC, într-un sistem
de gestiune a bazelor de date – Oracle 10g – pentru intreprinderi.
Astfel, oferă o infrastructură software completă şi comercială,
proiectată special pentru GC lucrul cu baze de date. Oracle 10g
permite adaptarea sistemelor informatice la modelul EGC, care
foloseşte puterea de prelucrare a unui mare număr de calculatoare,
puţin costisitoare, care acţionează ca un tot unitar.
Utilizarea pe dispozitive de stocare şi servere standardizate a
devenit mai usoară şi la un preţ mai redus.
Scurt istoric: Oracle este produsul unei mari companii care a
avut parte de un succes enorm în cei mai bine de 30 de ani de când se
află pe piaţă. Totul a început în anii '60, când Codd, cercetător la
I.B.M., a studiat posibilitatea ameliorării modului de stocare a
datelor în fişiere, deoarece existenţa informaţiilor redundante
predispunea la erori greu de depistat. În 1970 el a publicat un articol,
"A Relaţional Model of Data for Large Shared Databanks" care a
schimbat complet concepţiile privind structura bazelor de date. Un
programator, Larry Ellison, sesizând importanţa practică a teoriei lui
Codd, a realizat un produs software, Oracle, şi o firmă pentru
promovarea acestuia, Oracle Coorporation. De-a lungul anilor,
produsul firmei Oracle a trecut prin multe schimbări de nume, de la
version 1 la version 6, apoi la Oracle 7, 8, 8i, 9i, 10g şi chiar 11g în
anul 2009 (fig.2.1). Începând cu Oracle 12c, sistemul de gestiune a
bazelor de date Oracle a trecut în Cloud.
Orice sistem de gestiune a bazelor de date are cel puţin un
limbaj de programare cu instrucţiuni pentru descrierea datelor - DDL
şi instrucţiuni pentru manipularea datelor – DML. Aceste limbaje
permit implementarea unui model logic de date pentru baze de date,
deci sunt specifice. Pe langă acestea, majoritatea sistemelor deţin sau
au interfeţe cu alte limbaje de diferite tipuri, scopul fiind acela de a
oferi toate facilitaţile de programare necesare pentru dezvoltatorul de

61
aplicaţii cu baze de date. Acest lucru este necesar deoarece
majoritatea problemelor din lumea reală implică, pentru
informatizare, utilizarea mai multor tipuri de limbaje de programare,
deoarece fiecare oferă anumite facilitaţi şi avantaje.

Fig.2.1 Evoluţia sistemului Oracle 7


Oracle deţine în nucleul sistemului mai multe limbaje de
programare: SQL ca limbaj relaţional pentru descrierea şi
manipularea datelor în baza de date relaţională, PL/SQL ca limbaj
procedural propriu, Java ca limbaj orientat obiect şi de comunicaţie,
extensie de programare orientată obiect în PL/SQL,
precompilatoarele – ca interfeţe de programare cu limbajele

7
https://ittutorial.org/wp-
content/uploads/2019/06/Oracle_Database_Versions_History.png /

62
universale – Fortran, Cobol, Pascal, C etc. Rezultă asadar că Oracle
oferă dezvoltatorului posibilitatea de a scrie cod sursa în limbajele de
programare pe care le ştie sau de care are nevoie, practic în orice tip
de limbaj.

Fig.2.2 Structura SGBD Oracle

63
2.2 Instalarea sistemului Oracle 11g Express
Edition
Sistemul Oracle 11g Express edition este o versiune academică
a sistemului de gesttiune a bazelor de date Oracle 11g, având
posibilitatea gestiunii utilizatorilor şi a obiectelor bazei de date direct
dintr-un browser WEB. Kit-ul de instalare poate fi descarcat direct
de pe www.oracle.com.
Primii paşi sunt descrişi generic în Figura 2.3.

Fig. 2.3 Instalarea serverului Oracle 11g Express Edition (XE)

64
Kit-ul de instalare cere întâi să se accepte condiţoiile de
utilizare. Apoi să se introducă o parolă-mster pentru cele douăp
conturi de Administrare SYS, respectiv SYSTEM (Fig. 2.4)

Fig. 2.4 Introducerea parolei conturilor SYSTEM şi SYS

Portul Web folosit este 8080, iar pentru interfaţa mediului


integrat de programare ORACLE se reyervă portul 1521, care pot fi
modificate de utilizator (Fig. 2.5)

Fig. 2.5 Derularea procesului de instalare

65
Odata instalat, în primă etapă trebuie creată o bază de date;
pentru aceasta se porneşte modul APEX de administrare folosind
selecţie AllPrograms-> Oracle Database 11g ExpressEdition-> Get
Started (Fig. 2.6)

Fig. 2.6 Pornirea serverului Oracle 11g XE în modul Apex

Aplicaţia Apex în modul SYSTEM permite gestiunea directă a


spaţiului de stocare (Storage), a sesiunilor de lucru (Sessions), a
parametrilor BD (Parameters), precum şi crearea unei noi baze de
date (Application Expres)

Fig. 2.7 Interfaţa de control a serverului Oracle 11g XE în


modul Apex

66
Ultima opţiune presupune autentificarea administratorului
general )cinturile SYSTEM sau SYS=, cu parola introdusă în etapa
de instalare. (Fig. 2.8 propune parola “acasa”)

Fig. 2.8 Autentificarea contului SYSTEM


Odată autentificat, administratorul bazelor de date trebuie sa
creeze întâi o baza de date Oracle 11g, denumită simbolic
Workspace (sau XE), conform figurii de mai jos.

s
tu
d

Fig. 2.9 Crearea unei baze de date


67
Noua bază de date va avea un nume de lucru (Workspace
name) şi un administrator DBA (Database username). Conectarea la
noua bază de date se efectuează prin iniţializarea aplicaţiei Apex în
modul user, conform figurii 2.10, prin eliminarea unei porţiuni din
string-ul barei de cautare a browser-ului )alternativ, se poate
introduce de la tastatură 127.0.0.1:8080/apex)

Se elimina portiunea selectata din link


pana la apex

Fig. 2.10 Iniţializarea aplicaţiei Apex în modul client

Autentificarea la baza de date cere numele de lucu al acesteia


(Workspace), numele utilizatorului şi parola sa.

s
tud

Fig. 2.11 Autentificarea la baza de date prin Apex


68
Fig. 2.12 Crearea unui nou utilizator

69
Crearea unui utilizator nou presupune accesarea sectiunii
Administration din meniul grafig, a subsecţiunii Manage Users and
Groups (Fig 2.12). Pentru orice utilizator nou se cer introduse un
username, o adresă de e-mail, numele bazei de date pe care lucrează
implicit (Default Schema), statutul (Administator, Developer, Simple
user), alte drepturi (SQL workshop access este fundamental) şi o
parolă.

Fig. 2.13 Acordarea de drepturi noului utilizator

70
Fig. 2.14 Accesarea interfeţei de Comenzi SQL

Interfaşa de lucru SQl se accesează din mediul SQL Workshop,

71
submeniul SQL Commands (Fig. 2.14). Instrucţiunile SQL simple
pot fi rulate din fereastra SQL Commands folosind butonul Run.

Fig. 2.15 Execuţia unei comenzi SQL

Orice baza de date Oracle 11g ExpressEdition are preinstalată o bază


de date simplă formată din două tabele (emp – Employes, respectiv
dept -Depatments)

Tabela emp este prezentată în Fig, 2.16.


Cu tiltlu de exemplu, comanda SQL

DESCRIBE emp;

permite vizualizarea structurii acestei tabele, iar comanda

SELECT * FROM emp;

permite vizualizarea datelor din aceasta.

72
Fig. 2.16 Tabela emp
73
2.3. Oracle Forms Builder
Oracle Forms este un limbaj puternic, utilizat pentru
dezvoltarea aplicaţiilor interactive. Orice aplicaţie creată cu Oracle
Developer este prin natura ei o aplicaţie multi-utilizator, bazată pe
tehnologia client/server, independentă de platforma.
Oracle Forms constituie coloana vertebrală a pachetului de
programe Oracle Developer fiind utilizat pentru realizarea
interfeţelor interactive ale aplicaţiilor. Permite apelarea atât a altor
componente Oracle Developer cât şi a programelor scrise în C sau a
altor aplicaţii.
Oracle Forms este bazat pe programarea orientată pe
eveniment, fapt ce permite scrierea de cod PL/SQL ataşat unui
eveniment pentru a defini acţiunea care se va executa la apariţia
evenimentului respectiv. De asemenea Oracle Forms utilizează şi
conceptul de programare orientată pe obiect, permiţand mostenirea
de obiecte (moştenirea anumitor caracteristici) încapsularea
(definirea unor caracteristici proprii fiecărei clase de obiecte)
polimorfismul (rescriere unor funcţii).
În directorul destinat instrumentelor Oracle Developer sunt
create trei icoane pentru Oracle Forms: Forms Builder, Forms
Compiler şi Forms Runtime. Dezvoltarea unei aplicaţii se realizează
cu Form Builder, care poate apela pentru compilare şi execuţie
celelalte două componente, nefiind necesară apelarea separată a
acestora.
Forms Builder este mediul în care aplicaţiile sunt create,
testate şi depanate. El furnizează o serie de instrumente de design cu
ajutorul cărora se poate crea şi modifica funcţionalitatea sau aspectul
unei aplicaţii.
 Object Navigator
 Editorul de proprietăţi (Property Palette)
 Editorul de Aranjare (Layout Editor)
 Editorul PL/SQL (PL/SQL Editor)
 Editorul de meniuri (Menu Editor)

74
Fig. 2.17 Mediul Oracle Forms Builder 6i
Toate aceste instrumente sunt disponibile în meniul Tools
(fig. 2.17).
Cea mai importantă componenta este Object Navigator.
Aceasta permite accesul la diverse componente pentru realizarea
formelor, meniurilor şi biblioteciilor, precum şi la obiectele bazei de
date cum ar fi declanşatoarele (triggers) şi procedurile stocate.
Object Navigator permite navigarea facilă între elementele
ce aparţin formelor. Un obiect poate fi editat, modificat sau creat în
întregime de către Object Navigator. Fereastra principală a Object
Navigator prezintă fiecare obiect (instanţă) sau tip de obiect, ce poate
fi precedat de unul de simbolurile + si -. Aceste semne apar atunci

75
când un obiect sau un tip de obiecte are elemente (copii) care îi
aparţin: semul – indică faptul că deja obiectul este expandat, iar
semnul + apare atunci când acesta este restrâns, adică elementele
copii sunt ascunse.
Object Navigator utilitează icoane pentru a indica un obiect
care are proprietăţi. O proprietate este un parametru care descrie un
obiect. Fiecare tip de obiect are o listă diferită de proprietăţi care
poate fi modificată utilizând Property Pallete. Obiectele sunt create
folosind opţiunea Navigator-Create din meniul principal. Obiectele
pot fi create şi şterse selectând opţiuni din meniul Navigator sau
utilizând bara de butoane din fereastra Navigator.

2.4. Obiectele şi tipul acestora în Forms Builder

2.4.1. Forme (Forms)


O formă este un modul de bază creat cu Oracle Forms şi
reprezintă o colecţie de mai multe obiecte. Forma apare in Object
Navigator ca obiect părinte al tuturor obiectelor care sunt construite
în cadrul ei. Fişierele care conţin codul sursă al unei forme au
extensia .fmb (form binary). Acestea sunt transformate de către
compilator în fişiere executabile care au extensia .fmx. Aceste fişiere
nu se pot executa direct, ci doar prin intermediul modului Forms
Runtime.
2.4.2. Declanşatoare (Triggers)
Un trigger este un bloc PL/SQL ce se execută ca răspuns la
un eveniment. În Oracle Forms există peste o sută de evenimente
predefinite care pot lansa un trigger, adică execuţia unui bloc
PL/SQL atunci când are loc evenimentul respectiv. Fiecare trigger
este denumit dupa evenimentul care îl declanşează.
Există 5 prefixe pentru trigger-ele evenimentelor predefinite:
key-, on-, post-, pre-, si when-. Trigger-ele key- sunt cele mai uşor de
înţeles. Fiecare trigger este declaşat ca răspuns la apăsarea logica a

76
unei taste. Trigger-ele on- sunt de obicei numite declanşatoare de
tranzacţii (transaction triggers), multe dintre ele fiind generate
automat de către Oracle Forms. Exemplu: ON-CHECK-DELETE-
MASTER este generat în momentul creării unei relaţii între blocuri.
Trigger-e pre- si post- sunt activate înainte respectiv după un
eveniment. Trigger-ele when- sunt foarte utilizate (WHEN-
BUTTON-PRESSED, WHEN-VALIDATE-ITEM).
Blocul PL/SQL care defineşte declanşatorul poate fi executat
cu succes sau nu. Un declanşator eşuează când blocul PL/SQL
generează o excepţie specifică: form_trigger_failure.

2.4.3. Ferestre de Avertizare (Alerts)


O fereastră de avertizare (alert) este în esenţă o casetă
definită de utilizator, care conţine o icoană, un mesaj şi unul până la
3 butoane. Fereastra de avertizare se foloseşte pentru a furniza
informaţii adiţionale sau pentru a semnala întâlnirea unei erori,
permiţând utilizatorului sa ia o anumită decizie în funcţie de
butoanele pe care le deţine fereastra.

2.4.4. Blocuri de date (Data Blocks)


Un bloc este o structura logică similară unei tabele. El
conţine un set de elemente care sunt similare coloanelor şi sunt
aranjate sub formă de înregistrări, care sunt similare rândurilor dintr-
o tabelă. Un bloc poate să corespundă sau nu unei tabele din baza de
date.
Un bloc ce corespunde unei tabele poate fi folosit pentru
inserare, ştergere modificare tabelă. Blocurile ce corespund unei
tabele sunt cunoscute sub numele blocuri ale bazei de date şi au
specificată valoarea Yes pentru parametrul Database/Databse Data
Block . Un bloc bazat pe o tabelă are câteva funcţii proprii care nu
cer o programare adiţională. Un bloc bazat pe o tabelă poate fi folosit
pentru a introduce criterii de interogare prin plasarea formei în mod
interogare (query mode) . Utilizatorul poate introduce restricţii la
rândurile ce sunt returnate din tabelă.
77
2.4.5. Elemente (Items)
Elementele sunt componentele vizuale ale unei forme.
Fiecare element aparţine unui bloc, care prin esenţă e o colecţie de
elemenete. Într-un bloc PL/SQL din cadrul unei forme, un element
poate fi accesat folosindu-se sintaxa :bloc.element. Există noua tipuri
diferite de elemente: text item, chart item, check box, display_item,
image, button, radio group, list item, şi custom item. Un text item
este un câmp folosit pentru introducerea, regăsiea şi editarea cu
ajutorul tastaturii a textelor de tip şir de caractere, număr sau dată.
2.4.6. Relaţii (Relations)
O relaţie master/detail asociază un bloc master şi un bloc
detaliu, reflectând relaţia determinată de cheia primară si cheie
străină între tabelele pe care se bazează blocurile.
Obiectul relaţie coordonează automat relaţia master/detail
dintre blocuri. Atunci când o relaţie este creată, sunt create în mod
automat şi declanşatoarele şi procedurile PL/SQL necesare pentru a
forţa coordonarea dintre cele 2 blocuri. O relaţie poate fi creată
automat la crearea unui bloc folosind facilitatea Block Wizard, prin
selectarea unui bloc master pe care se bazează blocul curent. Această
opţiune există numai dacă blocul master există deja în formă şi când
relaţia cheie primară/cheie straină între tabele este definită în baza de
date.
2.4.7. Canvas-uri (Canvases)
Canvas-urile sunt suprafeţe vizuale pe care sunt plasate
elementele, astfel încât acestea pot fi manipulate sau vizualizate de
către utilizatorul final. Canvas-urile pot fi suprapuse, nu sunt ferestre,
ele sunt vizualizate prin intermediul ferestrelor, care sunt definite
separat. Relaţia dintre ferestre si canvas-uri este aceea ca într-o
fereastră apar unul sau mai multe canvas-uri.
2.4.8. Editoare (Editors)
Un editor este un editor text care apre pe ecran în cadrul unei
aplicaţii şi oferă o modalitate mai convenabilă de a vedea sau edita

78
un text lung într-un text_item. Un editor este definit prin
specificarea unor proprietăţi cum ar fi poziţia, mărimea, titlul si
fontul.
2.4.9. Parametrii (Parameters)
Un parametru este o variabilă utilizată pentru transmiterea
datelor între două forme sau între o formă şi un raport. Atunci când o
formă este apelată dintr-o altă formă parametrii sunt transmişi ca
parte a unei liste de parametri.
Prin definirea unor parametrii pentru o formă folosind Object
Navigator, forma se va aştepta să primescă o valoare pentru fiecare
dintre parametrii, iar în cazul în care valoarea nu va fi transmisă,
parametrul va primi o valoare implicită. Cu alte cuvinte parmetrii
reprezintă parametrii de intrare pentru o formă, ai căror valori sunt
transmise din forma apelantă.
2.4.10. Unităţi de program (Program Units)
Unităţiile de program sunt de 4 tipuri: proceduri
(procedures), funcţii (functions), specificaţii de pachete (package
specifications) şi corpuri de pachete (package bodies).
În momentul când se creează o unitate de program sunt
specificate numele şi tipul acesteia, iar apoi va apărea editorul
PL/SQL care va conţine un cadru pentru tipul de unitate de program
selectată (numele, tipul unităţii de program, cuvântul cheie BEGIN şi
cuvântul cheie END urmat de “;”).
Procedurile si funcţiile sunt definite de către utilizator, cu
parametrii opţionali de intrare si de ieşire care pot fi apelaţi din orice
alt bloc PL/SQL în cadrul aceluiaşi modul.
Apelarea unei proceduri: nume_procedura
(argumente)
iar o funcţie se apelează în felul următor: :variabilă
:= nume_funcţie(argumente).

79
2.4.11. Ferestre (Windows)
O fereastră este un element esenţial al unei interfeţe grafice.
Ferestrele sunt suprafeţe rectangulare care comunică informaţii
utilizatorului şi conţin informaţii ce pot fi manipulate.

2.5. Oracle11g: Database / Application Server /


Developer Suite
Astăzi, compania Oracle are o ofertă extrem de generoasă şi
sofisticată, pornind de la serverul de baze de date Oracle11g
Database (care constituie baza de integrare a tuturor celorlalte), suita
de dezvoltare Oracle 10g Developer Suite (compusă în principal din
Oracle11g Forms, Reports, Designer, JDeveloper, pentru dezvoltarea
şi proiectare de aplicaţii, dar şi WarehouseBuilder sau Discoverer,
pentru domeniul intitulat Business Intelligence), la care se adaugă
serverul de aplicaţii, certificare J2EE, Oracle11g Application Server
şi altele.
Cele trei produse, Oracle11g Database, Oracle11g
Application Server şi Oracle11g Developer Suite, furnizează
mijloace complexe pentru crearea aplicaţiilor de baze de date cu
niveluri ridicate în ceea ce priveşte productivitatea, performanţa,
disponibilitatea, fiabilitatea şi securitatea.

2.5.1. Oracle11g Database


Server-ul de baze de date este cheia rezolvării problemelor
de administrare a informaţiilor. Un astfel de server trebuie să
administreze o cantitate semnificativă de date în condiţiile unui
mediu multiuser, care asigură accesul concurenţial la acelaşi set de
date. De asemenea, server-ul bazei de date trebuie să prevină accesul
neautorizat şi să ofere metode eficiente pentru recuperarea datelor, în
cazul unor defecţiuni fizice sau logice.

80
Oracle11g Database aduce noi funcţionalităţi atât pentru
aplicaţiile de baze de date tradiţionale, cât şi pentru aplicaţiile
Internet:
 gestionează orice tip de informaţii;
 oferă scalabilitate complete atât pentru
sistemele cu un singur processor, cât şi pentru
sistemele complexe cu mai multe procesoare
sau configuraţiile cluster cu mai multe noduri;
 întruneşte condiţiile de disponibilitate
permanenţă a datelor;
 garantează securitatea informaţiilor;
 oferă posibilităţi eficiente de analiză a datelor;
 permite implementarea rapidă a soluţiilor
pentru afaceri etc.
Pentru a optimiza performanţele aplicaţiilor, Oracle11g
Database oferă o serie de componente care îmbunătăţesc
posibilităţile produselor: Application Server şi Developer Suite.
Bazele de date Oracle11g permit integrarea de cod Java în
aplicaţii. Avantajul utilizării Java, faţă de alte limbaje (de exemplu
,C), constă în faptul că acesta a fost dezvoltat astfel încât să poată
preveni accesul neautorizat în sistemul de operare pe care rezidă
codul Java. Un alt avantaj este faptul că permite gestiunea automată a
stocarii datelor. Astfel, nu mai este necesară alocarea sau dezalocarea
resurselor de stocare în mod explicit de către dezvoltatorii de
aplicaţii.
Instalarea sistemului Oracle11g cu opţiunea Oracle JVM
(Java Virtul Machine) permite executarea aplicaţiilor care utilizează
proceduri stocate Java, SQLJ, CORBA/EJB (Enterprise Java Beans),
Servlet, JSP şi interfaţă JDBC. Maşina vituală Java nu
interacţionează direct cu sitemul de operare, ci cu bibliotecile bazei
de date.
Oracle11g JVM foloseşte facilităţile server-ului de baze de
date cu scopul de a planifica execuţiile java pentru un număr
considerabil de utilizatori, în sistem concurenţial. În acest sens, se
permite mai multor utilizatori conectaţi la server să execute simultan

81
acelaşi cod Java, ca şi când ar rula propriul cod pe propria maşină
virtual Java.

2.5.2. Oracle11g Application Server


Oracle11g Application Server (Oracle11gAS) oferă o
infrastructura completă pentru dezvoltarea aplicaţiilor de tip e-
business şi Internet. De asemenea, el asigură instalarea şi
administrarea acestor aplicaţii. Astfel, se poate simplifica accesul la
aplicaţiile Internet, prin crearea de portaluri care oferă utilizatorului
un singur punct de accesare a acestor aplicaţii, fie din browser-e
Web, fie de pe dispozitive de tip Wireless.
Server-ul de aplicaţii Oracle11g include suport integral
pentru tehnologia Java (J2EE 1.3) şi standardele actuale pentru
servicii Web (XML, XMI, SOAP, UDDI, WSDL, WebDAV). De
asemenea, Oracle11gAS asigură confidenţialitatea informaţiilor
transmise prin reţea, incluzând suporturi de criptare, autentificare şi
autorizare si oferă un mediu de lucru eficient pentru dezvoltarea
aplicaţiilor Web complet independente de dispozitivul prin care sunt
accesate. Această funcţionalitatea este necesară pentru e-business şi
pentru administrarea informaţiilor publicate pe Internet.
Oracle11gAS este disponibil în trei variante:
 Java Edition
 Standard Sdition
 Enterprise Edition
Oracle11gAS Java Edition este varianta restrânsă, care
permite dezvoltarea rapidă a aplicaţiilor Java. Ea combină toate
produsele cu support J2EE într-un singur pachet, care include:
 Oracle11gAS Containers for J2ee
(OC4J)
 Oracle HTTP ServerOracle11gAS
Toplink
 Oracle11g JDeveloper
 Oracle Enterprise Manager

82
Componentele permit editarea, testarea şi dezvoltarea, într-
un singur mediu, a aplicaţiilor
Java şi a celor care implică servicii Web. Suportul pentru
serviciile Web permite publicarea ca servicii Web atât a claselor
Java, cât şi a procedurilor stocate Java sau PL/SQL .
Oracle11gAS suportă toate tipurile de clienti de reţea şi este
punct central de acces către baza de date. Acesta include două
extensii: Oracle Call Interface (OCI), pentru accesul nativ la bazele
Oracle, şi Oracle Database Conectivity (ODBC) , pentru accesul la
alte tipuri de baze.
Prin Oracle11gAS Portal se pot crea portaluri web pentru a
centraliza toate informaţiile din sistemele companiei şi a le
redistribui către anumite categorii de utilizatori. Acest mediu oferă,
pentru site-urile de tip portal, un punct comun ce permite accesul cu
uşurinţă la date, integrarea cu aplicaţiile şi conţinutul multimedia din
baza de date. Portalul asigură utilizatorilor acces la mai multe
aplicaţii, autentificarea acestora realizându-se o singură data, pentru
toate aplicaţiile în desfăşurare.
Oracle11gAS oferă servicii de tip director pentru
monitorizarea, gestiunea şi securizarea sistemelor distribuite. După
realizarea autentificării iniţiale, utilizatorul este validat automat
pentru alte aplicaţii pe care le accesează, fără a fi necesară
reintroducereea informaţiei de conectare.

2.5.3. Oracle11g Developer Suite


Oracle11g Developer Suite (Oracle11gDS) extinde
infrastructura formată din Oracle11gAS şi Oracle11g Database,
permiţând dezvoltarea de aplicaţii Internet singure, scalabile şi
fiabile. Oracle11gDS reprezintă un mediu integrat de dezvoltare
(Integrated Development Enviroment), care asigură întregul process
de creare a unei aplicaţii (modelare, dezvoltare, codificare, depanare,
optimizare, instalare).
Oracle11gDS înglobează suport pentru Java şi XML. Pe
lângă standardele acceptate de Oracle11gAS, mediul Oracle11gDS

83
oferă posibilitatea modelării UML integrate. Acest standard perminte
construirea de modele vizuale, conform cărora se poate genera cod
util în implementarea aplicaţiilor şi a serviciilor Web.
Componentele Oracle11g Developer pot fi folosite pentru:
 generarea de servicii Web şi aplicaţii performante care
pot rula pe diferite tipuri de dispozitive;
 extinderea aplicaţiilor tranzacţionale cu funcţionalităţi
de tip business intelligence (interogări ad-hoc,
rapoarte Web complexe), de publicare şi analiză a
datelor
 dezvoltarea rapidă de aplicaţii folosind tehnologia
Rapid Application Development
 crearea de aplicaţii de tip e-business integrate, bazate
în totalitate pe mediul Internet etc.

Fig.2.18 Componentele platformei Oracle Developer Suite


Componente pentru crearea de aplicaţii: JDeveloper,
Designer, Forms Developer, Software Configuration Manager .
Oracle11g JDeveloper asigură un cadru de dezvoltare
integrat cu Java, XML şi SQL care permite crearea, depanarea şi
instalarea rapidă a aplicaţiilor de tip e-business şi a serviciilor Web
care pot rula pe orice sistem de operare. De asemenea, Oracle11g
Jdeveloper introduce două modele UML, modelarea activităţilor şi a
claselor. Modelarea activităţilor oferă un mod simplu pentru
definirea proceselor de afaceri, iar modelarea claselor permite
dezvoltarea aplicaţiilor necesare pentru implementarea acestor
procese. Modelele UML permit generarea claselor java prin care se

84
implementează servicii Web şi se asigură publicarea, rularea şi
accesrea acestora direct dintr-o diagramă de clase UML.
Oracle11g Designer este pachetul de utilitare cu generator
integrat pentru proiectarea şi dezvoltarea de aplicaţii complexe.
Componentele sale permit descrierea şi analiza modelului,
proiectarea diagramei entitate/relaţie şi de aplicaţii orientate pe
obiecte.
Oracle11g Forms Developer este utilitar ce foloseşte
tehnologia RAD, cu ajutorul căruia se construiesc uşor şi rapid
aplicaţii ce interacţionează cu informaţiile bazei de date (forme
interactive şi grafice). Utilitarul este orientat pe evenimente,
permiţând definirea prin PL/SQL a acţiunii ce se va executa la
apariţia unui anumit eveniment. Utilizând tehnologia Java, aplicaţiile
pot include legături web şi butoane cu funcţionalităţi complexe.
Pentru dezvoltarea de aplicaţii complexe, sistemul oferă
precompilatoarele Pro* ( C/C++, PL/l, COBOL, ADĂ, FORTRAN şi
Pascal) care permit încorporarea de instrucţiuni SQL sau blocuri
PL/SQL în module scrise utilizând alte limbaje de programe.
Precompilarea citeşte codul sursă şi generează un fişier ce poate fi
procesat de către compilatorul limbajului respectiv.
Folosirea precompilatoarelor Oracle permite:
 Dezvolatrea aplicaţiilor de baze de date în
limbajul de nivel înalt;
 Utilizarea tehnicilor de programare avansată;
 Dezvoltarea de aplicaţii cu un grad înalt de
personalizare;
 Verificarea sintactică şi semantica a
comenzilor SQL şi a blocurilor PL/SQL;
 Precompilare separata a mai multor module de
cod şi apoi înglobarea acestora într-un singur
program executabil;
 Specificarea optiunilor de precompilare;
 Accesul concurent la baze de date Oracle din
locaţii diferite etc.

85
CapitoluI IV. LIMBAJUL DE
DEFINIRE, INTEROGARE ŞI
MANIPULARE A BAZELOR
DE DATE SQL
3.1. Evoluţie şi performanţe
SQL reprezintă cel mai important limbaj actual în domeniul
bazelor de date prin gama comenzilor şi opţiunilor de care dispune,
dar mai ales datorită faptului că s-a reuşit standardizarea lui şi
portarea pe toate sistemele de gestiune a bazelor de date
semnificative.
Încă din anul 1970, E.F.Codd a sugerat "adoptarea unui
model relaţional pentru organizarea datelor [...] care să permită
punerea la punct a unui sub-limbaj universal pentru gestiunea
acestora, sub-limbaj care să fie, în fapt, o formă aplicată de calcul
asupra predicatelor".
După mulţi autori, momentul decisiv în naşterea SQL ca
limbaj îl constituie lansarea proiectului System/R de către firma IBM,
eveniment ce a avut loc în 1974. Tot în 1974 Chamberlin şi Boyce au
publicat un articol în care este prezentat un limbaj structurat de
interogare, denumit SEQUEL (Structured English as QUEry
Language). În 1975 Chamberlin, Boyce, King şi Hammer redactează
o lucrare dedicată sub-limbajului SQUARE, asemănător SEQUEL-
ului, dar care utiliza expresii matematice şi nu cuvinte din limba
engleză. Autorii celor două studii au demonstrat că limbajele
SEQUEL şi SQUARE sunt complete din punct de vedere relaţional.
În 1976 un colectiv de autori condus de Chamberlin
elaborează o nouă lucrare în care se face referire la SEQUEL 2,
acesta fiind declarat limbaj de interogare al SGBD-ului System/R al
firmei IBM.

86
În 1980 Chamberlin schimbă denumirea SEQUEL în SQL -
Structured Query Language (Limbaj Structurat de Interogare), din
motive legale (s-a descoperit că acronimul SEQUEL fusese utilizat
anterior de altcineva), dar şi astăzi mulţi specialişti pronunţă SQL ca
pe predecesorul său.
Anii următori au înregistrat apariţia a o serie întreagă de
lucrări dedicate SQL care l-au perfecţionat şi consacrat ca pe cel mai
răspândit limbaj de interogare a bazelor de date relaţionale, fiind
prezent în numeroase "dialecte" specifice tuturor SGBDR-urilor
actuale, de la DB2 la Microsoft SQL Server, de la Oracle la FoxPro
şi Access.
Încercând să răspundă solicitărilor pentru standardizarea
unui limbaj de lucru cu bazele de date, Institutul Naţional American
pentru Standarde (American National Standard Institute - ANSI) a
început să realizeze în 1982 un limbaj relaţional pentru bazele de
date, bazat pe un articol conceptual al firmei IBM. În 1986 ANSI
publică standardul SQL ANSI X3.135-1986, standard care se
bazează, într-o mare măsură, pe "dialectul" SQL al produsului DB2
de la IBM. Organizaţia Internaţională pentru Standarde (ISO) a
adoptat propriul document, aproape identic cu ANSI SQL-86, pe
care l-a publicat în 1987 ca ISO 9075-1987 Database Language SQL.
SQL-86 defineşte comenzile de bază ale SQL, inclusiv pentru
crearea de tabele şi tabele virtuale (CREATE TABLE, CREATE
VIEW), însă nu conţine opţiuni de modificare a structurii sau
ştergere (ALTER…/DROP…) şi nici comenzi pentru acordare şi
revocare a drepturilor utilizatorilor.
În 1989 are loc revizuirea şi extinderea acestui standard,
"născându-se" SQL-89, care mai este denumit şi SQL-1.
Deşi recunoscut ca bază a multor SGBDR-uri comerciale,
SQL-1 şi-a atras numeroase critici. În plus, variantele comercializate
de diferiţii producători, deşi asemănătoare în esenţă, erau (şi sunt)
incompatibile la nivel de detaliu. Pentru a umple golurile SQL-1,
ANSI şi ISO au elaborat în 1992 versiunea SQL-2, specificaţiile
fiind prezentate la un nivel mult mai detaliat (dacă SQL-1 se întindea
pe numai 100 de pagini, SQL-2 a fost publicat în aproape 600).
Dintre numeroasele facilităţi aduse de SQL-92 amintim: joncţiunea
externă (OUTER JOIN), atribute zi-oră şi de alte tipuri, raportare
standardizată a erorilor, modificarea schemei bazei de date (DROP,
87
ALTER, REVOKE, GRANT), SQL dinamic, modificări şi ştergeri
referenţiale în cascadă, amânarea verificării restricţiilor, niveluri de
consistenţă a tranzacţiilor etc.
Pe lângă ANSI, ale cărui standarde au cea mai largă
audienţă, mai există şi alte organisme de standardizare SQL. X/Open
este un grup de firme vest-europene care a adoptat SQL ca nucleu al
unei întregi serii de standarde menite să asigure realizarea unui
mediu general pentru aplicaţii portabile, grefat pe sistemul de operare
UNIX.
IBM a avut un aport incontestabil la apariţia şi maturizarea
SQL, fiind un producător cu mare influenţă în lumea SGBD-urilor,
iar produsul său, DB2, este unul din standardele de facto ale SQL.
În 1989 un grup de producători de instrumente dedicate
bazelor de date au format SQL Access Group, în vederea realizării
conexiunilor dintre SGBDR-urile fiecăruia, pe baza unor specificaţii
comune, din care un prim set a fost publicat în 1991 sub titulatura
RDA (Remote Database Access). Specificaţiile RDA n-au reuşit să
se impună pe piaţa SGBD-urilor.
La insistenţele firmei Microsoft, SQL Access Group şi-a
concentrat eforturile pentru elaborarea unei interfeţe-standard pentru
SQL. Pe baza unui set de propuneri înaintat de Microsoft, în 1992 au
rezultat specificaţiile CLI (Call Level Interface). Acestea reprezintă
un ansamblu de funcţii şi proceduri pentru conectarea bazelor de date
prin SQL în medii multi-utilizator şi multi-platformă. Având drept
reper CLI, Microsoft elaborează şi implementează în acelaşi an un
set propriu, ODBC (Open DataBase Conectivity), care a devenit
standard în materie de interfaţă SQL pentru microcalculatoare
compatibile IBM PC în vederea accesării bazelor de date relaţionale.
Standardul SQL:1999, denumit iniţial SQL3, are ca
principale orientări: transformarea acestuia într-un limbaj complet, în
vederea definirii şi gestionării obiectelor complexe şi persistente.
Aceasta include: generalizare şi specializare, moşteniri multiple,
polimorfism, încapsulare, tipuri de date definite de utilizator, triggere
şi proceduri stocate, suport pentru sisteme bazate pe gestiunea
cunoştinţelor, expresii privind interogări recursive şi instrumente
adecvate de administrare a datelor.

88
Standardul SQL:2003 are drept caracteristici majore:
caracteristici legate de XML, funcţii window, secvenţe standardizate
şi coloane cu valori auto-generate (incluzând coloane-identitate).
Standardul SQL:2006 defineşte căi prin care SQL poate fi
utilizat împreună cu XML, căi de a importa şi stoca date XML într-o
bază de date SQL, de a le manipula în cadrul acelei baze de date şi de
a le publica.
Din punctul de vedere al utilizatorului final, obiectivul
principal al SQL constă în a oferi utilizatorului mijloacele necesare
formulării unei consultări numai prin descrierea rezultatului dorit, cu
ajutorul unei expresii logice, fără a fi necesară şi explicitarea
modului efectiv în care se face căutarea în baza de date. Altfel spus,
utilizatorul specifică rezultatul, iar sistemul se ocupă de procedura
de căutare.
Deşi este considerat, în primul rând, un limbaj de interogare,
SQL este mult mai mult decât un instrument de consultare a bazelor
de date, deoarece permite, în egală măsură:
 definirea datelor;
 consultarea bazei de date;
 manipularea datelor din bază;
 controlul accesului;
 partajarea bazei între mai mulţi utilizatori ai acesteia;
 menţinerea integrităţii bazei de date.
După Groff şi Weinberg, principalele atuuri ale SQL sunt:
 Independenţa de producător, nefiind o tehnologie
proprietară;
 Portabilitate între diferite sisteme de operare;
 Este standardizat;
 "Filosofia" sa se bazează pe modelul relaţional de
organizare a datelor;
 Este un limbaj de nivel înalt, cu o structură care se apropie
de limba engleză;
 Furnizează răspunsuri la numeroase interogări simple, ad-
hoc, neprevăzute iniţial;
 Constituie suportul programatic pentru accesul la baza de
date;
 Permite multiple imagini asupra datelor bazei;

89
 Este un limbaj relaţional complet;
 Permite definirea dinamică a datelor, în sensul modificării
structurii bazei chiar în timp ce o parte din utilizatori sunt
conectaţi la baza de date;
 Constituie un excelent suport pentru implementarea
arhitecturilor client-server.
Limbajul SQL constituie un exemplu de limbaj orientat spre
tansformări sau limbaj proiectat să utilizeze relaţiile pentru a
transforma intrările în ieşirile cerute. Ca limbaj, SQL are două
componente principale:
- un limbaj de definire a datelor pentru definirea structurii
bazei de date (DDL)
- un limbaj de manipulare a datelor (DML) pentru regăsirea şi
reactualizarea datelor.
Limbajul SQL conţine numai comenzi de definire şi manipulare
şi nu conţine comenzi de flux de control. Cu alte cuvinte nu există
comenzi IF…THEN…ELSE, GO TO, DO…WHILE sau alte
comenzi care să ofere un flux de control. Acestea trebuie
implementate prin utilizarea unui limbaj de programare sau de
control al lucrărilor sau interactiv prin decizii ale utilizatorului.
Datorită acestui fapt, limbajul SQL poate fi utilizat în două moduri.
Prima modalitate este de a folosi limbajul SQL interactiv, prin
introducerea instrucţiunilor de la un terminal. A doua este de a
integra instrucţiunile SQL într-un limbaj procedural.
SQL este un limbaj relativ uşor de învăţat:
 Este un limbaj neprocedural - se specifică ce informaţii sunt
cerute şi nu cum sunt obţinute (limbajul SQL nu necesită
specificarea metodelor de acces la date).
 SQL este un limbaj modern, cu format liber, ceea ce înseamnă că
nu este necesar ca fragmentele de comenzi să fie scrise în
anumite locuri de pe ecran. Totuşi o comandă (sau un set de
comenzi SQL) este mai lizibilă dacă se foloseşte indentarea şi
alinierea. De exemplu:
- fiecare clauză din cadrul unei comenzi trebuie să înceapă pe
o linie nouă;
- începutul fiecărei clauze trebuie să fie aliniat cu începutul
celorlalte;

90
- dacă o clauză are mai multe părţi, fiecare dintre ele trebuie să
apară pe câte o linie separată şi trebuie să fie indentată faţă
de începutul clauzei pentru a indica relaţia.
 Structura comenzilor constă în cuvinte standard din limba
engleză, cum ar fi CREATE TABLE, INSERT; SELECT.
 Limbajul SQL poate fi folosit de o gamă largă de utilizatori,
inclusiv administratorii de baze de date, programatorii de
aplicaţii şi alte tipuri de utilizatori.
SQL este primul şi deocamdată singurul limbaj de baze de date
standardizat care se bucură de o acceptare largă.
Cele mai multe "dialecte" SQL admit următoarele tipuri de date:
 SMALLINT: întregi - scurte (4 poziţii, reprezentate pe 16
biţi),
 INTEGER sau INT: întregi - lungi (9 poziţii, 32 biţi),
 NUMERIC(m,n) sau DECIMAL(m,n) sau DEC(m,n) -
reale, cu un total de m poziţii, din care n la partea
fracţionară,
 FLOAT: reale, virgulă mobilă (20 poziţii pentru mantisă),
 REAL : real, virgulă mobilă
 DOUBLE PRECISION: reale, virgulă mobilă, dublă
precizie (30 poziţii pentru mantisă),
 CHAR(n) sau CHARACTER(n): şir de caractere de
lungime n (max. 240),
 VARCHAR(n) sau CHAR VARYING(n) sau
CHARACTER VARYING(n): şir de caractere de lungime
variabilă (max. 254),
 DATE: dată calendaristică
 TIME: ora
 TIMESTAMP: an, lună, zi, ora, minutul, secunda, plus o
fracţiune zecimală dintr-o secundă.
Principalele comenzi ale SQL, care se regăsesc, într-o formă
sau alta, în multe dintre SGBDR-urile actuale sunt următoarele:

91
Tabelul nr. 3.1. Clase de comenzi SQL
Comandă Scop
Pentru manipularea datelor
SELECT Extragerea datelor din baza de date
INSERT Adăugarea de noi linii într-o tabelă
DELETE Ştegerea de linii dintr-o tabelă
UPDATE Modificarea valorilor unor atribute

Pentru definirea bazei de date


CREATE TABLE Adăugarea unei noi tabele în baza de
date
DROP TABLE Ştergerea unei tabele din bază
ALTER TABLE Modificarea structurii unei tabele
CREATE VIEW Crearea unei tabele virtuale
DROP VIEW Ştergerea unei tabele virtuale

Pentru controlul accesului la BD


GRANT Acordarea unor drepturi pentru utilizatori
REVOKE Revocarea unor drepturi pentru utilizatori

Pentru controlul tranzacţiilor


COMMIT Marchează sfârşitul unei tranzacţii
ROLLBACK Abandonează tranzacţia în curs

92
3.2. Comenzi pentru descrierea datelor. Limbajul
DDL (Data Description Language)
Comanda SQL utilizată pentru crearea unei tabele este
CREATE TABLE. Aceasta creează o tabelă vidă (fără linii), cu o
anumită structură.

CLIENŢI
C NumeCli Adres Localitate
odClie ent a
nt
1001 TEXTILA SA Bld. Copou, Iaşi
87
1002 MODERN SRL Bld. Gării, 22 Focşani
1003 OCCO SRL NULL Iaşi
1004 FILATURA SA Bld. Unirii, Focşani
145
1005 INTEGRATA I.V.Viteazu, Paşcani
SA 115
1006 AMI SRL Galaţiului, 72 Bacău
1007 AXON SRL Silvestru, 2 Iaşi
1008 ALFA SRL Prosperităţii, Paşcani
15

FACTURIEMISE
Nr C Data Valoa TVA
Factură odClien Factură reTotală Colectată
t
111111 1003 17.06. 2017 1700 271.42
111112 1001 17.06.2017 285 45.5

93
111113 1004 18.06.2007 585 93.4
111114 1003 18.06.2007 2850 455.04
111115 1008 18.06.2007 3570 570
111116 1008 19.06.2007 870 138.9
111117 1006 20.06.2007 1100 175.63
111118 1007 23.06.2007 1500 239.49
111119 1005 24.06.2007 4725 754.41
111120 1003 24.06.2007 300 47.89
111121 1001 24.06.2007 425 67.85
111122 1007 24.06.2007 875 139.7
111123 1006 25.06.2007 660 105.3
111124 1004 25.06.2007 3850 614.7
111125 1003 30.06.2007 1280 204.37
111126 1002 01.07.2007 5425 866.17
Fig. nr. 3.1. Baza de date utilizată în exemple

De exemplu, pentru crearea tabelei CLIENŢI, comanda se scrie


astfel:
CREATE TABLE CLIENŢI
(CodClient decimal (7) not NULL,
NumeClient char(25) not NULL,
Adresa char(30),
Localitate char(25),
PRIMARY KEY (CodClient))
Atributul CodClient este de tip numeric, valoarea sa fiind
reprezentată pe şapte poziţii. Celelalte atribute conţin şiruri de
caractere. Valorile pentru CodClient şi NumeClient sunt diferite de
NULL. Cheia primară a relaţiei este atributul CodClient.
Există posibilitatea adăugării ulterioare a unui nou atribut la cele
existente, ştergerii unui atribut sau de modificare a tipului sau
lungimii sale. Operaţiunea nu este atât de frecventă, fiind
recomandabil să se desfăşoare cât mai rar; o bună analiză desfăşurată
în faza de proiectare a bazei de date elimină, de obicei, acest gen de
probleme.
Dacă în tabela CLIENŢI se doreşte păstrarea şi a codului fiscal
al fiecărui furnizor, este necesară adăugarea atributului CodFiscal,
care este un şir de caractere (un număr precedat de litera R, dacă
94
clientul respectiv este plătitor de TVA) de lungime 10 caractere.
Comanda utilizată este ALTER TABLE, astfel:

ALTER TABLE CLIENŢI


ADD CodFiscal char(10)
SQL permite declararea cheilor primare, candidate şi a
coloanelor de referinţă (chei străine). Dacă stabilim că, pentru tabela
CLIENŢI, cheia primară este atributul CodClient, iar atributul
NumeClient este cheie candidată, comanda se poate scrie sub forma:

CREATE TABLE CLIENŢI


(CodClient decimal (7) not NULL,
NumeClient char(25) not NULL,
Adresa char(30),
Localitate char(25) ,
PRIMARY KEY (CodClient)
UNIQUE (NumeClient))
Cheile străine sunt declarate cu ajutorul opţiunii FOREIGN
KEY. Pentru tabela FACTURIEMISE, cheia primară este atributul
NrFactură, în timp ce CodClient este cheie străină către tabela
CLIENŢI:

CREATE TABLE FACTURIEMISE


(NrFactură decimal (8) not NULL,
DataFactură date,
CodClient decimal (7) not NULL,
ValoareTotala decimal (15) not NULL,
TVAColectata decimal (14) ,
PRIMARY KEY (NrFactură),
FOREIGN KEY (CodClient) REFERENCES CLIENŢI)
Ştergerea unei tabele din baza de date este realizabilă cu ajutorul
comenzii DROP TABLE. De obicei, această comandă se utilizează
atunci când pe parcursul lucrului s-au creat tabele intermediare,
temporare. Ştergerea unei asemenea tabele, denumită de exemplu
TEMP1, se declanşează prin comanda:
DROP TABLE TEMP1

95
3.3. Comenzi pentru interogarea bazelor de date.
Fraza Select

În SQL o interogare se formulează printr-o frază SELECT.


Aceasta prezintă trei clauze principale: SELECT, FROM şi WHERE.
 SELECT corespunde operatorului proiecţie din algebra
relaţională, fiind utilizată pentru desemnarea listei de atribute
(coloanele) din tabela-rezultat;
 FROM este cea care permite enumerarea relaţiilor din care vor fi
extrase informaţiile aferente consultării;
 prin WHERE se desemnează predicatul selectiv al algebrei
relaţionale, relativ la atribute ale relaţiilor care apar în clauza
FROM.
La modul general (şi simplist) o consultare simplă în SQL poate
fi prezentată astfel:
SELECT C1, C2, ..., Cn
FROM R1, R2, ..., Rm
WHERE P
Execuţia unei fraze SELECT se conc1retizează în obţinerea unei
tabele (relaţii) rezultat. Acestă poate fi o tabelă propriu-zisă sau o
tabelă temporară (care, de obicei, nu poate fi actualizată), dar şi o
tabelă derivată (imagine). Uneori tabela rezultat poate fi obţinută sub
forma unei variabile-tablou.
Ci - reprezintă coloanele (care sunt atribute sau expresii de
atribute) tabelei-rezultat;
Rj - sunt relaţiile ce trebuie parcurse pentru obţinerea
rezultatului;
P - este predicatul (condiţia) simplu sau compus ce trebuie
îndeplinit de tupluri pentru a fi incluse în tabela-rezultat.
Când clauza WHERE este omisă, se consideră implicit că
predicatul P are valoarea logică "adevărat".
Dacă în locul coloanelor C1, C2, ... Cn apare simbolul "*", în
tabela-rezultat vor fi incluse toate coloanele (atributele) din toate

96
relaţiile specificate în clauza FROM. De asemenea, în tabela-rezultat,
nu este obligatoriu ca atributele să prezinte nume identic cu cel din
tabela enumerată în clauza FROM. Schimbarea numelui se realizează
prin opţiunea AS .
Rezultatul unei fraze SELECT îl vom considera ca fiind sub
forma unei tabele oarecare. Trebuie avute în vedere, însă, că
rezultatul interogării poate fi obţinut şi sub forma unei tabele
temporare sau chiar a unei variabile-tablou (matrice). În unele
SGBD-uri, cum ar fi FoxPro, formatul general al frazei SELECT
conţine şi clauza INTO.
SELECT …
FROM …
INTO destinaţie
WHERE…
În destinaţie poate fi specificată o tabelă "normală", o tabelă
temporară (tabelă care se şterge automat la închiderea sa) sau o
variabilă-tablou. Dacă clauza INTO nu este utilizată, atunci în urma
interogării se obţine o tabelă temporară cu numele predeterminat
(Query).
Uneori, tabela rezultat ("normală" sau temporară) "încalcă"
poruncile modelului relaţional. Conform restricţiei de entitate, într-o
relaţie nu pot exista două linii identice. Or, în SQL, tabela obţinută
dintr-o consultare poate conţine două sau mai multe tupluri identice.
Spre deosebire de algebra relaţională, în SQL nu se elimină
automat tuplurile identice (dublurile) din tabela-rezultat. Pentru
aceasta este necesară utilizarea opţiunii DISTINCT:
SELECT DISTINCT C1, C2, ..., Cn
FROM R1, R2, ..., Rm
WHERE P
În concluzie, o frază SELECT, în forma în care a fost
prezentată, corespunde:
 unei selecţii algebrice (clauza WHERE - P)
 unei proiecţii (SELECT - Ci)
 unui produs cartezian (FROM - R1  R2  ...  Rm)
şi conduce la obţinerea unei noi relaţii (tabele-rezultat) cu n
coloane, fiecare coloană fiind:
 un atribut din R1, R2, ..., Rm sau

97
 o expresie calculată pe baza unor atribute din R1, R2, ...,
Rm.

Exemplu

Care este, pentru fiecare factură emisă, valoarea fără TVA ?


SELECT NrFactură, ValoareTotală - TVAColectata
AS ValoareFaraTVA
FROM FACTURIEMISE
Tabela rezultat din fig. nr. 4.2 va conţine două atribute:
NrFactură şi ValoareFaraTVA. Ultimul este un câmp calculat.
Rezultat:
NrFactură ValoareFaraTVA
111111 1428.58
111112 239.50
111113 491.6
111114 2394.96
111115 3000
111116 731.1
111117 924.37
111118 1260.51
111119 3970.59
111120 252.11
111121 357.15
111122 735.3
111123 554.7
111124 3235.3
111125 1075.63
111126 4558.83
Fig. nr. 3.2. Exemplu de câmp calculat (ValoareFaraTVA)

98
3.3.1 Interogări care utilizează operatorii asamblişti din
algebra relaţională

Reuniunea
SELECT *
FROM R1
UNION
SELECT *
FROM R2
Operatorul pentru reuniune este deci UNION. De remarcat că, la
reuniune, SQL elimină automat dublurile, deci nu este necesară
utilizarea clauzei DISTINCT. Operatorul UNION este prezent în
toate SGBD-urile importante.

Intersecţia
Pentru realizarea intersecţiei a două tabele, R1 şi R2 se
utilizează operatorul INTERSECT:
SELECT *
FROM R1
INTERSECT
SELECT *
FROM R2
Dacă în produsele profesionale, precum DB2 sau Oracle,
operatorul este prezent, în altele, precum Visual FoxPro,
INTERSECT rămâne un deziderat, funcţionalitatea sa realizându-se
prin subconsultări (operatorii IN şi EXISTS) sau, uneori, prin
joncţiune.

Diferenţa
Diferenţa dintre tabelele R1 şi R2 se realizează utilizând
operatorul MINUS sau EXCEPT. Fraza SELECT următoare
funcţionează în Oracle.

SELECT *

99
FROM R1
MINUS
SELECT *
FROM R2

Produsul cartezian
În SQL nu există operator explicit pentru efectuarea produsului
cartezian. Dacă în clauza FROM apar două relaţii, R1 şi R2, atunci,
în lipsa unei condiţii de joncţiune formulată în clauza WHERE,
tabela rezultat va conţine liniile obţinute din produsul cartezian R1
 R2.
SELECT *
FROM R1, R2

3.3.2 Interogări care utilizează operatorii relaţionali din


algebra relaţională

a. Selecţia

Exemplul 1
Care dintre facturile emise după 23.06.2007 prezintă valoarea
mai mare de 3000 lei ?
SELECT *
FROM FACTURIEMISE
WHERE DataFactură > {23.06.2007} AND
ValoareTotala > 3000
Rezultat:
NrFactu CodCli DataFactur ValoareTot TVAColec
ră ent ă ală tată
111119 1005 24.06.2007 4725 754.41
111124 1004 25.06.2007 3850 614.7
111126 1002 01.07.2007 5425 866.17

100
Operatorul AND a fost utilizat pentru a introduce un "ŞI" logic,
după cum OR se utilizează pentru “SAU” logic. În SQL, pentru
comparare, în afara "clasicilor": >, >=, <, <=, =,  (<>), mai pot fi
utilizaţi şi alţi operatori, dintre care în acest paragraf ne vom opri la:
BETWEEN (între, cuprins între),
LIKE (ca şi, la fel ca),
IN (în) şi
IS NULL.
Operatorul BETWEEN
Acest operator permite specificarea unui interval de valori în
care trebuie să se încadreze câmpul sau expresia testată. Intervalul se
referă la valori numerice sau la date calendaristice.
Exemplul 2
Care sunt facturile emise după 23.06.2007 şi care au valoarea
cuprinsă între 3000 şi 4000 lei ?
Fără operatorul BETWEEN fraza SELECT se scrie:
SELECT *
FROM FACTURIEMISE
WHERE DataFactură > {23.06.2007} AND
ValoareTotala >= 3000 AND ValoareTotala <=
4000
Utilizând operatorul BETWEEN se poate scrie:
SELECT *
FROM FACTURIEMISE
WHERE DataFactură > {23.06.2007} AND
ValoareTotala BETWEEN 3000 AND 4000
Operatorul LIKE
Acest operator se foloseşte pentru a compara un atribut de tip şir
de caractere (de exemplu NumeClient, Adresa, Localitate) cu un
literal (constantă de tip şir de caractere). Astfel, dacă se doreşte
obţinerea unei tabele-rezultat care să conţină numai clienţii ai căror
nume începe cu litera M, putem scrie predicatul din clauza WHERE
sub forma: NumeClient LIKE "M%". Deoarece după litera M apare
semnul "%", se vor extrage din tabela CLIENŢI toate tuplurile
pentru care valoarea atributului NumeClient începe cu litera M,
indiferent de lungimea acestuia (ex. MELCRET, MIGAS, MITA,
101
MATSUSHITA etc.). Despre semnul "%" se spune că este un
specificator multiplu, joker sau mască.
Un alt specificator multiplu utilizat în multe versiuni SQL este
liniuţa de subliniere ("_"). Spre deosebire de "%", "_" substituie un
singur caracter. Diferenţa dintre cei doi specificatori multipli este
pusă în evidenţă în exemplele următoare.

Exemplul 3
Care sunt clienţii ai căror nume este format din şapte caractere,
începe cu litera A şi sunt societăţi cu răspundere limitată (SRL-uri) ?
SELECT *
FROM CLIENŢI
WHERE NumeClient LIKE "A__ SRL"

Rezultat:
CodC NumeClient Adresa Localitate
lient
1006 AMI SRL Galaţiului, 72 Bacău

Exemplul 4
Dacă în exemplu 3 s-ar fi utilizat simbolul "%":
SELECT *
FROM CLIENŢI
WHERE NumeClient LIKE "A%SRL",
am fi obţinut:
Rezultat:
CodCli NumeClient Adresa Localitat
ent e
1006 AMI SRL Galaţiului, 72 Bacău
1007 AXON SRL Silvestru, 2 Iaşi
1008 ALFA SRL Prosperităţii, 15 Paşcani
În concluzie, "_" înlocuieşte (substituie) un singur caracter, în
timp ce "%" înlocuieşte un şir de caractere de lungime variabilă
(între 0 şi n caractere). Cei doi specificatori multipli pot fi utilizaţi
împreună.

102
Operatorul IN
Format general:
expresie1 IN (expresie2, expresie3, ...)
Rezultatul evaluării unui predicat ce conţine acest operator va fi
"adevărat" dacă valoarea expresiei1 este egală cu (cel puţin) una din
valorile: expresie2, expresie3, ... Este util atunci când condiţiile de
selecţie sunt mai complexe.

Exemplul 5
Care sunt clienţii din Iaşi şi Bacău ?
Fără utilizarea operatorului IN se scrie:
SELECT *
FROM CLIENTI
WHERE Localitate= "Iaşi" OR Localitate=
"Bacău”
Utilizând operatorul IN:
SELECT *
FROM CLIENTI
WHERE Localitate IN ("Iaşi", "Bacău)
Rezultat
C Nume Adresa Localitate
odClie Client
nt
1001 TEXTILA Bld. Copou, 87 Iaşi
SA
1003 OCCO SRL NULL Iaşi
1006 AMI SRL Galaţiului, 72 Bacău
1007 AXON SRL Silvestru, 2 Iaşi

Operatorul IS NULL
O valoare nulă este o valoare nedefinită. Este posibil ca la
adăugarea unei linii într-o tabelă valorile unor atribute să fie
necunoscute. În aceste cazuri valoarea atributului pentru tuplul

103
respectiv este nulă. Reamintim că, prin definiţie, nu se admit valori
nule pentru grupul atributelor care constituie cheia primară a relaţiei.

Exemplul 6
Dacă se doreşte aflarea clienţilor pentru care nu s-a introdus
adresa, se poate scrie:
SELECT *
FROM CLIENTI
WHERE Adresa IS NULL

Rezultat:
CodCli NumeClient Adresa Localitate
ent
1003 OCCO SRL NULL Iaşi

Observaţii
 Valoarea NULL nu se confundă cu valoarea zero (pentru
atributele numerice) sau cu valoarea "spaţiu" (pentru atributele
de tip şir de caractere)
 Operatorul NULL se utilizează cu IS şi nu cu semnul "=". Dacă
s-ar utiliza forma expresie = NULL şi nu expresie IS NULL,
rezultatul evaluării va fi întotdeauna fals, chiar dacă expresia nu
este nulă.

b. Proiecţia. Opţiunea ORDER BY

Coloanele tabelei-rezultat al consultării sunt specificate în


clauza SELECT, fiind separate prin virgulă.

Exemplul 1
Care sunt localităţile în care firma are clienţi ?
Este necesară parcurgerea relaţiei CLIENTI, singurul atribut
care interesează fiind Localitate. Deoarece SQL nu elimină dublurile
automat, dacă se doreşte ca în tabela-rezultat o localitate să figureze
o singură dată, se utilizează opţiunea DISTINCT:
SELECT DISTINCT Localitate

104
FROM CLIENTI

Rezultat:
Localitate
Iaşi
Focşani
Bacău
Paşcani

Prezentarea localităţilor în ordinea alfabetică a numelui acestora


este posibilă apelând la clauza ORDER BY.
SELECT Localitate
FROM CLIENTI
ORDER BY Localitate DESCENDING
Opţiunile ASCENDING (crescător) şi DESCENDING
(descrescător) indică modul în care se face ordonarea tuplurilor
tabelei-rezultat al interogării.
Prioritatea de ordonare este stabilită prin ordinea atributelor
specificate în ORDER BY: ordonarea "principală" se face în funcţie
de valorile primului atribut specificat; în cadrul grupelor de tupluri
pentru care valoarea primului atribut este identică, ordinea se
stabileşte după valoarea celui de-al doilea atribut specificat ş.a.m.d.
Dacă în ORDER BY lipsesc opţiunile
ASCENDING/DESCENDING, ordonarea se face implicit crescător.

c. Joncţiunea
SQL nu prezintă clauze sau operatori speciali pentru realizarea
theta-joncţiunii, echi-joncţiunii sau joncţiunii naturale. Dar, aşa cum
am văzut, o joncţiune este o combinaţie de produs cartezian şi
selecţie.

Exemplu:
Care sunt facurile emise clienţilor din municipiul Iaşi ?
SELECT NrFactura, NumeClient, Localitate
FROM FACTURIEMISE, CLIENŢI

105
WHERE FACTURIEMISE.CodClient =
CLIENŢI.CodClient
AND Localitate=”Iaşi”
sau
SELECT NrFactura, NumeClient, Localitate
FROM FACTURIEMISE INNER JOIN CLIENŢI
ON WHERE FACTURIEMISE.CodClient =
CLIENŢI.CodClient
WHERE Localitate=”Iaşi”

Rezultat:
NrFactură NumeClient Localitate
111111 OCCO SRL Iaşi
111112 TEXTILA SA Iaşi
111114 OCCO SRL Iaşi
111118 AXON SRL Iaşi
111120 OCCO SRL Iaşi
111121 TEXTILA SA Iaşi
111122 AXON SRL Iaşi
111125 OCCO SRL Iaşi

d. Sub-consultări. Operatorul IN
O altă facilitate deosebit de importantă a limbajului SQL o
constituie posibilitatea includerii (imbricării) a două sau mai multe
fraze SELECT, astfel încât pot fi formulate interogări cu mare grad
de complexitate.
Operatorul IN poate fi utilizat şi pentru includerea unei fraze
SELECT într-o altă frază SELECT.
Exemplul 1
Care sunt facturile emise în aceeaşi zi în care a fost întocmită
factura 111114 ?
SELECT *
FROM FACTURIEMISE
WHERE DataFactură IN
(SELECT DataFactură

106
FROM FACTURIEMISE
WHERE NrFactură=111114)

Observaţie
Sub-consultarea
SELECT DataFactură
FROM FACTURIEMISE
WHERE NrFactură=111114
are ca rezultat o tabelă alcătuită dintr-o singură coloană
(DataFactură) şi o singură linie ce conţine valoarea atributului
DataFactură pentru factura 111114:
DataFactură
18.06.2007
Clauza WHERE DataFactură IN determină căutarea în tabela
FACTURIEMISE a tuturor tuplurilor (liniilor) care au valoarea
atributului DataFactură egală cu una din valorile tuplurilor (în cazul
nostru, egală cu valoarea tuplului) din tabela obţinută prin "sub-
consultare". Cu alte cuvinte, în acest caz WHERE Data IN va
selecta toate facturile pentru care data emiterii este 18.06.2007.
Rezultat:
NrFactură CodClient DataFactură Valoare TVA
Totală Colectată
111113 1004 18.06.2017 585 93.4
111114 1003 18.06.2017 2850 455.04
111115 1008 18.06.2017 3570 570

Exemplul 2
Care sunt facturile emise în alte zile decât cea în care a fost
întocmită factura 111114 ?
SELECT *
FROM FACTURIEMISE
WHERE DataFactură NOT IN
(SELECT DataFactură
FROM FACTURIEMISE
WHERE
NrFactură=111114)

107
S-a utilizat negaţia, testându-se non-apartenenţa la o relaţie
creată printr-o sub-frază SELECT.

Exemplul 3
Care sunt clienţii cărora li s-au trimis facturi întocmite în
aceeaşi zi cu factura 111114 ?
SELECT DISTINCT NumeClient
FROM CLIENŢI
WHERE CodClient IN
(SELECT CodClient
FROM FACTURIEMISE
WHERE DataFactură IN
(SELECT DataFactură
FROM FACTURIEMISE
WHERE
NrFactură=111114))

Am ilustrat modul în care pot fi imbricate (înlănţuite, incluse)


trei fraze SELECT. O altă soluţie pentru rezolvarea aceleaşi
probleme este şi:

SELECT DISTINCT NumeClient


FROM CLIENŢI, FACTURIEMISE
WHERE
CLIENŢI.CodClient=FACTURIEMISE.CodClient
AND DataFactură IN
(SELECT DataFactură
FROM FACTURIEMISE
WHERE NrFactură=111114)

Se poate reţine, ca regulă generală, că aproape orice consultare


poate fi redactată în mai multe moduri, în funcţie de experienţa şi
imaginaţia celui care o formulează.

108
e. Funcţii de agregare (statistice): COUNT, SUM, AVG,
MAX, MIN
Formatul general al unei fraze SELECT ce conţine funcţii
predefinite este:
SELECT funcţia-predefinită1, ... , funcţia-
predefinităN
FROM listă-tabele
WHERE condiţii.
Rezultatul oricărei fraze SELECT este o nouă relaţie (tabelă). În
lipsa opţiunii GROUP BY, dacă în clauza SELECT este prezentă o
funcţie predefinită, tabela rezultat va conţine o singură linie.

Funcţia COUNT contorizează valorile unei coloane, altfel


spus, numără, într-o relaţie, câte valori diferite de NULL are coloana
specificată.

Exemplul 1
Câţi clienţi are firma ?
SELECT COUNT (CodClient) AS Nr_Clienti
FROM CLIENTI

Rezultat:
Nr_Clienti
8

În funcţia COUNT se poate utiliza ca argument, în locul


numelui unei coloane, semnul *; în acest caz se va determina câte
linii are tabela la care se aplică funcţia respectivă.

Exemplul 2
La câţi clienţi s-au trimis facturi ?
SELECT COUNT(*)
FROM CLIENTI
WHERE CodClient IN
(SELECT CodClient
FROM
FACTURIEMISE)

109
Rezultatul corect poate fi însă obţinut şi prin utilizarea clauzei
DISTINCT astfel:
SELECT COUNT (DISTINCT CodClient)
FROM FACTURIEMISE

Funcţia SUM calculează suma valorilor unei coloane.

Exemplul 3
Care este valoarea totală a facturilor emise ?
SELECT SUM (ValoareTotala) AS Total_FE
FROM FACTURIEMISE
Rezultat:
Total_FE
30000

Exemplul 4
Care este totalul valorii facturilor trimise clientului AXON SRL
?
SELECT SUM (ValoareTotala) AS
Total_FE_AXON
FROM FACTURIEMISE, CLIENTI
WHERE FACTURIEMISE.CodClient =
CLIENTI.CodClient
AND NumeClient = "AXON SRL"

Funcţiile MAX şi MIN determină valorile maxime, respectiv


minime ale unei coloane în cadrul unei tabele.

Exemplul 5
Care este cea mai mică valoare a unei facturi emise ?
SELECT MIN(ValoareTotala) AS ValMinima
FROM FACTURIEMISE

Rezultat
ValMinima
285

110
Exemplul 6
Care este factura emisă ce are cea mai mare valoare ?
SELECT NrFactură, ValoareTotala
FROM FACTURIEMISE
WHERE ValoareTotala = (SELECT MAX
(ValoareTotala)
FROM FACTURIEMISE)

Rezultat:
NrFactura ValoareTotala
111126 5425

f. Gruparea tuplurilor. Clauzele GROUP BY şi HAVING

SQL permite utilizarea clauzei GROUP BY pentru a forma


grupe (grupuri) de tupluri ale unei relaţii, pe baza valorilor comune
ale unei coloane. În frazele SELECT formulate până în acest
paragraf, prin intermediul clauzei WHERE au fost selectate tupluri
din diferite tabele.
Prin asocierea unei clauze HAVING la o clauză GROUP BY
este posibilă selectarea anumitor grupe de tupluri ce îndeplinesc un
criteriu.
Rezultatul unei fraze SELECT ce conţine clauza GROUP BY
este o tabelă care va fi obţinută prin regruparea tuturor liniilor din
tabelele enumerate în FROM, care prezintă o aceeaşi valoare pentru
o coloană sau un grup de coloane.
Formatul general este:
SELECT coloană1, coloană2, ...., coloanăm
FROM tabelă
GROUP BY coloană-de-regrupare

Exemplu 1
Care este totalul zilnic al valorii facturilor emise ?
SELECT DataFactură, SUM (ValoareTotala)
FROM FACTURIEMISE

111
GROUP BY DataFactură
În acest caz tabela-rezultat va avea un număr de linii egal cu
numărul de date calendaristice distincte din tabela FACTURIEMISE.
Pentru toate facturile aferente unei zile se va calcula suma valorilor,
datorită utilizării funcţiei SUM(ValoareTotala).
Succesiunea paşilor este următoarea:
1. Se ordonează liniile tabelei FACTURIEMISE în funcţie
de valoarea atributului DataFactură:

NrFact CodClie DataFa ValoareTo TVAColecta


ură nt ctură tala ta
111111 1003 17.06.20 1700 271.42
07
111112 1001 17.06.20 285 45.5
07
111113 1004 18.06.20 585 93.4
07
111114 1003 18.06.20 2850 455.04
07
111115 1008 18.06.20 3570 570
07
111116 1008 19.06.20 870 138.9
07
111117 1006 20.06.20 1100 175.63
07
111118 1007 23.06.20 1500 239.49
07
111119 1005 24.06.20 4725 754.41
07
111120 1003 24.06.20 300 47.89
07
111121 1001 24.06.20 425 67.85
07
111122 1007 24.06.20 875 139.7
07
111123 1006 25.06.20 660 105.37
07
112
111124 1004 25.06.20 3850 614.7
07
111125 1003 30.06.20 1280 204.36
07
111126 1002 01.07.20 5425 866.17
07

2. Se formează câte un grup pentru fiecare valoare


distinctă a atributului DataFactură:
3.
NrFact CodClien DataFac ValoareTot TVAColectat
ură t tură ala a
111111 1003 17.06.20 1700 271.42
07
111112 1001 17.06.20 285 45.5
07
111113 1004 18.06.20 585 93.4
07
111114 1003 18.06.20 2850 455.04
07
111115 1008 18.06.20 3570 570
07
111116 1008 19.06.20 870 138.9
07
111117 1006 20.06.20 1100 175.63
07
111118 1007 23.06.20 1500 239.49
07
111119 1005 24.06.20 4725 754.41
07
111120 1003 24.06.20 300 47.89
07
111121 1001 24.06.20 425 67.85
07
111122 1007 24.06.20 875 139.7
07

113
111123 1006 25.06.20 660 105.37
07
111124 1004 25.06.20 3850 614.7
07
111125 1003 30.06.20 1280 204.36
07
111126 1002 01.07.20 5425 866.17
07

3. Pentru fiecare din cele nouă grupuri se calculează suma


valorilor atributului ValoareTotala.
Tabela - rezultat final va avea nouă linii:
DataFactură SUM(ValoareTo
tala)
17.06.2007 1985
18.06.2007 7005
19.06.2007 870
20.06.2007 1100
23.06.2007 1500
24.06.2007 6325
25.06.2007 4510
30.06.2007 1280
01.07.2007 5425
Exemplul 2
Care este numărul facturilor emise pentru fiecare client ?
SELECT NumeClient, COUNT(NrFactură)
FROM FACTURIEMISE, CLIENTI
WHERE
FACTURIEMISE.CodClient=CLIENTI.CodClient
GROUP BY FACTURIEMISE.CodClient

Observaţie
Până la standardul SQL99 şi publicarea Amendamentului OLAP
la acest standard, în SQL nu puteau fi calculate, prin GROUP BY,

114
subtotaluri pe mai multe niveluri, pentru aceasta fiind necesară
scrierea de programe în SGBD-ul respectiv.

Clauza HAVING permite introducerea unor restricţii care sunt


aplicate grupurilor de tupluri, deci nu tuplurilor "individuale", aşa
cum "face" clauza WHERE. Din tabela rezultat sunt eliminate toate
grupurile care nu satisfac condiţia specificată.
Clauza HAVING "lucrează" împreună cu o clauză GROUP BY,
fiind practic o clauză WHERE aplicată acesteia.
Formatul general este:
SELECT coloană 1, coloană 2, .... , coloană m
FROM tabelă
GROUP BY coloană-de-regrupare
HAVING caracteristică-de-grup

Exemplul 3
Pentru facturile emise interesează valoarea zilnică a acestora
(în funcţie de data la care au fost întocmite, dar numai dacă aceasta
(valoarea zilnică) este de mai mare de cinci mii lei.
SELECT DataFactură, SUM(ValoareTotala)
FROM FACTURIEMISE
GROUP BY DataFactură
HAVING SUM(ValoareTotala) > 5000
La execuţia acestei fraze, se parcurg cei trei paşi prezentaţi
la exemplul 1, apoi, din cele nouă tupluri obţinute prin grupare,
sunt extrase numai cele care îndeplinesc condiţia
SUM(ValoareTotala) > 5000.

Rezultat:
Data SUM(ValoareTotala)
18.06.2007 7005
24.06.2007 6325
01.07.2007 5425

Exemplul 4
Să se afişeze ziua în care s-au întocmit cele mai multe facturi.
SELECT DataFactură

115
FROM FACTURIEMISE
GROUP BY DataFactură
HAVING COUNT(*) >= ALL
(SELECT COUNT(*)
FROM FACTURIEMISE
GROUP BY DataFactură)

Exemplul 5
Care sunt clienţii pentru care s-au întocmit numai două
facturi?
SELECT NumeClient
FROM CLIENTI INNER JOIN FACTURIEMISE
ON
CLIENTI.CODCLIENT=FACTURIEMISE.CODCLIENT
GROUP BY NumeClient
HAVING COUNT(NrFactura)=2
sau
SELECT NumeClient
FROM CLIENTI
WHERE CodClient IN
(SELECT CodClient
FROM FACTURIEMISE
GROUP BY CodClient
HAVING COUNT(NrFactura)=2)

Exemplu 6
Care sunt zilele în care s-au întocmit cel puţin trei facturi?
SELECT DataFact , Count(*) as Nr
FROM FacturiEmise
GROUP BY DataFact
HAVING COUNT(*)>=3

116
5.4. Comenzi pentru actualizarea bazelor de date

SQL prezintă comenzi specifice pentru modificarea conţinutului


unei tabele, înţelegând prin aceasta trei acţiuni prin care se
actualizează baza:
a) adăugarea de noi linii la cele existente într-o tabelă,
b) ştergerea unor linii,
c) modificarea valorii unui atribut.

117
3.4. Comenzi pentru manipularea datelor. Limbajul
DML (Data Manipulation Language)

3.4.1 Adăugarea de înregistrări

Adăugarea de noi linii într-o tabelă se realizează cu


comanda INSERT care are următoarea sintaxă:
Format: INSERT
INTO tabelă [(listă_câmpuri)]
VALUES (listă_valori)
Exemplul 1
Să presupunem că, la un moment dat, întreprinderea vinde
produse şi firmei RODEX SRL care are sediul pe strada Sapienţei,
nr.44 bis, în localitatea Iaşi. Acest nou client trebuie "introdus" în
baza de date, operaţiune care în SQL, se realizează prin comanda:
INSERT
INTO CLIENŢI
VALUES (1009, "RODEX SRL", "Sapienţei, 44
bis", “Iaşi”)
Fraza INSERT de mai sus poate fi scrisă şi sub forma:
INSERT
INTO CLIENŢI (CodClient, NumeClient,
Adresa, Localitate)
VALUES (1009, "RODEX SRL", "Sapienţei 44
bis", "Iaşi").
După cum se observă, după numele tabelei (CLIENŢI) au fost
enumerate toate atributele pentru care se introduc valori prin clauza
VALUES.
Dacă nu s-ar fi cunoscut adresa clientului RODEX, atunci fraza
INSERT ar fi avut forma:
INSERT
INTO CLIENŢI (CodClient, NumeClient,
Adresa, Localitate)
VALUES (1009, "RODEX SRL", NULL, "Iaşi")

118
În noua linie a tabelei CLIENŢI valoarea atributului Adresa va
fi NULL.
Se putea folosi şi forma:
INSERT
INTO CLIENŢI
VALUES (1009, "RODEX SRL", " ", "Iaşi")
În urma execuţiei acestei comenzi, valoarea atributului Adresa
va fi " " (un spaţiu), deci diferită de NULL.

3.4.2 Ştergerea înregistrărilor

Operaţiunea de eliminare a uneia sau mai multor linii dintr-o


tabelă se realizează prin comanda DELETE care are următoarea
sintaxă:
DELETE
FROM nume-tabelă
WHERE predicat
Exemplul 2
Să se elimine din tabela CLIENŢI linia aferentă clientului
MODERN SRL (cod 1002).
DELETE
FROM CLIENŢI
WHERE CodClient = 1002
Exemplu 3
Să se şteargă datele referitoare la facturile emise clienţilor din
oraşul Focşani.
DELETE
FROM FACTURIEMISE
WHERE CodClient IN
(SELECT CodClient
FROM CLIENŢI
WHERE Localitate = "Focşani")
În general, ştergerea unor linii trebuie privită cu multă
circumspecţie, deoarece atunci când linia de şters conţine valori ale
unor atribute ce apar în alte tabele ca şi chei străine, există riscul
pierderii integrităţii referenţiale.

119
Standardul SQL92 permite la crearea unei tabele descrierea
acţiunii care se va derula la ştergerea unei linii părinte în cazul în
care există linii copil. Spre exemplu, se poate refuza ştergerea de linii
din tabela CLIENŢI, dacă la crearea tabelei FACTURIEMISE se
specifică:

CREATE TABLE FACTURIEMISE


(NrFactură decimal (8) not NULL,
DataFactură date,
CodClient decimal (7) not NULL,
ValoareTotala decimal (15) not NULL,
TVAColectata decimal (14) ,
PRIMARY KEY (NrFactură),
FOREIGN KEY (CodClient) REFERENCES
CLIENŢI
ON DELETE RESTRICT)

3.4.3 Modificarea valorilor unor atribute

Pentru modificarea valorilor unuia sau mai multor atribute dintr-


o tabelă, comanda utilizată este UPDATE care are formatul general:
UPDATE tabelă
SET atribut = expresie
WHERE predicat
Ca rezultat, vor fi modificate valorile atributului specificat, noile
valori ale acestuia fiind cele care rezultă în urma evaluării expresiei;
modificarea se va produce pe toate liniile tabelei care îndeplinesc
condiţia specificată în predicat.

Exemplul 4
Noua adresă a clientului Modern SRL este “Bulevardul
Victoriei nr. 21”. Să se opereze modificarea în baza de date.
Se actualizează atributul Adresa din tabela Clienţi.

UPDATE CLIENŢI

120
SET Adresa=“Bulevardul Victoriei nr. 21”
WHERE NumeClient=”Modern SRL”

3.5 Interogarea a unei baze de date Oracle 11g


In acest capitol vom invata despre ragasirea datelor din tabele.
Folosirea comanzi SELECT pentru a accesa date din tabelele bazei
de date. Aceasta operatie este cunoscuta ca interogarea datelor. In
OracleXE, se poate utiliza fie comanda SELECT folosind uneltele
SQL Workshop, fie uneltele Query Builder pentru a construi
interogari folosind o interfata grafica. In acest laborator vom folosi
ambele metode de a construi interogari.

Toate operatiile pe o baza de date Oracle se efctueaza,


folosind constructii SQL.
Comanda SELECT are 3 capabilitati:
1 Selectie: identificarea randurilor
2 Proiectie: identificarea coloanelor
3 Unire: ragasirea datelor din tabele multiple
Pentru a scrie interogari exista doua posibilitati:
1 Folosind instrumentul SQL Workshop pentru a
introduce comenzi SELECT
2 Folosind instrumentul Query Builder pentru a
cosntrui grafic interogari

121
Cand navigati prin menu-ul SQL veti descoperi urmatoarele
instrumente (submenuri):
SQL Commands: cu ajutorul caruia puteti introduce
comenzi cum sunt cele de tipul SELECT
SQL Scripts: cu ajutorul caruia puteti sa executati scripturi
(fisiere) care contin comenzi SQL
Query Builder: poseda un instrument cu ajutorul caruia
puteti sa construiti interogari
3 La folosirea instrumentului SQL Commands
trebuie sa scriem comenzile SQL
4 La folosirea instrumentului Query Builder vom
construi interogari intr-o interfata grafica
Exemplu : creare de interogari care sa afiseza
informatii din tabelele Departamente si Employees.
5 In SQL Commands vom tipari urmatorul script
pentru a afisa informatiile din tabelul Departamente,
apoi veti apasa pe butonul de Run pentru a executa
scriptul; vem putea seta si numarul de inregistrari
afisate in pagina.
SELECT * FROM Departamente;
6 In SQL > Query Builder urmati pasii:
Dati click pe Create
Selectam tabelul pe care doriti sa-l afisam
(in cazul nostru Employees)
Selectam coloanele pe care dorim sa le
afisam
Coloanele selectate sunt afisate in josul
paginii
De asemenea veti putea vizualiza scriptul
SQL generat facand click pe optiunea SQL

122
Pentru a vedea rezultatul interogarii faceti
click pe optiunea Results sau pe butonul
Run

123
CapitoluI IV. LIMBAJUL
PL/SQL

4.1. Introducere
Limbajul SQL (Structured Query Language) este un limbaj
declarativ orientat pe obţinerea de mulţimi de selecţie într-o aplicaţie
în arhitectura client-server. Eficienţa sa este remarcabilă, dar în cazul
în care elementele unei mulţimi de selecţie trebuie accesate pe rând,
nu în grup, utilizarea sa nu mai este posibilă. Pe de alta parte, SQL
nu oferă nici suportul necesar realizării interfeţei unei aplicaţii. În
contrast cu SQL, limbajele procedurale pot manipula linii individuale
dintr-o mulţime de selecţie. Ele dispun de funcţii care permit trecerea
de la o linie la alta şi ramificarea codului în functie de rezultatul
testării valorilor preluate din tabelele bazei de date.

Fig. 4.1 Limbajul PL/SQL


Limbajul PL/SQL (Procedural Language extensions to SQL)
a fost dezvoltat de compania Oracle ca extensie a limbajului
declarativ SQL. PL/SQL este un limbaj de programare procedural
care poate fi folosit pentru descrierea unor prelucrări complexe sau
pentru programarea unor secvenţe de cod care trebuie executate
automat la apariţia unui eveniment (trigger). O caracteristică
remarcabilă a limbajului PL/SQL este faptul că procedurile sau
funcţiile scrise vor fi memorate în baza de date. Aceleaşi prelucrări

124
pot fi realizate de regulă şi în cadrul aplicaţiilor client care accesează
datele din baza, dar în cazul modificării unei metode de calcul
trebuie refăcute aplicaţiile client afectate şi suportate toate costurile
pe care le implică redistribuirea unor noi versiuni ale aplicaţiilor
client.
Având în vedere faptul că de multe ori aplicaţiile din
domeniul bazelor de date sunt în arhitectura client-server şi aplicaţia
client accesează aplicaţia server prin intermediul unei reţele,
utilizarea pe cât posibil a procedurilor scrise în PL/SQL poate
ameliora semnificativ viteza de prelucrare. În cazul unei proceduri
care ar implica transferul spre aplicaţia client a unui volum mare de
date (rezultatul unei interogări de exemplu), întârzierile cauzate de
reţeaua prin care se accesează serverul de baze de date pot fi mari.
Dacă prelucrarea datelor nu presupune afişarea acestora în aplicaţia
client, mult mai eficientă este soluţia prelucrării datelor pe server,
într-o procedură scrisă în PL/SQL.
PL/SQL este bazat pe limbajul ADA, o parte dintre
construcţiile sale sintactice provenind din Pascal.
Avantaje ale PL/SQL:
 stuctura de bloc (programele pot fi împărţite în
blocuri logice, fiecare conţinând resursele
necesare în acel bloc. Variabilele pot fi declarate
local în cadrul unui bloc în care vor fi folosite,
iar tratarea erorilor (sau Exceptiile) se poate face
în blocul în care apar);
 controlul execuţiei (deciziile, buclele şi salturile
pot fi folosite pentru a controla execuţia
programelor, decizând dacă şi când SQL şi alte
acţiuni să fie executate);
 portabilitatea (deoarece PL/SQL derivă din
ORACLE, programele pot fi puse pe toate
maşinile care suportă ORACLE şi PL/SQL);
 performanţele (utilizarea PL/SQL poate ajuta la
îmbunătăţirea performanţelor aplicaţiilor).

125
PL/SQL ofera constructii procedurale cum ar fi variabile, constante
si tipuri. Limbajul ofera constructii selective si iterative
constructiilor SQL.

4.2. Crearea unul bloc de baza PL/SQL

Cosntructia de baza in PL/SQL este blocul. Un bloc consta dintr-o


multime de cosntructii SQL si/sau PL/SQL.

Un bloc PL/SQL consta din 3 sectiuni:

DECLARE
/* Sectiunea de declarare: variabile, tipuri de date,
subprograme locale */
BEGIN
/* Secţiunea executabilă: declaraţii SQL sau
proceduri*/
/* Este singura secţiune din bloc care trebuie să
apară */
EXCEPTION
/* Secţiunea de lucru cu excepţiile: declaraţii de lucru
cu erorile */
END;

 Declaratii (optional): aceasta sectiune incepe cu cuvantul


cheie DECLARE si se incheie cand incepe sectiunea cu cod
executabil.
 Cod executabil (obligatoriu): aceasta sectiune incepe cu
cuvantul cheie BEGIN si se sfarseste cu END. Dupa
cuvantul cheie END trebuie pus semnul de punctuatie punct
si virgula.
 Tratarea exceptiilor (optionala): sectiunea de trateare a
exceptie este inclusa in partea de cod executabil si incepe cu
cuvantul cheie EXCEPTION.

126
Sectiune Descriere

Contine declaratii de variabile, constante,


Declaratii cursoare si exceptii definite de user care sunt
(DECLARE) referite in sectiunile de cod executabil si
exceptie.

Constine cosntructii SQL care cauta date


Executie
in baza de date si cosntructii PL/SQL pentru a
(BEGIN...END)
manipula datele din bloc.

Specifica ce actiuni trebuie efectuate cand


Exceptie
sunt intalnite erori sau conditii anormale in
(EXCEPTION)
sectiunea de cod executabil.

Un program PL/SQL contine mai multe blocuri care pot fi


separate sau continute unul intr-altul.

4.2.1 Tipurile de blocuri

Exista 3 tipuri de blocuri:

 Blocuri anonime: acestea sunt blocuri PL/SQL care sunt


definite in cadrul unei aplicatii si nu au nume
 Proceduri: acestea sunt blocuri PL/SQL care au un nume,
au parametri de intrare, au eventual parametri de iesire, dar
nu au returnează o valoare explicită.
 Functii: acestea sunt blocuri PL/SQL care au un nume, au
parametri de intrare si tot timpul returneaza o singură valoare

127
Tipuri de blocuri
 Anonime Procedură Funcţie
FUNCTION nume
[DECLARE] PROCEDURE nume RETURN tip data
IS IS
BEGIN
BEGIN BEGIN --instr.
--instr. --instr. RETURN
valoare;
[EXCEPTION] [EXCEPTION] [EXCEPTION]

END; END; END;

Fi. 4.2 Tipuri de blocuri PL/SQL

4.2.2. Operatori, delimitatori şi variabile

Operatorii PL/SQL sunt în buna parte copiaţi din linbajul


PASCAL. Astfel avem

a . Operatori simpli

+ operatorul de adunare
- operatorul de scadere/negare
* operatorul de multiplecare
/ operatorul de impartire
= operator relational
> operator relational
< operator relational

128
b. Operatori multicaracter

** exponential
<> relational
!= diferit
<= , >= mai mic sau egal, mai mare sau egal
:= asignare
=> asociere (la pointeri)
.. rang
|| concatenare

Pe lângă operatori exiată un număr de delimitatori specifici PL/SQL:

<< >> etichetă


-- comentariu
( ) delimitator de lista sau expresii
; delimitator de instructiuni
, separator în cadrul unei liste
. selector de componenta
@ delimitator de access la distanta
' delimitator de şir (nu ghilimele)
: delimitator de maşină

Variabilele pot avea orice tip de data SQL, cum ar fi CHAR,


VARCHAR2, DATE, sau NUMBER, cu subdiviziunile sale
INTEGER şi REAL, sau un tip de date specific PL/SQL cum ar fi
BOOLEAN (care are trei valori distincte, considerate constante:
TRUE, FALSE şi NULL) sau PLS_INTEGER.

Tipul de date BINARY_INTEGER se foloseste pentru a păstra


valori intregi cu semn între -2147483648 si 2147483647,
reprezentate pe 32 biţi. Valorile BINARY_INTEGER necesita mai
putin spatiu decat valorile NUMBER (care au 36 de cifre
semnificative) si subtipurile NUMBER. De asemena, operatiile
PLS_INTEGER folosesc aritmetica hardware deci sunt mai rapide
decat operatiile pentru NUMBER care folosesc aritmetica din
biblioteci. Pentru calcule care depasesc domeniul

129
BINARY_INTEGER, se foloseste tipul de data INTEGER sau
NUMBER.

Există de asemenea tipul de date LONG, echivalent cu


VARCHAR2, dar av[nd mai mult de 256 de caractere.

Dupa fiecare declaratie se pune punct si virgula

Exemplu 1: Declararea Variabilelor in PL/SQL

DECLARE
No_art NUMBER(6);
Nume_art VARCHAR2(20);
in_stoc BOOLEAN;
pret_art NUMBER(6,2);
desc_art VARCHAR2(30);

Se pot defini variabile avand tipuri de date ca: tabel, inregistrare,


vector (tipurile de date compuse vor fi discutate in laboratorul viitor).

Observaţii asupra opera

4.2.3. Atribuirea unei valori variabilei

Pot exista 3 moduri de atribuirea de valori unei variabile:

 Prin folosirea operatiei de atribuire :=

Exemplu 2: atribuirea unei variabile folosind operatia de


atribuire :=

DECLARE
Salariu_sapt NUMBER;
Ore_lucr NUMBER := 40;
Salariu_ NUMBER := 22.50;
bonus NUMBER := 150;

130
Tara country VARCHAR2(128);
Suma NUMBER := 0;
dat done BOOLEAN;
id_validare BOOLEAN;
sal_rec1 salariati%ROWTYPE;
sal_rec2 salariati %ROWTYPE;
BEGIN
Salariu_sapt:= (Ore_lucr * Salariu_ora) + bonus;
Tara:= 'Canada';
Canada' := UPPER('Canada');
done := (suma > 100);
id_validare := TRUE;
sal_rec1. nume := 'Lupu';
sal_rec1. prenume := 'Dan';
sal_rec1 := sal _rec2;
END;

 Al 2-lea mod de atribuire este prin selectarea sau citirea


valorilor din baza de date folosind instrucţiunea SELECT ...
INTO numeVaribila

Exemplu 3 : Atribuirea de valori unei variabile folosind Select


Into. Variabilei bonus i se asigneaza 10% din salariul
angajatului cu id = 100.
DECLARE
bonus NUMBER(8,2);
id_sal NUMBER(6) := 100;
BEGIN
SELECT salary * 0.10 INTO bonus FROM salariati
WHERE id_salariat= id_sal;
END;

 Al 3-lea mod de atribuire se face prin trecerea unui


parametru OUT sau IN OUT unui subprogram si apoi
atribuind valoarea din interiorul blocului. In acest exemplu
functia DBMS_OUTPUT.PUT_LINE este folosita pentru a
afisa rezultatul din programul PL/SQL.

131
4.2.4. Declararea Constantelor

Declararea unei constante se face ca si declararea unei


variabile numai ca se foloseste cuvantul cheie CONSTANT si
imediat se atribuie o valoare constanta. Nu mai sunt permise alte
atribuiri.

credit_limit CONSTANT NUMBER := 5000.00;

4.2.5 Citirea şi afişarea variabilelor în PL/SQL

Introducerea de la tastatură a datelor într+o variabilă PL/SQL


se efectueaya de obicei prin inserrea caracterului & înaintea numelui
variabilei, în interiorul blocului de execuţie. Oracle opreşte execuţia
instrucţiunii ce conţine o astfel de variabila şi deschide o fereastră
separată în cere cere să i se introducă o valoare variabilei.

Afişarea valorilor variabilelor se face folosind instrucţiunea


DBMS_OUTPUT.put_line(), instrucţiune care afişează stringuri
concatenate prin dimbolul dublu ‘||’. Variabilele numerice sunt
convertite automat la tipul de date VARCHAR2; conversia poate fi
forţată folosind funcţia TO_CHAR().

Exemplu:

DECLARE
V1 NUMBER(5) := 16;
V2 NUMBER(5);
V3 NUMBER(5);

BEGIN
V3:= sqrt(V1+ &V2); -- valoarea variabilei V2 este citita de la
tastatura
DBMS_OUTPUT.PUT_LINE('V3= ' || TO_CHAR(V3);
END;

132
O alternativă simplă de citire a unei variabile de la tastatură este
V1:= &V1;

4.2.6 Atributele de transfer automat a tipului de date

Ca parte a declaratiei unei variabile este tipul acesteia. Tipul


de data pentru fiecare variabila PL/SQL este unul din tipurile
impartite intre SQL si PL/SQL, cum ar fi NUMBER sau
VARCHAR. Se pot folosi cuvintele speciale %TYPE sau
%ROWTYPE pentru a declara variabile care pastreaza coloane de
tabele sau inregistrari din tabele
a. Atributul %TYPE

Atributul %TYPE ofera posibilitatea de a seta tipul de data al


unei variabile ca fiind acelasi cu tipul de data al unei coloane dintr-o
tabele.

Exemplu: v_last_name emp.name%TYPE;

Declarand tipul pentru variabila v_last_name cu %TYPE avem


2 avantaje. In primul rand nu trebuie stiut cu exactitate tipul de data
al coloanei din tabela, si in al 2-lea rand in tabela trebuie schimbat
tipul de data pentru last_name nuami trebuie schimbat si in program.

b. Atributul %ROWTYPE

In PL/SQL, inregistrarile sunt folosite pentru a grupa date. O


inregistrare consta dintr-un numar de campuri in care se pot pastra
valori. Atributul %ROWTYPE ofera un tip de inregistrare care
reprezinta un rand dintr-o tabela. Inregistrarea poate stoca intreaga
linie din tabel.

DECLARE
dept_rec dept%ROWTYPE; -- declararea variabilei inregistrare

133
Se foloseste notatia cu punct pentru a referi un camp din
inregistrare, ca in exemplu urmator:
v_deptid := dept_rec.department_id;

134
4.3. Instrucţiuni în PL/SQL

4.3.1 Instrucţiuni de atribuire

Instrucţiunile de atribuire se impălementează în secţiunea


executabilă cuplrinsă între BEGIN şi END.
Cea mai simplă instrucţiune de atribuire este asignerea filosind
operatorul := . Formetul general este:

Variabila:= Expresie;
A nu se confunda atribuirea prin asignare ci operatorii logici
sau aritmetici.
OPERATORII

Operator Descriere

+-/* aritmetici

= egalitate

!= or <> inegalitate

|| concatenare string

:= asignare

A doua instrucţiune de atribuire este SELECT INTO


WHERE. Diferenţa majoră faţă de clasicul SELECT din SQL: după
clauza SELECT trebuie să avem o clauză INTO în care să enumerăm

135
variabilele, pentru fiecare atribut din SELECT câte o variabilă
asociată. Instrucţiunea dă eroare dacă există mai multe valori
selectate pentru un atribut, de unde clauza WHERE devine
obligatorie

Instrucţiunea SELECT în PL/SQL funcţionează doar dacă


rezultatul interogării este un singur tuplu. Situaţia este identică cu
SELECT -ul care furnizează o singură înregistrare despre care am
vorbit la interogări. Dacă interogarea returnează mai mult de un
tuplu, trebuie să folosim o tabelă cursor. De exemplu:

DROP TABLE T1;


CREATE TABLE T1(
nume VARCHAR(20),
salar INTEGER
);
DELETE FROM T1;
INSERT INTO T1 VALUES(’POPESCU Ion’, 600);
INSERT INTO T1 VALUES(’BALAJ Maria’, 500);
INSERT INTO T1 VALUES(’AVRAM Alina’, 700);
SELECT * FROM T1;
/* Deasupra e SQL simplu, mai jos este un program PL/SQL
*/
DECLARE
v_nume VARCHAR(20);
v_salar NUMBER;
BEGIN
/* Pentru cei care au salarul=500, acesta se mareste cu
100*/
SELECT nume, salar INTO v_nume,v_salar FROM T1
WHERE salar=500;
Delete from t1 where salar=500;
INSERT INTO T1 VALUES(v_nume,v_salar+100);
END;
.
run;
/* din nou SQL simplu */

136
SELECT * FROM T1;

Din fericire, un singur cuplu din tabela T1 verifică condiţia ca


salarul să fie egal cu 500, şi anume (BALAJ Maria, 500). Comanda
DELETE şterge înregistrarea respectivă, urmând ca INSERT sa o
introducă din nou în tabelă, de data asta cu salarul mărit.

Alt exemplu:

CREATE TABLE T2 (nr1 INTEGER, nr2 INTEGER);

DELETE FROM T2;

INSERT INTO T2 VALUES(1, 3);


INSERT INTO T2 VALUES(2, 4);

/* Deasupra este SQL; mai jos program PL/SQL */

DECLARE
v_nr1 NUMBER;
v_nr2 NUMBER;
BEGIN
/* daca primul numar este mai mare ca 1, se inverseaza
insereaza o
inregistrare noua in care numerele sunt inversate*/
SELECT nr1,nr2 INTO v_nr1,v_nr2 FROM T2 WHERE
nr1>1;
INSERT INTO T2 VALUES (v_nr2,v_nr1);
END;

137
4.3.2 Structuri de control

a. Instrucţiunea IF

are formatul general:

IF <conditie> THEN <lista_declaratii> ELSE


<lista_declaratii> END IF;

Partea ELSE este opţională. Dacă se doreşte imbricarea:

IF <conditie_1> THEN ...


ELSIF <conditie_2> THEN ...
... ...
ELSIF <conditie_n> THEN ...
ELSE ...
END IF;
Exemplu IF fără ELSE:

SELECT * FROM T1;


DECLARE
v_nume VARCHAR2(20);
v_salar NUMBER;
BEGIN
/* Celor care au salarul=700, li se va mari salarul cu
100 lei */
SELECT nume,salar INTO v_nume,v_salar FROM
T1 WHERE salar=700;

138
IF v_salar=700 THEN
DELETE FROM T1 WHERE SALAR=700;
INSERT INTO T1
VALUES(v_nume,v_salar+100);
END IF;
END;

SELECT * FROM T1;

Alt exemplu:

SELECT * FROM T1;


DECLARE
v_nume VARCHAR2(20);
v_salar NUMBER;

BEGIN
/* Celor care au salarul=700, li se va mari salarul cu
100 lei */
SELECT nume,salar INTO v_nume,v_salar FROM
T1 WHERE salar=700;
IF v_salar=700 THEN
DELETE FROM T1 WHERE SALAR=700;
INSERT INTO T1
VALUES(v_nume,v_salar+100);
END IF;
END;

139
.
run;

b. Instructiunea IF-THEN-ELSIF
Instrucţiunea combină două sau mai multe IF-uri pe remura ELSE.
Ca structura schematică avem

IF-THEN-ELSIF :
Schema generală
IF Condition
TRUE FALSE

ELSIF
Condition
THEN Actions
TRUE FALSE

ELSE
THEN Actions
Actions

Fig. 4.3 Formatul instrucţiunii IF-THEN-ELSIF

Exemplu
IF v_start > 100 THEN
RETURN (2 * v_start);
ELSIF v_start >= 50 THEN

140
RETURN (.5 * v_start);
ELSE
RETURN (.1 * v_start);
END IF;
...

c. Instructiunea CASE

Instrucţiunea CASE se foloseşte pentru o selecţie multiplă în funcţie


de valorile unei variabile.
Exemplu
DECLARE
grade CHAR(1);
BEGIN
grade := 'B';
CASE grade
WHEN 'A' THEN DBMS_OUTPUT.PUT_LINE('Excellent');
WHEN 'B' THEN DBMS_OUTPUT.PUT_LINE('Very Good');
WHEN 'C' THEN DBMS_OUTPUT.PUT_LINE('Good');
WHEN 'D' THEN DBMS_OUTPUT.PUT_LINE('Fair');
WHEN 'F' THEN DBMS_OUTPUT.PUT_LINE('Poor');
ELSE DBMS_OUTPUT.PUT_LINE('No such grade');
END CASE;
END;

Exemplu:

141
DECLARE
grade CHAR(1);
BEGIN
grade := 'B';
CASE
WHEN grade = 'A' THEN
DBMS_OUTPUT.PUT_LINE('Excellent');
WHEN grade = 'B' THEN DBMS_OUTPUT.PUT_LINE('Very
Good');
WHEN grade = 'C' THEN DBMS_OUTPUT.PUT_LINE('Good');
WHEN grade = 'D' THEN DBMS_OUTPUT.PUT_LINE('Fair');
WHEN grade = 'F' THEN DBMS_OUTPUT.PUT_LINE('Poor');
ELSE DBMS_OUTPUT.PUT_LINE('No such grade');
END CASE;
END;
-- in loc de folosi ELSE in CASE se poate folosi
-- EXCEPTION
-- WHEN CASE_NOT_FOUND THEN
-- DBMS_OUTPUT.PUT_LINE('No such grade');

142
4.3.3 Structuri de ciclare

a. LOOP

Instrucţiunea centrală de ciclare în PL/SQL este LOOP. Exista


3 forme diferite pentru LOOP:

 LOOP
 WHILE-LOOP
 FOR-LOOP

Exemplu
LOOP
instr1;
instr2; …
END LOOP;
Pentru a ieşi dintr+o buclp de ciclare, PL/SQL propune două
alternative: comanda EXIT, sau condiţia de ieşire EXIT WHEN.

b. Folosirea comenzii EXIT

Comanda EXIT statement forteaza iesirea din blucla .

Exemplu

DECLARE
credit_rating NUMBER := 0;
BEGIN
LOOP
credit_rating := credit_rating + 1;
IF credit_rating > 3 THEN
EXIT; -- iesirea din blucla

143
END IF;
END LOOP;
-- DBMS_OUTPUT.PUT_LINE ('Credit rating: ' ||
TO_CHAR(credit_rating));
IF credit_rating > 3 THEN
RETURN; --se foloseste RETURN si nu EXIT cand suntem in
afara LOOP
END IF;
DBMS_OUTPUT.PUT_LINE ('Credit rating: ' ||
TO_CHAR(credit_rating));
END;

Comanda EXIT trebuie plasata in interioruk buclei LOOP.

c. Comanda EXIT-WHEN

Comanda EXIT-WHEN determina iesirea din bucla in urma


unei conditii..

Exemplu
IF count > 100 THEN EXIT; ENDIF;
sau
EXIT WHEN count > 100;

Cele 2 constructii de mai sus sunt echivalente, dar EXIT-


WHEN este mai usor de inteles.

Tema: dati 2 exemple de programe in PL/SQL care folosesc


structurile de control LOOP, folosind obiectele din baza de date
creata de voi.

144
d. Etichetarea unei blucle PL/SQL

Ca si blocurile PL/SQL, buclele pot fi etichetate. Eticheta


optionala inchisa intre << >> trebuie sa apara la inceputul buclei.
Numele etichetei trebuie sa apara si la sfarsitul buclei.

Exemplu

DECLARE
s PLS_INTEGER := 0;
i PLS_INTEGER := 0;
j PLS_INTEGER;
BEGIN
<<outer_loop>>
LOOP
i := i + 1;
j := 0;
<<inner_loop>>
LOOP
j := j + 1;
s := s + i * j;
EXIT inner_loop WHEN (j > 5);
EXIT outer_loop WHEN ((i * j) > 15);
END LOOP inner_loop;
END LOOP outer_loop;
DBMS_OUTPUT.PUT_LINE ('The sum of products equals: ' ||
TO_CHAR(s));
END;

e. Bucla WHILE-LOOP

Bucla WHILE-LOOP se executa pana atata timp cat conditia


este adevarata.

WHILE condition LOOP


sequence_of_statements
END LOOP;
145
Aceasta este echivalenta cu:

LOOP
sequence_of_statements
EXIT WHEN boolean_expression;
END LOOP;

Tema: dati 2 exemple de programe in PL/SQL care folosesc


structurile de control WHILE-LOOP, folosind obiectele din baza de
date creata de voi.

f. Utilizarea buclei FOR-LOOP

Bucla FOR itereaza un număr de instrucţiuni pentru un


anumit interval de intregi. Numarul de iteratii este cunoscut inainte
de intrarea in blucla. Operatorul “..” serveste ca operator de
domeniu. Domeniul este calculat cand se intra prima data in bucla si
nu mai este niciodata reevaluat.

Exemplu:

DECLARE
p NUMBER := 0;
BEGIN
FOR k IN 1..500 LOOP – calcularea lui pi cu 500 termeni
p := p + ( ( (-1) ** (k + 1) ) / ((2 * k) - 1) );
END LOOP;
p := 4 * p;
DBMS_OUTPUT.PUT_LINE( 'pi is approximately : ' || p ); -- print
result
END;

Exemplu:

BEGIN
FOR i IN REVERSE 1..3 LOOP

146
DBMS_OUTPUT.PUT_LINE (TO_CHAR(i));
END LOOP;
END;

In interiorul unei blucle FOR, variabila index cu care se


itereaza i nu poate modificată.

BEGIN
FOR i IN 1..3 LOOP -- assign the values 1,2,3 to i
IF i < 3 THEN
DBMS_OUTPUT.PUT_LINE (TO_CHAR(i));
ELSE
i := 2; -- nu este permisă, produce o eroare
END IF;
END LOOP;
END;

147
4.3.4 Folosirea excepţiilor

O excepţie este un identificator PL/SQL asociat unei condiţii


anormale apărute în timpul execuţiei unui bloc PL/SQL. Invocarea
unei excepţii are ca efect terminarea blocului, deci ieşirea din blocul
PL/SQL. Pentru evitarea unor situaţii de întrerupere anormală,
excepţia poate fi captată si poate fi specificată o rutină de tratare a
acesteia.
O excepţie poate fi invocata in doua moduri:
a. Apare o eroare Oracle si excepţia asociata ei este automat
invocată
b. Excepţia poate fi invocată în mod explicit prin instrucţiunea
RAISE in cadrul blocului.

Captarea unei excepţii


Daca excepţia este invocată în secţiunea executabilă a unui
bloc se caută în cadrul secţiunii de tratare a excepţiilor o rutină de
tratare asociata. Daca PL/SQL poate trata excepţia, ea nu este
propagată în blocul exterior sau în mediul apelant, caz în care se
consideră că execuţia blocului s-a desfăşurat cu succes.

Propagarea unei excepţii


Daca nu există o rutină pentru tratarea ei, excepţia este
propagată în mediul apelant, caz în care execuţia blocului se termină
cu eşec.

Tipuri de excepţii
Sunt trei tipuri de excepţii:
1. Excepţii pre-definite asociate erorilor care apar cel
mai frecvent în blocurile PL/SQL (de exemplu
NO_DATA_ FOUND, TOO_MANY_ROWS,

148
INVALID_CURSOR, ZERO_DIVIDE). Aceste
excepţii nu trebuie declarate, serverul Oracle le invocă
în mod automat, dar trebuie tratate în secţiune
EXCEPTION
2. Excepţii non-predefine recunoscute de Oracle dar
tratate de utilizator cu ajutorul codului de eroare
returnat (de exemplu ORA- 01400). Trebuie declarate
în secţiunea declarativă. Serverul Oracle le invocă în
mod automat, dar trebuie tratate în secţiune
EXCEPTION
3. Excepţii definite de utilizator, asociate unor condiţii
specifice de prelucrare (de exemplu cazul în care
valoarea stocului unui anumit produs este zero).
Trebuie declarate în secţiunea declarativă, invocate de
către utilizator şi tratate în secţiunea EXCEPTION

Tratarea tuturor excepţiilor se realizează în secţiunea


EXCEPTION a blocurilor PL/SQL astfel:

EXCEPTION
WHEN exception1 [OR exception2 …]
THEN
statement1 ;
statement2 ;

[WHEN exception3 [OR exception4 …]
THEN
statement1 ;
statement2 ;

149
…]
[WHEN OTHERS THEN
statement1 ;
statement2 ;
…]

a. Tratarea excepţiilor predefinite ale Serverului Oracle

Acestea nu trebuie declarate, fiind definite de către Oracle


Server si invocate implicit. Lista completă a excepţiilor predefinite
Oracle poate fi consultată din PL/SQL Reference, capitolul 10.
Câteva exemple de excepţii predefinite sunt prezentate mai jos:

Numele Numărul Descriere


erorii
NO_DATA_FOUND ORA-01403 O instrucţiune SELECT care ar fi
trebuit sa întoarcă o singura linie
nu a returnat nici o linie.
TOO_MANY_ROWS ORA-01422 O instrucţiune SELECT care ar fi
trebuit sa întoarcă o singura linie
a returnat mai multe linii.
INVALID_CURSOR ORA-01001 Apariţia unei operaţii ilegale
asupra unui cursor (de exemplu
şi
încercarea de a deschide un cursor
CURSOR_ALREADY_O deja deschis).
PEN

Tabel 4.2 Excepţii predefinite

150
Exemple:

Să se afişeze angajatul cu codul 10. Să se trateze eroarea apărută în


cazul în care nu există nici un angajat cu acest cod.
set serveroutput on

DECLARE
v_nume VARCHAR2(20);

BEGIN
SELECT nume INTO v_nume
FROM angajati
WHERE id_angajat=10;
dbms_output.put_line(v_nume);

EXCEPTION
WHEN NO_DATA_FOUND THEN
dbms_output.put_line('Nu exista angajatul cu acest ID!');

END;
/
Să se afişeze salariul angajatului cu prenumele John. Să se trateze
eroare apărută în cazul în care există mai mulţi angajaţi cu acelaşi
nume (interogarea SQL din bloc întoarce mai multe înregistrări).

SET SERVEROUTPUT ON
DECLARE
sal angajati.salariul%type;
BEGIN
select salariul into sal from angajati where prenume='John';
DBMS_OUTPUT.PUT_LINE('John are salariul de: '||sal);
EXCEPTION
WHEN TOO_MANY_ROWS THEN
DBMS_OUTPUT.PUT_LINE('Exista mai multi salariati cu
numele John! Utilizati un cursor pentru selectie!');
END;
/

151
b. Tratarea excepţiilor non-predefinite Oracle Server

Se poate capta o eroare a Serverului Oracle ce nu are


asociata o excepţie predefinită asociindu-i un nume codului de eroare
returnat sau folosind clauza WHEN OTHERS. In PL/SQL, directiva
EXCEPTION_INIT determină compilatorul sa asocieze un nume de
excepţie unui număr (cod) de eroare standard a Serverului Oracle.
Aceasta permite referirea erorii standard prin nume şi scrierea unei
rutine de tratare a ei.

Tratarea acestor erori se realizează in 3 paşi:


1) Declararea excepţiei: se face în zona DECLARE a blocului
NUME_EXCEPTIE EXCEPTION;

2) Asocierea codului erorii cu excepţia declarată anterior: se


realizează tot în zona DECLARE prin utilizarea directivei de
compilare EXCEPTION_INIT:

PRAGMA EXCEPTION_INIT(NUME_EXCEPTIE,
COD_EROARE);
unde COD_EROARE este un cod de eroare standard Oracle;

3) Tratarea excepţiei în zona EXCEPTION a blocului:


EXCEPTION
WHEN NUME_EXCEPTIE THEN .........;

Se pot utiliza 2 atribute pentru a gestiona erorile apărute:


SQLCODE – returnează codul numeric al erorii. Poate avea
următoarele valori:
• 0 – nu a apărut nici o excepţie;
• 1 – este o excepţie definită de utilizator;
• +100 – excepţia NO_DATA_FOUND;
• un număr negativ – o eroare Oracle Server;
SQLERRM – returnează mesajul asociat erorii.

Aceste atribute pot fi încărcate în variabile şi inserate într-o tabelă de


erori pentru vizualizare şi verificare ulterioară.

152
Exemplu:

Să se insereze în tabela departamente un nou departament cu


ID-ul 200, fără a preciza denumirea acestuia. În acest caz va apare o
eroarea cu codul ORA-01400 prin care programatorul este avertizat
de încălcarea unei restricţii de integritate. Această excepţie poate fi
tratată astfel:

SET SERVEROUTPUT ON
DECLARE
-- se asociază un nume codului de eroare apărut
INSERT_EXCEPT EXCEPTION;
PRAGMA EXCEPTION_INIT(INSERT_EXCEPT, -01400);
BEGIN
insert into departments (department_id, department_name) values
(200, NULL);
EXCEPTION
--se tratează eroarea prin numele său
WHEN insert_except THEN
DBMS_OUTPUT.PUT_LINE('Nu ati precizat informatii suficiente
pentru departament');
--se afişează mesajul erorii
DBMS_OUTPUT.PUT_LINE(SQLERRM);
END;
/

c. Tratarea excepţiilor definite de utilizator

In PL/SQL se pot defini excepţii ale utilizatorului. Ele


trebuie declarate în secţiunea declarativa a blocului şi invocate
explicit prin instrucţiunea RAISE.

Etape:
1. Se declara excepţia în secţiunea declarativă:
nume_exceptie EXCEPTION;

153
2. Prin instrucţiunea RAISE se invocă în mod explicit, în cadrul
secţiunii executabile: RAISE nume_exceptie;
3. Se tratează în rutina corespunzătoare din secţiunea de tratare
a excepţiilor:
WHEN nume_exceptie THEN......

Exemplu:
Să se invoce o eroare în cazul în care utilizatorul încearcă să
execute blocul PL/SQL după ora 17.
DECLARE
e_exc1 EXCEPTION;

BEGIN
IF TO_NUMBER(TO_CHAR(SYSDATE,
'HH24'))>=17 THEN
RAISE e_exc1;
END IF;

EXCEPTION
WHEN e_exc1 THEN
dbms_output.put_line('Este ora
'||TO_CHAR(SYSDATE, 'HH24'));
dbms_output.put_line('Operatiune permisa
doar '||' in timpul programului');
END;
/

154
Capitolul V. POCEDURI ŞI
FUNCŢII ÎN PL/SQL
Un subprogram PL/SQL este un bloc ne-anonim PL/SQL care
se apeleaza folosind un set de parametrii. PL/SQL are doua tipuri de
subprograme clasice: Proceduri stocate si Funcţii, precum şi două
tipuri de subprograme specifice: Declanşatoarele (triggers) şi
Cursoarele

5.1. Proceduri stocate şi funcţii în PL/SQL


Procedurile stocate si functiile sunt blocuri denumite care
permit gruparea si organizarea comenzilor SQL si PL/SQL. Atat
codul sursa cat si cel executabil sunt stocate in baza de date. Prin
stocarea lui in baza de date, codul se afla intr-o locatie accesibila si
centralizata. Deoarece codul executabil se afla in baza de date,
invocarea procedurilor stocate este eficienta.
Procedurile stocate se pot crea cu comanda CREATE
PROCEDURE, care declara o lista de parametri si actiuni care se
efctueaza de blocul PL/SQL. Sintaxa
CREATE [OR REPLACE] PROCEDURE
NumeProcedura
[(parametru1 [mod] tipData1,
parametru2 [mod] tipData2, ...)]
IS|AS
[declaratii de variabile locale; …]
BEGIN
-- instrucţiuni SQL sau PL/SQL
END NumeProcedura;

155
Parametrii sunt folositi pentru a transfera valorilor datelor
intre apel si procedura. Parametrii sunt cunoscuti ca argumete.
Parametrii pot avea unul din cele 3 moduri: IN, OUT si IN OUT.
 parametrul IN transmite o valoare constanta
procedurii (parametrul de intrare)
 parametrul OUT transmite o valoare de la
procedura unei variabile (parametru de iesire)
 parametrul IN OUT transmite o valoare
procedurii si o valoare posibil diferita de la
procedura la o variabila, folosind acelasi
parametru
Exemplu:
CREATE OR REPLACE PROCEDURE mareste_salariu1
(p_id IN emp.empno%Type,
p_percent IN NUMBER)
IS
BEGIN
UPDATE empSET sal= sal*(1+p_percent/100)
Where empno= p_id;
END mareste_salariu1;
--blocul in care se executa procedura :
BEGIN
mareste_salariu1 (176,10);
END

156
O funcţie este un bloc PL/SQL cu nume care acceptă
parametric de intrare, poate fi apelată şi returnează întotdeauna o
valoare.
In general, se foloseste o functie pentru a calcula o valoare
numerică. Functia se creeaza folosind comanda CREATE
FUNCTION care declara o lista de parametrii si defineste actiunile
care trebuie efectuate de blocul PL/SQL standard.
Sintaxa declaraţiei de funcţii:

CREATE [OR REPLACE] FUNCTION numeFunctie


[(parametru1 [mode] tipData1,
parametru2 [mode] tipData2, ...)] RETURN tipData
IS|AS
[declaratii de variabile locale; …]
BEGIN
-- instrucţiuni SQL sau PL/SQL
RETURN valoare;
END [numeFunctie];

Functiile si procedurile sunt structuri asemanatoare. O


functie poate returna o valoare, in timp ce o procedura poate returna
zero sau mai multe valori prin intermediul parametrilor OUT. Ca şi o
procedură, o funcţie are un header, o secţiune de declaraţii , o
sectiune de cod executabil şi o sectiune pentru administrarea
exceptiilor. O funcţie trebuie sa aiba clauza Return în header si cel
putin o clauza Return în sectiunea de cod executabil.

Exemplu: funcţie care primeşte la intrare un numar n şi să


calculeze expresia: (2*n+n/2) mod n. (x mod y returnează restul
împărţirii lui x la y).

157
DECLARE
nr number(4):=10;
FUNCTION half_of_square(original NUMBER) RETURN
NUMBER IS
BEGIN
RETURN mod((2*original + original/2),original);
END half_of_square;
BEGIN
DBMS_OUTPUT.PUT_LINE('functia a returnat valoarea:
'||to_char(half_of_square(nr)));
END;

158
5.2. Pachete de proceduri în PL/SQL
Pachetele PL/SQL permit gruparea tipurilor PL/SQL,
variabilelor , structurilor de date, exceptiilor si subprogramelor intr-
un singur container.
Pachetul se crează în 2 părti:
– · Specificarea pachetului este interfaţa pentru
aplicatie. Aici se declară tipurile publice, variabile,
constante, exceptii, cursoare si subprograme.
– · Corpul pachetului defineste propriul subprogram.
Corpul pachetului poate defini de asemenea obiecte
PL/SQL, cum ar fi variabile, constante, exceptii şi
cursoare.
Corpul pachetului trebuie sa completeze implementarea pentru
toate procedurile si functiile declarate in definita pachetului. Forma
sintactica a celor două componente:
-Pentru interfaţa packetului

CREATE [OR REPLACE] PACKAGE package_name


IS|AS declaratii de variabileş
antetul procedurilor şi funcţiilor incluse in pachet
END [package_name];

-Pentru corpul packetului

CREATE [OR REPLACE] PACKAGE BODY package_name


IS|AS declaratii de variabileş
BEGIN

159
instrucţiuni de iniţializare si descrierea explicită a
procedurilor şi funcţiilor incluse in pachet
....
END [package_name];

Exemplu Pachet cu doua proceduri de concedirere a salariaţilor.


Declaraţie de pachet
CREATE OR REPLACE PACKAGE emp_admin AS
-- declararea tipurilor externe, vizibile, cursoare, exceptii
TYPE EmpRecTyp IS RECORD (emp_id NUMBER, sal
NUMBER);
-- Declararea subprogramelor vizibile
PROCEDURE fire_employee (emp_id NUMBER);
PROCEDURE fire_employee (emp_email VARCHAR2);
END emp_admin;

şi corpul acestuia
CREATE OR REPLACE PACKAGE BODY emp_admin AS
PROCEDURE fire_employee (emp_id NUMBER) IS
BEGIN
DELETE FROM employees WHERE employee_id = emp_id;
END fire_employee;
PROCEDURE fire_employee (emp_email VARCHAR2) IS
BEGIN
DELETE FROM employees WHERE email = emp_email;
END fire_employee;
END emp_admin;

160
Fig. 5.1 Componentele unui pachet de proceduri şi funcţii

161
5.3. Triggere în PL/SQL

DML trigger flow of control

Fig 5.1 Schema Oracle a execuţiei unui Trigger

Declanşatoarele, sau triggere, sunt unităţi de program care


sunt executate automat în răspuns la un eveniment care afectează
baza de date. Ele se execută înainte sau după execuţia unei
instrucţiuni DML, sau după procesarea fiecărui rând al unei atbele a
bazei de date, în urma execuţiei unei instricţiuni INSERT, UPDATE
sau DELETE.

Concepte ale declaşatoarelor


BEFORE trigger: Un declanşator executat înaintea unui eveniment
de manipulare a datelor (DML), de exemplu BEFORE INSERT.
AFTER trigger: Un declanşator executat după unui eveniment de
manipulare a datelor (DML), de exemplu AFTER UPDATE.
STATEMENT-LEVEL trigger: Un declanşator executat o data
pentru o instrucţiune SQL care poate efecta unul sau mai multe
înregistrări din baza de date.

162
ROW-LEVEL trigger: Un declanşator executat de fiecare data
pentru fiecare înregistrare din baza de date afectată de un eveniment.
Să presupinem că o tabelă de cărţi conţine 1000 de înregistrări.
Atunci comanda următoare UPDATE va modifica 1,000 de rânduri:
UPDATE books SET title = UPPER (title);
Un declanţator row-level (ce conţine clauza FOR EACH ROW) va fi
executat de 1000 de ori.
NEW pseudo-record: O structură de date NEW care arată ca o
înregistrare PL/SQL. Acestă pseudo-înregistrare este activă doar
pentru declanşatoare DML after UPDATE sau INSERT şi conţine
valorile datelor noi care au fost introduce în tabele.
OLD pseudo-record: O structură de date OLD care arată ca o
înregistrare PL/SQL, activă doar pentru declanşatoare DML before
UPDATE sau DELETE şi conţine valorile datelor noi care au fost
introduce în tabele..
Clauza WHEN : determină în ce condiţii se execută declanşatorul.

to_table from_table
EXEMPLUL 1. COL1 COL1
Declanşatoare STATEMENT-LEVEL şi 1
ROW-LEVEL: 2
-- se consider 2 tabele identice, una cu 3
date, una fără 4
CREATE TABLE from_table(col1 NUMBER); 5
- 6
- 7

c 8
r 9
e
10
a
Fig 5.2 Două tabele
-coloană identice
CREATE TABLE to_table (col1 NUMBER);

163
BEGIN - - populare prin generare
FOR counter IN 1..10 LOOP
INSERT INTO from_table VALUES(counter);
END LOOP;
END;

-- Următorul exemplu crează 2 declanşatoare


(triggere) simple, unul la nivel de instrucţiune, altul la
nivel de rând
-- trigger la nivel de instrucţiune
CREATE OR REPLACE TRIGGER statement_trigger
AFTER INSERT ON to_table
BEGIN
DBMS_OUTPUT.PUT_LINE('After Insert Statement Level');
END;

-- trigger la nivel de rând


CREATE OR REPLACE TRIGGER row_trigger
AFTER INSERT ON to_table
FOR EACH ROW
BEGIN
DBMS_OUTPUT.PUT_LINE('After Insert Row Level');
END;
După compilarea trigger-elor, se execută o simplă inserare in tabela
to_table. Rezultatul execuţiei este afişat pe pagina următoare
SET SERVEROUTPUT ON;
INSERT INTO to_table SELECT * FROM from_table;

164
>
10 rows inserted. to_table from_table

After Insert Row Level COL1 COL1


After Insert Row Level 1 1
After Insert Row Level 2 2
After Insert Row Level 3 3
After Insert Row Level 4 4
After Insert Row Level 5 5
After Insert Row Level 6 6
After Insert Row Level 7 7
After Insert Row Level
8 8
After Insert Row Level
9 9
After Insert Statement Level
10 10

Fig 5.3 Rezultatul execuţiei operaţiei INSERT

Lucrul cu înregistrări NEW şi OLD


De câte ori se foloseşte un declanşator la nivel de rând, PL/SQL
crează şi populează două structure de date care funcţionează ca şi
înregistrări (RECORD). Aceste sunt pseudo-records NEW şi OLD.
OLD păstreză valorile vechi ale unui rând afectat de eveniment; iar
NEW conţine noile valori. Aceste înregistrări au aceeşi structură ca
variabilele declarate cu clauza %ROWTYPE pe tabela pe care
rulează trigger-ul.
• Pentru triggere ataşate unei operaţii INSERT, structura OLD nu
conţine date;
• Pentru triggere ataşate unei operaţii DELETE, structura NEW nu
conţine date;
• Pentru triggere ataşate unei operaţii UPDATE, ambele structuri
NEW şi OLD conţin date;

165
• Datele din structura OLD nu se pot modifica, cele din structura
NEW se pot modifica;
• Înregistrările NEW sau OLD nu pot fi folosite ca parametrii la o
funcţie sau procedură, chiar dacă este declarată inăuntru
declanşatorului.
• Datele din structurile NEW şi OLD se referenţiază ca şi RECORD
extern, folosind simbolul “:”, cum ar fi:
IF :NEW.salary > 10000 THEN...
• Clauza FOR EACH ROW este obligatorie

EXEMPLUL 4. Folosirea structurii NEW


DROP TABLE incremented_values;

CREATE TABLE incremented_values (value_inserted NUMBER,


value_incremented NUMBER);

CREATE OR REPLACE TRIGGER increment_by_one


BEFORE INSERT ON incremented_values
FOR EACH ROW
BEGIN
:new.value_incremented := :new.value_incremented + 1;
DBMS_OUTPUT.PUT_LINE(' TRIGGER increment_by_one ');
END;

CREATE OR REPLACE TRIGGER increment_by_two


BEFORE INSERT ON incremented_values
FOR EACH ROW
BEGIN
IF :new.value_incremented > 1 THEN
:new.value_incremented := :new.value_incremented + 2;
DBMS_OUTPUT.PUT_LINE(' TRIGGER increment_by_two ');
END IF;
END;

CREATE OR REPLACE TRIGGER update1


BEFORE UPDATE ON incremented_values

166
FOR EACH ROW
BEGIN
:new.value_incremented := :new.value_incremented + 1;
DBMS_OUTPUT.PUT_LINE(' TRIGGER update1');
END;

After running the script, execute these commands and view the
results:
SET SERVEROUTPUT ON;
INSERT INTO incremented_values VALUES(1,1);
1 rows inserted.
TRIGGER increment_by_one
INSERT INTO incremented_values VALUES(2,2);
1 rows inserted.
TRIGGER increment_by_two
TRIGGER increment_by_one

UPDATE incremented_values SET value_inserted =10,


value_incremented=10;
2 rows updated.
TRIGGER update1
TRIGGER update1

value_inserted value_incremented
10 11
10 11

Dacă se adaugă următorul trigger:


CREATE OR REPLACE TRIGGER update2
BEFORE UPDATE ON incremented_values
FOR EACH ROW

167
BEGIN
:new.value_incremented := :old.value_incremented + 5;
DBMS_OUTPUT.PUT_LINE(' TRIGGER update2');
END;

Comanda UPDATE de mai jos va avea ca efect apelul a două


triggere simultan:
SET SERVEROUTPUT ON;
UPDATE incremented_values SET value_inserted =10,
value_incremented=10;
2 rows updated.
TRIGGER update2 prima linie
value_inserted value_incremented
(old:11+5)
10 17 TRIGGER update1 prima linie
10 17 (new:16+1)
TRIGGER update2 a doua linie
(11+5)
TRIGGER update1 a doua linie
(16+1)

Triggerele se folosesc curent pentru a verifica şi păstra


integritatea logică a datelor din baza de date
EXEMPLUL 5. Caz de trigger care verifica daca datele introduse
sunt corecte , dupa inserare (Trigger de verificare)

CREATE OR REPLACE TRIGGER increment_Verification


AFTER INSERT ON incremented_values FOR EACH ROW
BEGIN
IF :new.value_incremented <0 THEN
DELETE * FROM incremented_values WHEN

168
value_incremented = :new.value_incremented;
--sterge inregistrarea
DBMS_OUTPUT.PUT_LINE(' Eroare de introducere');
END IF;
END;

169
5.4. Cursoare în PL/SQL
Serverul Oracle utilizează o zonă de memorie de lucru (numită
zonă privată SQL) pentru a executa instrucţiunile SQL şi pentru a
stoca informaţiile procesate. Se poate utiliza un cursor explicit pentru
a eticheta zona privată de memorie şi a avea acces la informaţiile
stocate.
Cursoarele pot fi:
• Implicite – declarate de către PL/SQL pentru toate
instrucţiunile DML.
• Explicite – declarate de către programator pentru interogările
care returnează mai mult de o înregistrare. Pot fi gestionate prin
câteva unelte specifice. În acest fel fiecare înregistrare poate fi
prelucrată individual.

5.4.1. Cursoare Implicite

Cursoarele implicite sunt administrate automat de PL/SQL,


deci nu trebuie scris niciun cod pentru manipularea lor. Se poate tine
cont de executia unui cursor implicit prin intermediul atributelor
cursorului.

Atributele cursoarelor implicite. Pot returna informatii


despre executia comenzilor DML (Data Manipulation Language) si
DDL (Data Definition Language), cum ar fi INSERT, UPDATE,
DELETE, SELECT INTO, COMMIT sau ROLLBACK. Atributele
cursorului sunt: %FOUND, %ISOPEN, %NOTFOUND şi
%ROWCOUNT.

 %FOUND

Pana cand comanda SQL de manipulare a datelor este


executata, atributul %FOUND este NULL. %FOUND este

170
TRUE daca o comanda de tipul INSERT, UPDATE sau
DELETE afecteaza una sau mai mult inregistrari din baza de
date sau SELECT INTO returneaza una sau multe
inregistrari.

Exemplu: Folosirea atributului SQL%FOUND

CREATE TABLE dept_temp AS SELECT * FROM dept;


DECLARE
dept_no NUMBER(4) := 40;
BEGIN
DELETE FROM dept_temp WHERE deptno = dept_no;
IF SQL%FOUND THEN --daca stergerea s-a efectuat cu succes
INSERT INTO dept_temp VALUES (70, 'Personal','Craiova');
END IF;
END;

Conţinutul iniţial al tabelei nou create dept_temp


DEPTNO DNAME LOC
10 ACCOUNTING NEW YORK
20 RESEARCH DALLAS
30 SALES CHICAGO
40 OPERATIONS BOSTON

DEPTNO DNAME LOC


10 ACCOUNTING NEW YORK
20 RESEARCH DALLAS
30 SALES CHICAGO
70 Personal Craiova

Tabel 5.1 Conţinutul tabelei dept_temp înainte şi după


executarea secvenţei de cod.

 %ISOPEN

Oracle inchide cursorul automat dupa executarea


comenzilor. Ca rezultat, %ISOPEN devine FALSE.

171
 %NOTFOUND

%NOTFOUND este atributul opus lui %FOUND.


%NOTFOUND este TRUE daca INSERT, UPDATE sau
DELETE nu afecteaza nici o inregistrare din baza de date
sau SELECT INTO nu returneaza nici o inregistrare. Altfel
este FALSE.

 %ROWCOUNT

%ROWCOUNT returneaza numarul de inregistrari


afectate de una din comenzile INSERT, UPDATE, sau
DELETE sau numarul de inregistrari afectate de SELECT
INTO. %ROWCOUNT este 0 daca comanda INSERT,
UPDATE, sau DELETE nu afecteaza nici o inregistrae, sau
SELECT INTO nu returneaza nici o inregistrare.

Exemplu: Folosirea SQL%ROWCOUNT

CREATE TABLE emp_temp AS SELECT * FROM emp;

7839 KING PRESIDENT 17-NOV-81 5000 10


7698 BLAKE MANAGER 7839 01-MAY-81 2850 30
7782 CLARK MANAGER 7839 09-JUN-81 2450 10
7566 JONES MANAGER 7839 02-APR-81 2975 20
7788 SCOTT ANALYST 7566 09-DEC-82 3000 20
7902 FORD ANALYST 7566 03-DEC-81 3000 20
7369 SMITH CLERK 7902 17-DEC-80 800 20
7499 ALLEN SALESMAN 7698 20-FEB-81 1600 30
7521 WARD SALESMAN 7698 22-FEB-81 1250 30
7654 MARTIN SALESMAN 7698 28-SEP-81 1250 30
7844 TURNER SALESMAN 7698 08-SEP-81 1500 30
7876 ADAMS CLERK 7788 12-JAN-83 1100 20
7900 JAMES CLERK 7698 03-DEC-81 950 30
7934 MILLER CLERK 7782 23-JAN-82 1300 10

Tabel 5.2 Conţinutul tabelei emp_temp înainte de executarea


secvenţei de cod.

172
DECLARE
mgr_no NUMBER(4) := 7698;

BEGIN
DELETE FROM emp_temp WHERE mgr = mgr_no;
DBMS_OUTPUT.PUT_LINE('Number of employees deleted: ' ||
TO_CHAR(SQL%ROWCOUNT));
END;

7839 KING PRESIDENT 17-NOV-81 5000 10

7698 BLAKE MANAGER 7839 01-MAY-81 2850 30

7782 CLARK MANAGER 7839 09-JUN-81 2450 10

7566 JONES MANAGER 7839 02-APR-81 2975 20

7788 SCOTT ANALYST 7566 09-DEC-82 3000 20

7902 FORD ANALYST 7566 03-DEC-81 3000 20

7369 SMITH CLERK 7902 17-DEC-80 800 20

7876 ADAMS CLERK 7788 12-JAN-83 1100 20

7934 MILLER CLERK 7782 23-JAN-82 1300 10

Tabel 5.3 Conţinutul tabelei emp_temp după de executarea


secvenţei de cod.
La execuţia blocului anonim apare:
Number of employees deleted: 5

Valoarea atributului SQL%ROWCOUNT se refera la cea mai


recenta comanda SQL executata in PL/SQL.

173
5.4.2. Cursoare explicite

Cand este nevoie de control precis asupra rezultatului


interogarilor, trebuie declarat explicit un cursor in PL/SQL.
Se folosesc 3 comenzi pentru a controla un cursor: OPEN,
FETCH şi CLOSE.
1. Prima data trebuie initializat cursorul prin OPEN.
2. Apoi se poate executa FETCH repetat pana cand toate
inregistrarile au fost citite sau se poate folosi clauza BULK
COLLECT pentru a citi toate inregistrarile o singura data.
3. Pentru a închide cursorul se foloseste comanda CLOSE.

No

Yes
DECLARE OPEN FETCH EMPTY? CLOSE

• Crearea • Identifica • Citirea • Testarea • Inchidere


unei un cursor randului existentei cursor
zone activ curent informatiei
cursor intr-o • Intoarcere
explicite varibila la FETCH
daca mai
sunt
randuri

Fig. 5.4 Etapele folosirii unui cursor explicit

174
În figura 5.4 sunt prezentate etapele de lucru cu un cursor
explicit.
 Declararea unui cursor. La declarare, cursorul primeste un
nume si este asociat cu o interogare. Optional se poate
declara tipul pe care il returneaza cursorul, de exemplu
table_name%ROWTYPE.
Exemplu: Declararea unui cursor
DECLARE
my_emp NUMBER(4); -- variabila pentru campul empno
my_job VARCHAR2(9); -- variabila pentru campul job
my_sal NUMBER(7,2); -- variabila pentru campul sal
CURSOR c1 IS SELECT empno, job, sal FROM emp
WHERE sal> 2000;
my_dept dept%ROWTYPE; --
variabila pentru inregistrarea dn tabelul dept
CURSOR c2 RETURN dept%ROWTYPE IS SELECT *
FROM dept WHERE deptno = 10;

Cursorul nu este o variabila PL/SQL: nu se pot atribui valori


unui cursor si nu poate fi utilizat intr-o expresie. Numirea cursoarelor
dupa denumirea tabelelor din baza de date este posibila, dar nu este
recomandata. Un cursor poate lua parametri care pot aparea in
interogarea asociata cursorului în loc să folosim constante. În
urmatorul exemplu, parametrii cursorului se initializeaza la valori
implicite.

DECLARE
CURSOR c1 (low NUMBER DEFAULT 10, high
NUMBER DEFAULT 30) IS
SELECT * FROM dept WHERE
deptno>low AND deptno<high;
175
Observaţie: Instrucţiunea OPEN execută interogarea
asociată cursorului, identifică setul activ şi poziţionează cursorul
pe primul rând. Instrucţiunea FETCH returnează rândul curent şi
poziţionează cursorul pe rândul următor. Ea se poate repeta până
când nu mai sunt rânduri sau o condiţie specificată este atinsă.
Instrucţiunea CLOSE eliberează cursorul şi resursele cerute
de acesta.

 Deschiderea cursorului
Cand se deschide un cursor, se executa interogarea care
returneaza multimea de inregistrari care indeplinesc conditiile de
cautare.
DECLARE
CURSOR c1 IS SELECT employee_id, last_name, job_id,
salary FROM employees
WHERE salary > 2000;
BEGIN
OPEN C1;
...
Deschiderea unui cursor presupune următoarele operaţii:
1. Alocă memorie de dimensiune potrivită.
2. Analizează şi descompune instrucţiunea SELECT.
3. Face legătura între variabilele de memorie şi înregistrare.
4. Identifică setul activ (înregistrările returnate de SELECT)
5. Poziţionează pointerul pe primul rând din setul activ.

Dacă instrucţiunea SELECT nu dă nici un rând, ORACLE


nu generează o eroare în cazul cursoarelor explicite. Utilizatorul
poate utiliza atributul acestuia nume_cursor%ROWCOUNT
pentru a afla câte înregistrări au fost returnate.

176
 Citirea cursorului
Pentru prelucrarea datelor din cursor se poate folosi comanda
FETCH pentru a citi câte o înregistrare la un moment dat, în
interiorul unei bucle LOOP, cu condiţia de ieşire
EXIT WHEN nume_cursor%NOTFOUND;
Formatul instrucţiunii FETCH este
FETCH nume_cursor INTO lista_variabile;
în care lista variabile trebuie să acopere lista câmpurilor din
SELECT-ul care defineşte cursorul.

Exemplu:

DECLARE
v_job emp.job%TYPE; -- variabila pentru job
v_ename emp.ename%TYPE; -- variabila pentru ename
CURSOR c1 IS SELECT ename, job FROM emp
WHERE job='CLERK';

v_emp emp%ROWTYPE; -- variabila pentru inregistrare din


tabela emp
CURSOR c2 is SELECT * FROM emp
WHERE job='MANAGER';
BEGIN
OPEN c1; -- deschiderea cursorului
LOOP
FETCH c1 INTO v_ename, v_job; -- citirea a 2 coloane si stocarea
valorilor in variabile
EXIT WHEN c1%NOTFOUND;
DBMS_OUTPUT.PUT_LINE( RPAD(v_ename, 25, ' ') || v_job);
END LOOP;
CLOSE c1;
DBMS_OUTPUT.PUT_LINE( '-------------------------------------' );
OPEN c2;
LOOP

177
FETCH c2 INTO v_emp; -- citirea intregii inregistrari in variabila
inregistrare v_emp
EXIT WHEN c2%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(RPAD(v_emp.ename, 25, '
')||v_emp.job);
END LOOP;
CLOSE c2;
END;

La execuţie se afişează:
SMITH CLERK
ADAMS CLERK
JAMES CLERK
MILLER CLERK
-------------------------------------
BLAKE MANAGER
CLARK MANAGER
JONES MANAGER

Observaţie Orice variabila din interogare este evaluata numai la


deschiderea cursorului. In urmatorul exemplu, fiecare salariu
selectat este inmultit cu 2, chiar dacă variabila factor este
incrementată după fiecare citire.

Exemplu:

DECLARE
my_sal emp.sal%TYPE;
my_ename emp.ename%TYPE;
factor INTEGER := 2;
CURSOR c1 IS
SELECT factor*sal,ename FROM emp WHERE job = 'CLERK';
BEGIN
DBMS_OUTPUT.PUT_LINE(RPAD('NUME',10,'-
')||RPAD('SALARIU MARIT', 28, '-')||'factor');
OPEN c1; -- initial factor este 2

178
LOOP
FETCH c1 INTO my_sal, my_ename;
EXIT WHEN c1%NOTFOUND;
factor := factor + 1; -- nu afecteaza cu nimic
DBMS_OUTPUT.PUT_LINE(RPAD(my_ename,15,'
')||RPAD(my_sal, 25, ' ')||factor);
END LOOP;
CLOSE c1;
END;
La execuţie apare:
anonymous block completed
NUME------SALARIU MARIT---------------factor
SMITH 1600 3
ADAMS 2200 4
JAMES 1900 5
MILLER 2600 6

 Inchiderea Cursorului
Comanda CLOSE închide cursorul făcându-l nedisponibil. O data
închis, cursorul mai poate fi redeschis şi altă dată.

 Atributele unui cursor explicit


Fiecare cursor sau variabila de tipul cursor are 4 atribute: %FOUND,
%ISOPEN ,%NOTFOUND, si %ROWCOUNT.
Atributele cursorului descriu informatia despre executia unei
interogari care returneaza mai multe inregistrari.

Exemplu pentru %FOUND:

SET SERVEROUTPUT ON;


DECLARE
CURSOR c1 IS SELECT ename, sal FROM emp WHERE
ROWNUM < 11;

179
my_ename emp.ename%TYPE;
my_sal emp.sal%TYPE;
BEGIN
OPEN c1;
LOOP
FETCH c1 INTO my_ename, my_sal;
IF c1%FOUND THEN -- citire cu succes
DBMS_OUTPUT.PUT_LINE('Name = ' || my_ename || ', salary
= ' || my_sal);
ELSE -- iesire din bucla
EXIT;
END IF;
END LOOP;
END;

La execuţie;
anonymous block completed
Name = KING, salary = 5000
Name = BLAKE, salary = 2850
Name = CLARK, salary = 2450
Name = JONES, salary = 2975
Name = SCOTT, salary = 3000
Name = FORD, salary = 3000
Name = SMITH, salary = 800
Name = ALLEN, salary = 1600
Name = WARD, salary = 1250
Name = MARTIN, salary = 1250

180
Exemplu pentru %ROWCOUNT:

DECLARE
CURSOR c1 IS SELECT ename FROM emp WHERE ROWNUM
< 11;
name emp.ename%TYPE;
BEGIN
OPEN c1;
LOOP
FETCH c1 INTO name;
EXIT WHEN c1%NOTFOUND OR c1%NOTFOUND IS
NULL;
DBMS_OUTPUT.PUT_LINE(c1%ROWCOUNT || '. ' || name);
IF c1%ROWCOUNT = 5 THEN
DBMS_OUTPUT.PUT_LINE('--- Fetched 5th record ---');
END IF;
END LOOP;
CLOSE c1;
END;
anonymous block completed
1. KING
2. BLAKE
3. CLARK
4. JONES
5. SCOTT
--- Fetched 5th record ---
6. FORD
7. SMITH
8. ALLEN
9. WARD
10. MARTIN

 Folosirea buclei FOR pentru citirea unui cursor

Alternativ instrucţiunii FETCH, se poate folosi o instrucţiune FOR


pentru extragerea datelor din cursor.

181
Forma generală:

FOR record_name IN cursor_name LOOP


statement1;
statement2;
...
END LOOP;

Acest tip de citire a unii cursor este o formă simplificată a buclei


LOOP ce execută Implicit open, fetch şi close. Nu se declară
variabile RECORD, sunt implicite.

Exemplu 1:

FOR item_record IN NumeCursor LOOP


-- implicit open si implicit fetch
v_ordertotal := v_ordertotal +

(item_record.price *

item_record.quantity);
i := i + 1;
prodid_table (i) := item_record.prodid;
ordertotal_table (i) := v_ordertotal;
END LOOP; -- implicit close

182
Exemplu 2
DECLARE
my_dept departments.department_id%TYPE:=10;
BEGIN
my_dept:=20;
FOR emp_record IN (SELECT * FROM employees
WHERE department_id=my_dept) LOOP
DBMS_OUTPUT.PUT_LINE(emp_record.employee_id||
' '||emp_record.first_name||' '||emp_record.last_name||
' '||emp_record.salary);
END LOOP;
END;

Varianta de mai sus are dezavantajul că nu se pot utiliza atributele


cursorului explicit.

 Se pot utiliza şi cursoare cu parametri sub forma:


CURSOR nume_cursor
[(nume_parameteru tip_dată, ...)]
IS
instrucţine_select;
La deschiderea cursorului se utilizează sintaxa:
OPEN nume_cursor (val_parametru,…);

Exemplu:
SET SERVEROUTPUT ON

183
DECLARE
CURSOR emp_cursor (deptno NUMBER) IS
SELECT employee_id, last_name
FROM employees
WHERE department_id = deptno;
dept_id NUMBER;
lname VARCHAR2(15);
BEGIN
OPEN emp_cursor (10);
...
CLOSE emp_cursor;
...
OPEN emp_cursor (300);
...
CLOSE emp_cursor;
...
END;

184
Capitolul VI. PROIECTAREA
FIZICĂ A BAZELOR DE
DATE RELAŢIONALE

6.1. Caracteristici ale unei baze de date fizică

Implementarea fizică a unei baze de date relaţionala trebuie :


 să fie translatabilă în tabele
 să fie accesibilă după valoarea oricărui atribut, şi nu numai
dupa idetificatorii unici
 să suporte operatorii relaţionali
Translatabilă în tabele. Pentru a implementa relaţii logice se
poate folosi o variantă de structuri de date, una dintre ele fiind o
simplă tabelă pentru fiecare relaţie. În acest caz, structura fizică
oglindeşte structura logică. Alte structuri de date sunt listele
inlănţuite si arborii. Indiferent de structura de date fizică folosită, ea
trebuie să fie invizibilă utilizatorului, adică acestea trebuie să vadă
datele ca si când ele ar fi aşezate în tabele, fără a-i păsa de modul în
care acestea sunt memorate efectiv.
Accesibilă dupa orice atribut. Indiferent de structura de date
fizică folosită, utilizatorul trebuie să poată să ceară acces la date
specificând valoarea oricărui atribut al relaţiei. De exemplu, să
considerăm relaţia :
PROFESOR(NUME_PROFESOR,
MARCA#,RANG,NUME_CATEDRA,NUME_FACULTATE,TEL
EFON,DATA_NASTERII,DATA_ANGAJARII).

185
Utilizatorul trebuie să poată cere liniile din PROFESOR cu o
valoare oarecare a lui NUME_PROFESOR , sau a lui MARCA# sau
a oricărui atribut si nu trebuie să fie restricţionat în aceasta la
atributele ce identifică unic cheia.
Suportă operatorii relaţionali . Structura de date fizică trebuie
să fie capabilă a suporta operaţiile din SELECT, PROJECT şi JOIN,
fără a cere utilizatorului poziţionări în structura de date prin pointeri
si adrese. Managerul bazei de date trebuie să fie in stare sa
regăsească o submulţime a liniilor tabelei care satisfac criteriul de
calificare bazat pe valori de atribute, să regasescă o submultime
specifică de coloane ale tabelei, precum si să combine tabele
potrivind valorile atributelor de legatura.
Operatorii relaţionali de bază trebuie să fie suportaţi fără ca
utilizatorul să trebuiască să specifice căi de acces prin structura de
date fizică si utilizatorul nu trebuie să ştie care inregistrări pointează
la care sau cum se obţine un tuplu din altul.
SGBD-urile relaţionale oferă diferite limbaje pentru a
manipula tabele. Oparatorii specifici SELECT, PROJECT şi JOIN
nu trebuie sa apară neapărat, funcţiile lor trebuie insă oferite.

186
6.2 Transformări logico-fizice de bază
Există mai multe abordări legate de maparea relaţiilor logice în
relaţiile fizice. Cea mai directă transformare logico-fizică este de a
implementa fiecare tabelă a schemei conceptuale ca o singura relaţie
de bază. Însa, pentru a îmbunătăţi performanţa sistemului,
proiectantul bazei de date fizice trebuie să determine dacă una din
următoarele transformări logico-fizice ar fi mai potrivită :
 partiţionarea verticală a unei tabele : spargerea tabelei în mai
multe relaţii de bază , fiecare cu o parte din atributele relaţiei iniţiale
Dupa cum apare în tabelă :

Fig. 6.1 Partiţionare verticală a unei tabele Cont în Cont_client şi


Balata_cont

 partiţionarea orizontală a unei tabele : spargerea tabelei în


mai multe relaţii de bază, fiecare cu o parte din tuplele relaţiei
iniţiale

187
 reuniunea tabelelor : combinarea tabelelor într-o singură
relaţie de bază

Fig. 6.2 Reuniunea tabelelor după o partiţionare verticală

Aceste transformări vor avea ca rezultat relaţii de bază care nu


corespund exact cu tabelele de start.

6.2.1 Partiţionarea verticală

Partiţionarea verticală proiectează anumite coloane ale tabelei


într-o relaţie şi celelalte coloane în altă relaţie. Coloanele cu cheia
primară apar în ambele relaţii de bază, astfel încât tabela logică
originală poate fi reconstituită.

188
Partiţionarea verticală poate fi potrivită dacă anumite coloane
ale tabelei sunt accesate mai frecvent dacât celelalte. Separând
coloanele accesate mai rar de cele accesate mai des se reduce
volumul de date care trebuie copiate de pe memoria secundară ca
răspuns la o cerere. Astfel tranzacţiile care cer date numai din partiţia
frecvent accesată nu trebuie să transfere şi coloanele de care nu au de
fapt nevoie.
Partiţionarea verticală poate fi de asemenea potrivită atunci
când anumite coloane ale tabelei sunt accesate în primul rând de un
alt grup. Această formă de partiţionare este în special utilă atunci
când aceste grupuri de utilizatori sunt separate geografic. Rezultatul
este o bază de date distribuită , cu anumite relaţii bazate pe un
calculator şi altele pe altul.

Fig. 6.3 Distribuirea relaţiilor în cadrrul unui proces de fragmentare

De exemplu, coloanele tabelei ANGAJAT care conţin date


despre compensaţii pot fi memorate pe calculatorul departamantului
salarizare, iar celelalte coloane ale aceleiaşi tabele pe calculatorul
departamentului Personal.
O bază de date distribuită eficient memorează datele acolo
unde acestea vor fi accesate. Accesul la date memorate local evită

189
costurile de comunicare cu alte calculatoare si alte partiţii ale bazei
de date distribuite.
O altă aplicaţie a partiţionării verticale este de a forţa
restricţiile de bază. Un utilizator are acces fie la o relaţie de bază în
intregul ei, fie nu are acces de loc. Dacă anumite coloane ale tabelei
sunt necesare utilizatorilor cu un nivel de autorizare , iar celelalte
utilizatorilor cu un alt nivel de autorizare, atunci punând coloanele in
relaţii de bază diferite vom putea permite managerului bazei de date
să impună restricţiile de securitate.

6.2.2 Partiţionarea orizontală

Partiţionarea orizontală pune mai multe linii ale tabelei într-o


relaţie de bază şi celelalte linii în altă relaţie. Tabela logică originală
poate fi reconstruită făcând reuniunea celor două relaţii de bază.
După cum apare în tabelul:

Fig. 6.4 Partiţionare orizontală a tabelei Client

190
Partiţionarea orizontală poate fi potrivită dacă anumite linii ale
tabelei sunt accesate mult mai frecvent dacât celelalte linii. Separând
liniile frecvent accesate de cele accesate mai rar reducem volumul de
date care trebuie copiate pe/de pe memoria secundară ca răspuns la
cerere. Astfel, tranzacţiile care cer date numai din partiţia frecvent
accesată nu trebuie să tragă dupa ele datele din cealaltă partiţie.
Partiţionarea orizontala poate fi de asemenea utilă atunci când
anumite linii ale tabelei sunt accesate de un anumit grup de utilizatori
iar celelalte de către un alt grup. Ca şi în cazul partiţionării verticale,
dacă cele două grupuri sunt separate geografic, rezultatul va fi o bază
de date distribuită. De exemplu, liniile din tabela CONT ar putea fi
memorate in Timişoara pentru Banatul de Sud şi în Arad pentru
Banatul de Nord.

6.2.3 Reuniunea

Liniile mai multor tabele pot fi combinate intr-o relatie de


bază, o transformare care cere ca tabelele constituente să aibă un
atribut comun.

Fig. 6.5 Reuniunea tabelelor după o partiţionare orizontală

191
Uzual, acest atribut este atributul de cheie primară al unei
tabele şi atributul de cheie straină a celeilalte tabele.
Reuniunea este potrivită atunci când cele doua tabele sunt
aproape întotdeauna accesate împreună, cu o operaţie de JOIN pe
atributul comun.
De exemplu, să considerăm modelul de date :

Fig. 6.6 Schema Entitate-Atribut a midelului de date Job-


Aptitudini_job

Relaţiile sale corespunzătoare sunt reprezentate mai jos pentru


job
COD_JOB TITLU_JOB
60 Secretar
70 Programator
80 Manager
Tabel 6.1 Conţinitul datelor tabelei JOB

192
Pentru APTITUDINI_JOB avem:
COD_JOB APTITUDINE# DESC_APTITUDINE
60 463 Tehnoredactare
60 231 Editare
70 231 Editare
70 801 C
60 333 Procesare date
Tabel 6.2 Conţinutul datelor tabelei APTITUDINI_JOB

Dacă liniile JOB şi APTITUDINI_JOB asociate sunt aproape


întotdeauna accesate împreună, atunci apare relaţia de bază formată
prin reuniunea relaţiilor din tabelul anterior:

COD_JOB TITLU_JOB APTITUDINE DESC_APTITUDINE


#
60 Secretar 463 Tehnoredactare
60 Secretar 333 Procesare date
60 Secretar 231 Editare
70 Programator 231 Editare
70 Programator 801 C
80 Manager 0 0
Tabel 6.3 Conţinitul datelor tabelei reunite
JOB+APTITUDINI_JOB

Reuniunea fizică poate conduce atât la imbunătăţirea


performanţei cât şi la dificultăţi de menţinere a consistenţei deoarece
ea reduce nivelul de normalizare.

193
6.2.4 Aplicabilitatea transformărilor

Faptul că o transformare particulară este potrivită pentru o


tabela dată depinde de mai mulţi factori, incluzând :
laţimea tabelei
lungimea tabelei
patternurile de acces la tabelă :
unele linii sunt mai frecvent accesate decât altale
unele coloane sunt mai frecvent accesate decât altele
unele tabele sunt accesate frecvent impreuna
Putem face anumite generalizări ale efectelor factorilor de mai
sus, dacă considerăm fiecare factor independent, pe fondul
nemodificării celorlalţi.
 Cu cât o tabelă e mai largă, probabilitatea ca ea să poată fi
partajată vertical este mai mare
 Cu cât o tabelă e mai lungă, probabilitatea ca ea să poată fi
partajată orizontal este mai mare
 Cu cât accesul este îndreptat mai mult spre o submulţime a
liniilor unei tabele cu atât mai mare va fi probabilitatea ca ea să poată
fi partiţionată orizontal
 Cu cât accesul este îndreptat mai mult spre o submulţime a
coloanelor unei tabele cu atât mai mare va fi probabilitatea ca ea să
poată fi partiţionată vertical
 Cu cât două tabele sunt accesate mai frecvent împreună cu
atât va fi mai mare probabilitatea ca ele să poată fi reunite într-o
singură relaţie de bază.

194
6.2.5 Scheme virtuale (vederi utilizator)

Într-un mediu cu trei scheme, vederile utilizator sunt construite


prin operaţii relaţionale asupra tabelelor schemei conceptuale :
selectarea de linii care satisfac anumite criterii de calificare, proiecţia
anumitor coloane, reuniunea tabelelor după valori de atribute care se
potrivesc. Maparea între tabelele schemei conceptuale şi relaţiile de
bază ale schemei interne este folosită apoi pentru a localiza datele
pentru o vedere utilizator particulară.
Într-un mediu cu două scheme, vederile utilizator sunt mapate
direct pe relaţiile de bază, neexistând schema conceptuală. Fiecare
vedere utilizator poate lua din mai multe relaţii şi fiecare relaţie de
bază suportă mai multe vederi utilizator. Definiţia vederilor permite
ca accesul utilizatorilor să fie restricţionate la submultimi ale bazei
de date şi combinaţii diferite de date pot fi folosite pentru a suporta
diferite aplicaţii.

195
6.3. Optimizarea performanţei
Fiecare din aceste transformări între tabele şi relaţii de bază
incearcă să îmbunătăţescă performanţa bazei de date, reducâd
volumul datelor transferate la/de la memoria secundară şi reducând
cerinţele de comunicaţii într-o reţea de calculatoare.
Atunci când se dezvoltă o structură eficientă a bazei de date
fizice mai trebuiesc luate şi alte decizii :
Accesul la atribut :care atribute trebuie să aibă căi de acces
rapide preconstrite
Reuniuni preconstruite : care reuniuni între relaţiile de bază
trebuie să aibă căi de acces rapide preconstruite
Buffere :cât de mare trebuie să fie spaţiul buffer pentru a
transfera relaţiile de bază între memoria principală şi cea secundară
Gruparea relaţiilor fizice : ce relaţii de bază ar trebui memorate
împreună în acelaşi fişier

6.3.1 Accesul la atribut

Multe in SGBD-urile relaţionale permit proiectantului bazei de


date să specifice care atribute vor avea căi de acces rapide
preconstruite. Aceste atribute sunt acelea pentru care utilizatorii
specifică valori atunci când ei doresc să acceadă anumite linii din
tabelă.
Proiectantul bazei de date analizează patternurile de acces la
tabela, determinând cât de frecvent următorul tip de acces este
specificat :

SELECT lista de nume de atribute


FROM nume tabela

196
WHERE nume atribut1=valoare1
AND nume atribut2=valoare2
AND……

Cu cât apare mai frecvent un nume de atribut in clauzele


WHERE a cererilor de regăsire şi de actualizare, cu atât mai mult
trebuie spre el o cale de acces rapidă preconstruită. Prezenţa unei
astfel de căi poate afecta semnificativ performanţa bazei de date.
Prelucrarea unei cereri care califică liniile pe baza valorilor
atributelor pentru care nu există cale de acces rapid implică tipic o
analiză secvenţială porţiunii bazei de date conţinând tabela cerută.
Într-o încercare de a imbunătăţi performanţa pentru cererile
următoare, anumite SGBD-uri construiesc şi memorează automat căi
de acces rapid atunci când o cerere califică liniile pe baza unui
atribut care nu a avut deja o cale preconstruită.
Căile de acces rapid preconstruite sunt implementate fie prin
structuri de indecşi, fie prin ‘hashing’ pe valorile atributului
desemnat. Structurile de indecşi sunt, în general, variante ale
structurilor B-arbori. Structurile hash sunt calcule de adrese pe bucăţi
sau pe blocuri dintr-un fisier. În majoritatea SGBD-urilor
comerciale,numai un atribut al unei relaţii de bază poate avea o cale
de acces rapid preconstruită prin hashing. Valorile acestui atribut
determină locaţiile de memorie ale liniilor relaţiei. În contrast, multe
din atributele unei relaţii de bază pot avea căi de acces rapid
preconstruite implementate prin structuri de indecşi. Fiecare structură
de index pointează la o mulţime de linii din relaţie, în concordanţă cu
valorile de atribut ale acestor linii.
Atributele care cer cel mai adesea căi de acces rapid
preconstruite sunt atributele de cheie primară, atributele de cheie
alternată si atributele de cheie straină. Atributele de cheie primară
trebuie sa aibă aproape întotdeauna căi de acces rapid preconstruite.
Identificatorul unic al unei linii al tabelei este în general folosit în
cererea de acce la acea tabelă. Dacă o relaţie de bază are calea de
acces rapid preconstruită implementată ca şi o funcţie hash, atunci

197
acea cale de acces este întotdeauna implementată pe atributul de
cheie primară.
Dacă cheia primară este compusă, atunci calea de acces rapid
este construită pe mulţimea de atribute care alcătuiesc cheia primară.
De exemplu, daca cheia primară este COD_DIVIZIE,
ID_DEPARTAMENT atunci hashingul sau indexarea se face pe
combinaţia celor doua atribute. Calea de acces cheie primară nu ar fi
complementată corect cu un index pe COD_DIVIZIE şi un alt index
pe ID_DEPARTAMENT.
Atributele de cheie alternată pot avea căi de acces rapide, dacă
ele sunt folosite în comun în loc de cheie primară pentru accesul la
tabelă. De exemplu, ANGAJAT# este cheie primară a tabelei
ANGAJAT, dar cheia alternată SSN# este mai folosită pentru a
califica liniile, atunci poate exista o cale de acces la ANGAJAT# si
una la SSN#. Utilizatorii pot astfel accesa usor datele din ANGAJAT
bazându-se pe oricare din cele două atribute.
Atributele de cheie straină pot avea căi de acces rapid
preconstruite dacă valorile lor sunt folosite uzual pentru a califica
liniile tabelei şi/sau dacă tabela este reunită frecvent cu tabela în care
atributul de cheie straină apare ca şi cheie primară. Cele două tabele
pot fi reunite mai eficient daca există indecşi pentru atributele de
reuniune.
Alte atribute pot avea căi de acces rapide dacă îndeplinesc
toate condiţiile următoare :
valorile lor sunt folosite în mod obişnuit pentru a califica linii
valorile lor nu sunt actualizate frecvent
valorile lor sunt discriminatorii
Menţinerea unei căi de acces rapid pentru un atribut ale cărui
valori se actualizează des este costisitoare. Dacă un atribut este
indexat, atunci de fiecare dată când valoarea lui se schimbă pentru
linie, structura de index trebuie modificată. Dacă liniile sunt in
hashing, atunci schimbând valoarea atributului hash aproape
întotdeauna apare necesară şi o mutare a înregistrării liniei.

198
Un atribut discriminator este unul pentru care un procent
relativ mic deţin liniile tabelei au o valoare particulara a acelui
atribut. De exemplu, in relaţia ABGAJAT, atributul COD_SEX nu
este un atribut discriminator, căci există doar două valori posibile
pentru acest atribut. Astfel construind un index dupa COD_SEX ar fi
costisitor şi nu va reduce numărul de inregistrări analizate ca răspuns
la o cerere utilizator. Pe de altă parte, COD_JOB probabil că este un
atribut discriminator. Dacă exista 100 de valori posibile pentru
COD_JOB, atunci un index care suportă accesul direct pe COD_JOB
reduce o căutare 1% din inregistrare.

6.3.2. Reuniuni preconstruite

Un alt mod de a îmbunătăţi performanţa este de a construi căi


de acces rapide la tabele JOIN înainte de a primi cererea
utilizatorului pentru reuniune. Reuniunea a două tabele mari poate fi
un proces consumator de resurse, căci pentru fiecare valoare a
atributului de reuniune dintr-o tabelă trebuie gasită linia cu valoarea
atributului de reuniune din cealaltă tabelă. Dacă aceaşi reuniune va fi
cerută in viitor, atunci reţinând corespondenţa dintre cele două
tabele, evităm refacerea potrivirilor.
Corespondenţa dintre tabelele reunite poate fi reţinută în mai
multe moduri, incluzând :
a. un director cu valori atribut- reuniune, cu pointeri la
liniile pertinente din fiecare din cele două tabele,
reprezentate mai jos
S D C
b1 d1 c1
b2 d2 c2
b3 d3 c3
b4 d4 c4
b5 d5 c5

199
b. liste înlănţuite, cu un lanţ de pointeri de la fiecare
linie dintr-o tabelă la liniile potrivite din cealaltă
tabelă

B D E Primul R cu
valoarea B
b1 d1 e1 1
b2 d2 e2 3
b3 d3 e3 4
b4 d4 e4 0
b5 d5 e5 0
Tabel 6.4 Conţinutul lui S

A B C Urmatorul R cu
valoarea B
a1 b1 c1 2
a2 b2 c2 0
a3 b3 c3 0
a4 b4 c4 5
a5 b5 c5 0
Tabel 6.5 Conţinutul lui R

200
Nu toate SGBD-urile relaţionale suportă reuniuni
preconstruite. Proiectantul bazei de date fizice trebuie să determine
care reuniuni ar pute fi preconstruite, pe baza beneficiilor prezise.

DIRECTOR
Valoare B Pointer R Pointer S
b1 1 1
b1 2 1
b2 3 2
b3 4 3
b3 5 3
b4 0 4
b5 0 5
Tabel 6.6 Conţinutul listei de pointeri

6.3.3 Buffere

O altă cerinţă este gestionarea bufferelor pentru transferul


relaţiilor de bază între memoria principală şi cea secundară. Multe
SGBD-uri relaţionale dau proiectantului bazei de date posibilitatea
de a specifica mărimea fiecărui buffer şi numărul de buffere.
Obişnuit, mărimea unui buffer este aceaşi cu mărimea unei pagini
din memoria principală, care este determinată de către sistemul de
operare. Numărul de buffere trebuie să fie suficient de mare pentru a
păstra în memoria principală setul de lucru de linii folosite în
servirea unei cereri, aceasta depinzând de caracteristicile cererii şi de
conţinutul bazei de date.

201
6.3.4 Gruparea relaţiilor de bază

Un SGBD relaţional foloseşte posibilităţile sistemului de


gestiune a fişierelor din sistemul de operare pentru a memora şi
accesa relaţii de bază. Un fişier este într-un spaţiu de adrese compus
dintr-o colecţie de pagini de aceaşi mărime şi poate să fie rezident în
memoria principală sau secundară. Astfel de fişiere se folosesc
pentru a memora datele utilizator, structurile de date pentru căile de
acces, date din directorii interni, rezultate intermediare generate ca
răspuns la interogaţii.
Managerii bazelor de date relaţionale difeă prin modul în care
ei mapează aceste relaţii în fişiere.
O relaţie de bază –un fişier. Fiecare fişier conţine linii dintr-o
relaţie de bază şi o relaţie de bază apare într-un singur fişier.
N relaţii de bază-un fisier. Fiecare fişier conţine linii din mai
multe relaţii de bază, dar fiecare relaţie de bază apare într-un singur
fşier.
N relaţie de bază-M fişiere. Fiecare fişier conţine linii din mai
multe relaţii de bază şi fiecare relaţie de bază poate apare în mai
multe fişiere.
O relaţie de bază-M fişiere. Fiecare fişier conţine linii dintr-o
relaţie de bază, dar o relaţie de bază poate apare în mai multe fişiere.
Schema care este folosită este determinată de către SGBD şi
nu de către proiectantul bazei de date fizice. Cunoaşterea ei ajută
proiectantul in luarea de decizii.
Dacă un fişier conţine linii din mai multe relaţii de bază, atunci
proiectantul bazei de date poate grupa acele date care se pare că se
vor accesa împreună. De exemplu, dacă tuplele din două relaţii de
bază sunt frecvent accesate împreună, să spunem din cauza unui join
între ele, atunci proiectantul trebuie să ia în considerare posibilitatea
de a le memora împreună. Astfel vor fi necesare mai puţine accese la
memoria secundară pentru a răspunde cererilor de date.

202
Daca tuplele din două relaţii de bază sunt mai rar accesate
împreună, atunci ele trebuie memorate în fişiere separate. Obiectivul
este de a grupa pe o pagină tuplele care par a fi accesate împreună. O
altă posibilitate pentru gruparea fizică este de a plasa pe o aceeaşi
pagină liniile care par a fi accesate împreună. Aceste linii pot fi de la
aceeşi relaţie sau de la relaţii diferite, presupunând că un fişier poate
memora mai multe de o relaţie.

Gruparea fizică este facută uzual de :


valoare atribut, astfel că liniile cu valori similare pentru un
atribut desemnat sunt memorate împreună.
timpul de memorare, astfel că liniile pot fi regăsite fie în
secvenţa FIFO, fie în secvenţa LIFO.
Asociaţie, astfel încat ocurenţele entităţii fiu să fie memorate
aproape de ocurenţa entităţii lor tată.

Dimensiunea fişierelor. Fiecărui fişier trebuie să i se aloce


suficient spaţiu pentru a încăpea relaţiile sale în viitorul imediat plus
cel puţin 20% spaţiu liber. Alocarea de spaţiu adiţional la un fişier
poate fi scumpă, în special dacă utilizatorilor li se interzice să
acceadă datele în timpul reorganizării. Prea mult spaţiu înseamnă a
plăti pentru exces de capacitate, iar prea putin spaţiu înseamnă a nu
găsi spaţiu pentru noile tuple şi a mănui dapăşirile din pagini pline.

203
6.4 Baze de date relaţionale distribuite
Baza de date descrisă de un singur model de date logice poate
fi implementată fizic pe mai multe calculatoare, conectate printr-o
reţea de comunicaţii. Rezultatul este o bază de date distribuită. Nu
toate datele rezidă într-o bază de date fizică, dar exista un model
logic care leagă datele împreună.
Datele pot fi distribuite în mai multe moduri, incluzând :
 partiţii întregi, în care o relaţie este memorată în întregime
într-o bază de date fizică
 partiţii orizontale, în care anumite linii ale unei relaţii sunt
memorate într-o bază de date fizică si celelalte într-alta.
 Partiţii verticale, în care anumite coloane ale unei relaţii sunt
memorate într-o bază de date fizică iar altele într-alta.
 Partiţii cu acoperiri, în care o parte sau tot conţinutul unei
partiţii este replicat într-o altă partiţie.
Raţiunea primară pentru o bază de date distribuită este ca o
întreprindere descentralizată care trebuie să partajeze informaţii între
diferitele părţi distribuite. Operaţiile distribuite pot conduce la
următoarele situaţii :
 Datele pot fi generate în mai multe părţi, cerând acces local
rapid şi rezumate de date dincolo de local.
 Datele pot fi generate central, cerând acces rapid la distanţă.
Atât central cât şi parţiile trebuie să actualizeze datele.
 Datele pot fi generate în multe părţi, cerând acces rapid atât
la datele locale cât şi la cele memorate la distanţă.
În toate aceste situaţii, distribuirea bazei de date poate conduce
la o mai buna performanţă decât centralizarea ei într-o locaţie.
Aceasta are loc deoarece distribuirea reduce volumele de comunicaţii
de date, majoritatea acceselor fiind locale şi reduce volumul de date

204
memorate pe orice maşină dată, reducând cerinţele de capacitate şi
îmbunătăţind responsabilităţile locale.

205
Capitolul VII. TRANZACŢII
ÎN BAZE DE DATE
DISTRIBUITE

7.1 Introducere
Mecanismele tranzacţionale nu sunt o noutate în lumea bazelor
de date. În anii 70, la doar câteva sute de kilometri distanţă,
laboratoarele IBM de la San Jose şi Universitatea Berkeley dezvoltau
în paralel primele sisteme relaţionale, System R şi Ingres, ambele
cuprinzând anumite forme de procesare tranzacţională. Începând de
atunci, toate SGBD-urile importante încorporează mecanisme
tranzacţionale.
Procesarea tranzacţiilor are ca scop păstrarea integrităţii bazei
de date. Trebuie însă precizat că mecanismele tranzacţionale nu sunt
singurele care se ocupă de păstrarea integrităţii. Mai precis,
procesarea tranzacţiilor se referă doar la două aspecte:
Recuperarea bazei de date după un incident (database
recovery) – se bazează pe includerea unui anumit nivel de
redundanţă prin memorarea istoriei tranzacţiilor într-un aşa-numit
“jurnal” (log). Deşi acest aspect nu face subiectul articolului de faţă,
anumite elemente tehnice privind jurnalizarea vor fi utilizate în
continuare.
Controlul interferenţelor care pot avea loc între tranzacţiile
care se execută in mod concurent (concurrency control) – este un
aspect critic în sistemele de aplicaţii OLTP (On-Line Transaction
Processing). Este vorba despre “controlul” (şi nu neapărat
“evitarea”) interferenţelor deoarece, deşi întotdeauna nedorite, aceste
interferenţe pot fi permise – în anumite forme bine precizate – pentru

206
a creşte performenţele sistemului. Vom vedea în continuare cum se
realizează acest lucru.

Câteva observaţii preliminare:

a) Integritatea (sau consistenţa) bazei de date


este o noţiune care este destul de dificil de definit în mod
riguros. Pentru scopurile acestei prezentări este suficient
să admitem că baza de date este consistentă dacă
respectă toate regulile formale de integritate (integrity
rules) care i-au fost impuse şi, în plus, informaţiile pe
care le conţin se presupune că sunt corecte.
b) Toate aspectele discutate în continuare se
referă la baze de date de mari dimensiuni, exploatate în
regim multi-utilizator. Vom considera mai ales cazul
sistemelor relaţionale (marea majoritate a SGBD – urilor
sunt de acest fel) deşi – exceptând aspectele legate de
SQL – toate noţiunile prezentate sunt aplicabile oricărui
tip de SGBD. Mai mult, majoritatea noţiunilor, depăşesc
în generalitate sfera bazelor de date, fiind aplicabile
sistemelor concurente în general.
c) În cele ce urmează nu voi detalia modul în
care este implementat accesul concurent (time – sharing,
multibreading, multiprocessing, etc.). Va fi considerat în
general cazul sistemelor centralizate dar, când sunt
relevante, vor fi amintite diferenţele care pot apărea în
cazul sistemelor distribuite.

207
7.2 Tranzacţii

7.2.1 Definiţie

Metafora tranzacţiei a fost inspirată de practicile


comerciale, fiind analogă unui contract comercial prin care cele
doua părţi semnatare îşi asuma nişte obligaţii reciproce. Adesea
contractul prevede şi o instanţă de arbitraj, care să prevină
situaţia în care una dintre părţi nu îşi îndeplineşte obligaţiile. În
această situaţie, arbitru stabileşte anumite compensaţii prin care
se revine la o situaţie cât mai apropiată de cea existentă înainte
de încheierea contractului.
Există diferite definiţii pentru noţiunea de tranzacţie: “o
execuţie singulară a unui program” [ULLMAN80], “o unitate
logică de procesare” [DATE95]. Înţelegerea noţiunii este însă
mult mai intuitivă pe baza celor patru proprietăţi fundamentale
care o caracterizează: ACID (Atomicity,Consistency,
Isolation,Durability).

7.2.2 Caracterul atomic

O tranzacţie se compune în general dintr-o succesiune de


operaţii de citire şi scriere în baza de date împreună cu paşi
computaţionali. Tranzacţia reflectă însă o operaţie atomică,
indivizibilă, ceea ce înseamnă că succesiunea de operaţii trebuie
executată în totalitate. Din păcate, nici un sistem de calcul nu ne
poate oferi garanţia că aşa se va întâmpla. Din acest motiv a fost
adoptat principiul “totul sau nimic”. O componentă a SGBD-ului
numită transaction manager asigură respectarea acestui principiu
pe baza celor două operaţii fundamentale: COMMIT –
semnalează încheierea cu succes a tranzacţiei şi provoacă
permanentizarea consecinţelor acesteia; ROLLBACK –
semnalează eşecul tranzacţiei şi provoacă anularea consecinţelor

208
acesteia prin refacerea stării bazei de date dinaintea începerii
tranzacţiei.
E de remarcat faptul că operaţia ROLLBACK poate fi
explicită (specificată ca atare în program) sau implicită (deci
declanşată automat de sistem în cazul în care programul client nu
reuşeşte, dintr-un motiv sau altul, să se termine normal).

7.2.3 Caracterul consistent

O tranzacţie transformă baza de date dintr-o stare


consistentă într-o stare consistentă. Deoarece operaţiile care o
compun se execută secvenţial, în intervalul de timp dintre
începutul execuţiei tranzacţiei şi sfârşitul acesteia este posibil ca
baza de date să nu se afle într-o stare consistentă. De pildă, o
tranzacţie care transferă suma de 1000 de lei din contul A în
contul B, poate fi executată în doua etape: mai întâi se scade
suma din contul A apoi se adună suma în contul B. între cele
două etape baza de date nu reflectă realitatea, deoarece suma nu
este nici în contul A nici în contul B.
Păstrarea consistenţei este valabilă chiar şi în cazul în
care tranzacţia eşuează: prin operaţia ROLLBACK, baza de date
este adusă în starea în care era înainte de începerea tranzacţiei,
stare pe care am presupus-o consistentă. Momentul începerii unei
tranzacţii poate fi exprimat explicit în program sau poate fi
implicit, caz în care coincide cu momentul încheierii tranzacţiei
precedente. Aceste momente reprezintă “puncte de consistenţă ”
(comit points sau synchpoints). Momentul lansării unui program
este considerat implicit un punct de consistenţă.

7.2.4 Izolare

În general asupra unei baze de date acţionează simultan


mai multe programe, astfel încât există şansa ca mai multe
tranzacţii să acţioneze asupra aceloraşi date. Pe baza caracterului
consistent, putem deduce că, aplicată asupra unei inconsistenţe, o

209
tranzacţie va genera o stare inconsistentă. Cum pe timpul
execuţiei unei tranzacţii este posibil ca baza de date să fie
inconsistentă, rezultată că o tranzacţie nu are voie să acţioneze
asupra rezultatelor intermediare ale altei tranzacţii sau, altfel
spus, tranzacţiile trebuie să se execute ca şi cum ar fi izolate.

7.2.5 Durabilitatea

Odată ce o tranzacţie a fost comisă, sistemul asigură


utilizatorul că actualizările pe care tranzacţia le-a produs devin
persistente. Aceasta înseamnă că ele vor “supravieţui”, chiar
dacă intervine un accident imediat după comitere, înainte de
scrierea fizica pe disc a noilor valori. La modul practic, acest
mecanism este implementat prin jurnalizarea operaţiilor în date
precum şi a tranzacţiilor. Comiterea unei tranzacţii va forţa
scrierea pe suport a informaţiilor de jurnalizare, astfel încât la
reluarea operării, sistemul le va putea reconstitui (dacă este
cazul).

7.2.6 Probleme de control

În absenţa unor mecanisme de control al concurenţei pot


apărea fenomene nedorite, care pot conduce la rezultate eronate
sau la coruperea consistenţei bazei de date. Literatura de
specialitate menţionează în general trei anomalii tipice care pot
să apară [DATE95]. Pentru exemplificare vom considera o
aplicaţie de rezervare de locuri pentru o companie de
transporturi aeriene .
Să considerăm două tranzacţii de tip “Rezervare”, R1 şi
R2, care se execută în mod concurent şi care, întâmplător, se
referă la acelaşi zbor Z. Vom face abstracţie de operaţia de
inserare (care nu este importantă în acest context) si vom folosi o
notaţie simplificată: deoarece selecţia este – în esenţă – o citire, o
vom nota cu Read. Modificarea, fiind o scriere, o vom nota cu
Write. O posibila succesiune temporară a evenimentelor ar putea
fi următoarea:

210
t1 – R1: Read Z
t2 – R2: Read Z
t3 – R1: Write z
t4 – R2: Write Z
...
Citirile efectuate de cele doua tranzacţii vor găsi linia în
aceeaşi stare. Să presupunem că valoarea câmpului VANDUT
este 25. Ambele tranzacţii vor seta variabilele lor locale vândut
la valoarea 25. Actualizarea efectuată de tranzacţia R1 la
momentul t3 va modifica valoarea câmpului la 26. La momentul
t4, tranzacţia R2 actualizează şi ea linia Z, plasând însă câmpului
VANDUT aceeaşi valoare. Se realizează două rezervări, dar
numărul locurilor vândute creşte cu o unitate. Dacă numărul
solicitărilor este mare, este foarte probabil că va fi vândut un loc
în plus la cursa respectivă.
Anomalia, numită “modificarea pierdută” (the lost
update) a survenit datorită faptului că tranzacţia R2 şi-a bazat
actualizarea de la momentul t4 pe o valoare citită la momentul
t2, care însă a fost între timp (la momentul t3) modificată de
tranzacţia R1. Practic, efectul actualizării realizate de tranzacţia
R1 la momentul t3 s-a pierdut. Dacă tranzacţia R2 ar fi citit linia
Z după ce ea a fost modificată de R1, atunci R2 ar fi plasat în
câmpul VANDUT valoarea 27, ceea ce ar fi fost corect.
O altă situaţie posibila este cea în care una dintre
tranzacţii este anulată. Să consideram scenariul următor:
t1 – R2: Read Z
t2 – R2: Write Z
t3 – R1: Read Z
t4 – R2: ROLLBACK
t5 – R1: Write Z

211
...
În această situaţie, tranzacţia R1 va avea în variabilele
locale rezultatul scris de tranzacţia R2 la momentul t2. Anularea
tranzacţiei poate surveni din motive diverse (să presupunem că
adăugarea liniei corespunzătoare rezervării în tabela REZ
eşuează din lipsa de spaţiu pe disc) şi va provoca revenirea liniei
Z la valorile dinainte de momentul t2. În acest caz, tranzacţia R1
îşi va baza acţiunile viitoare pe nişte valori care, practic, nu au
existat niciodată în baza de date! Să presupunem că la momentul
t1 câmpul VANDUT al liniei Z conţinea valoarea 25. La
momentul t2 această valoare este incrementată, astfel încât
tranzacţia R1 va citi la momentul t3 valoarea 26. La momentul
t4, tranzacţia R2 este anulată şi în consecinţă, valoarea câmpului
VANDUT al liniei Z va fi adusă la valoarea pe care o avea
înainte de începerea tranzacţiei R2, deci 25. La momentul t5,
tranzacţia va scrie în linia Z valoarea 27. Ceea ce este, evident,
greşit. Anomalia (numită uncomitted dependency) provine din
faptul că tranzacţia R1 a citit rezultate intermediare ale
tranzacţiei R2.
Pentru a exemplifica o a treia anomalie, numită “analiza
inconsistentă” (inconsistent analysis) vom considera tabela
CLIENT, asupra căreia se execută în mod concurent doua
tranzacţii. Tranzacţia T1 calculează suma totala încasată de la
pasagerii cursei Z, în timp ce tranzacţia T2 transferă o anumită
sumă x din contul unui client C3 în contul unui client C1 (care s-
a întâmplat că au zburat împreună). În mod normal suma totală
ar trebui să fie aceeaşi indiferent în care cont se afla suma x. Să
presupunem că soldurile clienţilor C1,C2 si C3 sunt 200, 100 şi
respectiv 300, iar x este 20.
Dar iată ce se poate întâmplă:

t1-T1: Read C1 (sold=200, total=200)


t2-T1: Read C2 (sold=100,total=300)
t3-T2: Read C3 (sold=300)

212
t4-T2: Write C3 (sold=280)

t5-T2: Read C1 (sold=200)

t6-T2: Write C1 (sold=220)

t7-T2: Commit

t8-T1: Read C3 (sold=280, total=580)


...
Pentru clienţii C1, C2 si C3 totalul ar fi trebuit să fie,
desigur, 600. Este evident că suma totală va fi greşită. Spre
deosebire de celelalte două cazuri prezentate, nu mai este vorba
despre citirea unor valori actualizate de o tranzacţie înainte de
comiterea acesteia. T1 nu citeşte nimic în timpul din momentul
începerii tranzacţiei T2 şi până la comiterea acesteia. Problema
provine din faptul că T1 a citit unul dintre conturi înainte de
transfer iar pe celălalt după transfer.
În toate cele trei cazuri, anomaliile sunt provocate de
interfeţele dintre tranzacţii care se execută în mod concurent. O
metoda simplă de evitarea acestor interfeţe ar fi executarea
completă a tranzacţiilor în ordinea începerii lor. În acest caz
performanţele serverului de date ar fi afectate în mod
inacceptabil. Ar fi ca şi cum într-un mare magazin cu autoservire
clienţii ar fi lăsaţi înăuntru unul câte unul, fiecare după ce
clientul precedent şi-a terminat toate cumpărăturile.
Pentru a echilibra cât mai bine performanţa şi siguranţa,
constructorii de sisteme de gestiune a bazelor de date au
dezvoltat mai multe procedee prin care interfeţele între
tranzacţiile concurente să poată fi controlate. Cel mai răspândit
este mecanismul bazat pe blocarea (locking) unor porţiuni ale
bazei de date pentru a interzice altor tranzacţii accesul la datele
respective pe durata unor operaţiuni critice efectuate de o
tranzacţie. O altă metodă este cea bazată pe aplicarea unor

213
“mărci de timp” (timestamping) asupra tranzacţiilor şi a
obiectelor implicate în tranzacţii. Ambele procedee (precum si
procedeele “hibride”) pornesc de la premiza pesimistă că
interfeţele nedorite sunt oricând posibile şi chiar probabile, deci
se bazează pe prevenirea lor. Există însă şi o abordare optimistă,
care pleacă de la “prezumţia de nevinovăţie” şi care încearcă
doar să depisteze şi să rezolve conflictele în cazul în care acestea
apar. Toate metodele au avantaje si dezavantaje, fiecare dintre
ele se pretează la anumite aplicaţii şi sunt inacceptabile în cazul
altora.

7.2.7 Exemplu aplicativ

Aplicaţiile tipice OLTP sunt cele de rezervare de locuri.


O versiune mult simplificată de baza de date pentru rezervări de
locuri pentru avion se poate baza pe trei tabele:
 ZBOR – Tabela cuprinde date despre fiecare cursă
aeriană. Câmpuri:
NR, DATA – Identificatorul şi data zborului.
Împreuna formează cheia primară;
SRC, DEST – Ruta;
CAP – Capacitatea aeronavei (locuri);
VANDUT – Numărul locurilor vândute.

 CLIENT – Tabela cuprinde informaţii despre clienţi.


Câmpuri:
NUME, ADR – Numele (cheia primară) şi adresa clientului;
SOLD – Suma încasată de la client.

 REZ – Cuprinde rezervările făcute. Câmpuri:


NR,DATA – Zborul (cheie străină);
NUME – Clientul (cheie străină);

214
OBS – Cerinţe speciale.

Această bază de date este accesată în mod concurent de


diverse programe client care se execută la casele de bilete, la agenţii
de turism, la alte companii aeriene, etc. Operaţiunile cele mai curente
sunt cele de rezervare de locuri. O descriere - la rândul ei
simplificată - a unei tranzacţii de rezervare poate fi dată folosind un
pseudocod sugestiv cu SQL înglobat (embeded SQL):
Exemplul “Rezervare”

begin_transaction Rezervare
begin
input (nr_zbor, data, nume_client);
EXEC SQL SELECT VANDUT, CAP
INTO vândut,cap
FROM ZBOR
WHERE NR=nr_zbor
AND DATA=data;
if vândut=cap then
begin
output (“nu mai sunt locuri”);
Abort
end
else
begin
EXEC SQL UPDATE ZBOR
SET VANDUT=vândut + 1

215
WHERE NR=nr_zbor AND DATA=data;
EXEC SQL INSERT
INTO REZ (NR, DATA, NUME, OBS)
VALUES (nr_zbor, data, nume_client,
null);
Commit;
Output (“OK”)
end
end-if
end.

În exemplul “Rezervare” am presupus că este vorba


despre un client deja existent în baza de date (în tabela
CLIENT). Oricum, se poate considera că introducerea sau
actualizarea datelor clientului face obiectul unei alte tranzacţii,
care se execută după ce s-a făcut rezervarea:

begin_transaction Taxare
begin
input(nume_client, adr, suma);
EXEC SQL SELECT SOLD
INTO sold
FROM CLIENT
WHERE NUME = nume_client:
if SQLSTATE = “02000” then
begin (*client nou*)
EXEC SQL INSERT

216
INTO CLIENT (NUME, ADR, SOLD)
VALUES (nume_client, adr,0);
end
end – if;
EXEC SQL UPDATE CLIENT
SET SOLD = sold + suma
WHERE NUME = nume_client;
Commit;
Ouput (“OK”)
end.

217
7.3 Blocare (Lock)
Ideea pe care se bazează tehnica blocării este foarte simplă: o
tranzacţie care a început să opereze asupra unor date trebuie să
interzică accesul altor tranzacţii la datele respective până în
momentul în care operaţia se încheie. În acest timp, datele sunt
“ţinute sub cheie” (to lock – a încuia ). Controlul blocării datelor este
asigurat de o componentă a SGBD – ului numită Lock Manager
(LM). În momentul în care o tranzacţie T doreşte să acceseze un
anumit obiect al bazei de date (piesa de date), va cere componentei
LM blocarea obiectului. Dacă obiectul este blocat de o altă
tranzacţie, tranzacţia T va fi pusă în stare de aşteptare (wait) până
când obiectul este eliberat.
Să reanalizăm a doua anomalie prezentată în secţiunea
precedentă (uncommited dependency). La momentul t1 tranzacţia R2
blochează linia Z. La momentul t3, tranzacţia t3, tranzacţia R1 cere
la rândul ei blocarea liniei Z dar, linia fiind deja blocată de R2 , este
pusă în stare de aşteptare. La momentul t4, tranzacţia R2 se termină
(prin ROLLBACK) şi eliberează linia Z. Abia acum R1 obţine
blocarea liniei Z şi poate să o acceseze. Datele asupra căruia
acţionează acum R1 sunt “curate” (efectele tranzacţiei R2 au fost
anulate ), deci anomalia a fost evitată.
Se poate observa cu uşurinţă că această modalitate de
blocare este prea restrictivă. Anomaliile apar doar în cazul
actualizărilor datelor, ceea ce sugerează ca rafinare a tehnicii implica
folosirea a doua tipuri de blocări:
Blocare partajata (share lock sau Slock) – Permite citirea
obiectului dar interzice modificarea acestuia, motiv pentru care mai
este numită “blocare pentru citire” (read lock). Mai multe tranzacţii
pot bloca simultan pentru citire un anumit obiect.
Blocare exclusivă (exclusive lock sau x lock) – Interzice
accesul altor tranzacţii la obiectul blocat, fie pentru citire, fie pentru
modificare. Blocarea exclusivă este mai “tare” decât blocarea

218
partajata, fiind folosită doar pentru actualizări, motiv pentru care mai
este numită “blocare pentru scriere” (write lock).
Se poate observa că anumite cereri de blocare asupra unui
obiect pot fi compatibile sau nu, în funcţie de tipul blocării.
Compatibilitatea cererilor de blocare poate fi exprimată sintetic
printr-o matrice de compatibilitate.
O situaţie specială este cea în care o tranzacţie blochează
pentru citire un obiect şi doreşte să obţină o blocare exclusivă. Dacă
obiectul respectiv nu este blocat partajat şi de către alte tranzacţii,
blocarea exclusivă este obţinută de tranzacţia în cauză. Procedeul se
numeşte “promovarea blocării” (lock promotion).
În cazul celor mai multe SGBD-uri, blocarea este implicită:
orice operaţie asupra datelor este automat precedată de cererea
pentru obţinerea blocării datelor respective (S lock pentru citire, X
lock pentru actualizare – adică: UPDATE, INSERT şi DELETE).
Încheierea tranzacţiei (cu sau fără succes) eliberează în mod automat
blocările pe care aceasta le deţinea. Anumite sisteme (ex. Adabas D)
permit “înlănţuirea tranzacţiilor” (transaction chaining) cu păstrarea
anumitor blocări (prin clauza KEEP LOCK a instrucţiunii
COMMIT).
Standardul SQL nu face nici o prezumţie legată de modul de
implementare a mecanismelor de control al accesului concurent (prin
blocare, prin mărci de timp sau alte metode) şi, în consecinţă, nu
prevede instrucţiuni explicite de blocare. Cu toate acestea,
majoritatea SGBD-urilor relaţionale oferă în propriile dialecte SQL
instrucţiuni de blocare explicită (LOCK). Anumite sisteme non-
relaţionale (Raima, de exemplu) folosesc doar blocări explicite. De
obicei aceste sisteme prevăd şi instrucţiuni de deblocare explicită
(UNLOCK).
Deşi sunt cele mai uzuale, blocările partajate şi exclusive nu
sunt singurele posibile. Unele SGBD-uri (IBM DB2, Sybase SQL
Server, Raima db_VISTA ) folosesc o aşa-numita “blocare pentru
actualizare” (update lock), care este un nivel intermediar între
blocarea partajată şi cea exclusivă. Dacă mai multe tranzacţii
blochează partajat (pentru citire) un anumit obiect, una dintre ele

219
(doar una) poate obţine o blocare pentru actualizare (remarcaţi că o
blocare exclusivă nu poate fi obţinută în aceste codiţii). De obicei
utilizarea blocării pentru actualizare este posibilă doar în situaţia
unui mecanism de control special (bazat în general pe versiuni
multiple ale datelor) care să avertizeze o altă tranzacţie care solicită o
blocare pentru actualizare că datele au fost modificate.
O tabelă de date poate fi la un moment dat blocată în mod
exclusiv (x), blocată în mod parţial (S) sau poate să nu fie blocată (-).
În funcţie de aceasta stare, o altă cerere de blocare poate fi
compatibilă (Y – caz în care Lock Managerul o rezolvă favorabil)
sau conflictuală (N – caz în care este refuzată, tranzacţia care a emis-
o fiind pusă în stare de aşteptare).
Matricea de compatibilitate pentru blocări exclusive şi
partajate este:

X S -

X N N Y

S N Y Y

- Y Y Y

Tabel 7.1 Matricea de compatibilitate pentru blocări exclusive

Matricea poate fi extinsă pentru a cuprinde şi blocări de tip


intent lock:

220
X SIX IX S IS -

X N N N N N Y

SIX N N N N Y Y

IX N N Y N Y Y

S N N N Y Y Y

IS N Y Y Y Y Y

- Y Y Y Y Y Y

Tabel 7.2 Matricea extinsă de compatibilitate


Legenda (vezi Blocare ierarhică):
 IS – intent shared
 IX – intent exclusive
 S – shared
 SIX – shared intent exclusive
 X – exclusive

221
7.4 Interblocare (Deadlock)
Să revedem acum problema “actualizării pierdute”,
folosind blocările partajate şi exclusive. La momentul t1
tranzacţia R1 solicită o blocare partajată a liniei Z şi
(presupunând că linia nu era blocată pentru scriere de o altă
tranzacţie) o obţine. La momentul t2, tranzacţia R2 solicită şi
ea o blocare partajată a liniei Z, pentru a face o actualizare. Nu
obţine blocarea, deoarece linia este blocată pentru citire de
tranzacţia R2,deci este pusă în stare de aşteptare. Tranzacţia R2
cere şi ea blocarea exclusivă şi, evident, nu o obţine din motive
similare. Nici una dintre tranzacţii nu poate continua, deoarece
fiecare aşteaptă ca cealaltă să elibereze linia Z.
Această situaţie se numeşte deadlock sau
“interblocare”. Este uşor de verificat că şi în situaţia “analizei
inconsistente” se va ajunge la o interblocare. Rezultatul este că
am rezolvat problema anomaliilor dar am obţinut o altă
problemă, cea a interblocărilor. Rezolvarea noii probleme
cuprinde două aspecte:

1) Prevenirea interblocării.

Implică stabilirea unui protocol de acces la date care să


facă imposibilă apariţia situaţiilor de deadlock. O variantă
posibilă este ca fiecare tranzacţie să blocheze “în bloc” toate
liniile de care are nevoie. Altă variantă este stabilirea unei
ordini a obiectelor iar cererile de blocare să fie rezolvate în
conformitate cu această ordine. Ambele metode au
dezavantajul că limitează semnificativ performanţele prin
blocarea resurselor pe durate mai lungi decât cele strict
necesare. Pe de altă parte, prima metodă nu este aplicabilă

222
întotdeauna, deoarece este posibil ca o tranzacţie să nu
cunoască de la început toate datele de care are nevoie.

2) Detectarea interblocării.

Cea mai simplă metodă de detectare a unei situaţii de


deadlock este cea bazată pe un mecanism de time – out: dacă
durata execuţiei unei tranzacţii depăşeşte o valoare prestabilită,
sistemul deduce că a apărut o interblocare.
O altă metodă se bazează pe construirea şi menţinerea
dinamică a unui “graf de aşteptare” (Wait – For Graph).
Noţiunile acestui graf reprezintă tranzacţiile care se execută
(T1,T2…,Tn) iar arcele reprezintă relaţia de dependenţă
(aşteptare): existenţa unui arc de la Ti la Tj semnifică faptul că
tranzacţia Ti aşteptă ca tranzacţia Tj să elibereze anumite
resurse.
Detectarea unei interblocări revine la detectarea
existentei unui ciclu în graful de aşteptare.
În practică, cel mai adesea se utilizează o mixtură de
tehnici: se impune un protocol de acces care să reducă
posibilitatea interblocării (fără să o prevină total, dar şi fără să
inhibeze semificativ concurenţa), să implementeze un
mecanism care să detecteze interblocările cele mai uzuale,
lăsându-le pe celelalte pe seama unui mecanism de time – out.
Rezolvarea efectivă a unei interblocării revine la
stabilirea unei “victime” dintre tranzacţiile implicate în
deadlock şi anularea ei (ROLLBACK). După ce interblocarea a
fost înlăturată, tranzacţia poate fi lansată din nou în execuţie.
Desigur, într-o interblocare pot să intervină mai mult de
două tranzacţii (deşi experimentele cu System R au demonstrat
că în realitate astfel de situaţii sunt extrem de rare). În acest caz
223
este posibil ca mai multe tranzacţii să trebuiască anulate pentru
a debloca execuţia.
Cele mai multe sisteme reprogramează automat pentru
execuţie tranzacţiile anulate. Există însă şi sisteme care
returnează doar un cod de eroare aplicaţiei, acesteia revenindu-
i sarcina să se ocupe de rezolvarea problemei.

7.5 Serializare
Problema care se pune este: cum putem ştii dacă
execuţia concurentă a unui grup de tranzacţii este corectă sau
nu ?
Să începem cu o definiţie: Se numeşte planificare
(schedule) oricare ordine posibilă de executare a operaţiilor
grupului de tranzacţii considerat.
O primă constatare este că, dacă presupunem că fiecare
tranzacţie în parte din grup este corectă, atunci orice planificare
serială a tranzacţiilor (una după alta indiferent de ordine) este
corectă. Deşi afirmaţia este intuitivă, se poate justifica uşor
prin faptul că orice program execută o secvenţă de tranzacţii
(deci niciodată două tranzacţii simultan). Aşadar tranzacţiile
din grupul considerat sunt executate de programe diferite (sunt
deci independente), ordinea execuţiei lor fiind irelevantă (de
regulă FIFO: first in first out).
În cazul în care se execută operaţii ale unei tranzacţii în
timp ce execuţia altor tranzacţii nu a fost încă încheiată avem
de-a face cu o planificare intercalată (interleaved), caz în care
este posibil ca execuţia să nu fie corectă (cum a fost cazul celor
trei exemple prezentate la început).
Două planificări ale unui grup de tranzacţii sunt
echivalente dacă vor produce mereu acelaşi rezultat, oricare ar

224
fi starea iniţială a bazei de date (aceasta înseamnă de fapt, că
operaţiile conflictuale sunt în aceeaşi ordine).
O planificare este serializabilă dacă este echivalentă cu
o planificare serială. Orice planificare serială fiind corectă,
înseamnă că am găsit criteriul de corectitudine căutat. Execuţia
unui grup de tranzacţii este corectă dacă s-a făcut conform unei
planificări serializabile. Să remarcăm că nici una dintre
planificările utilizate ca exemple pentru cele trei anomali nu
este serializabilă.
O caracterizare mai puţin riguroasă, dar mult nai
intuitivă a serializabilităţii este următoarea: Oricare ar fi două
tranzacţii A şi B dintr-o planificare a unui grup de tranzacţii
concurente, fie A precede logic pe B, fie B precede logic pe A.
Faptul că “A precede logic pe B” înseamnă că B poate vedea
rezultatele execuţiei tranzacţiei B. Deci, dacă consideram toate
obiectele de tranzacţia A, atunci B vede toate aceste obiecte fie
modificate deja de A, fie în forma în care erau înainte ca
modificările să se producă, dar niciodată ca un amestec de
obiecte modificate sau nemodificate.
Teoria este, desigur, mult mai bogata şi specifică mai
mulţi algoritmi de verificare a criteriului pe care l-am enunţat.
Rezultatul cel mai important din perspectiva practică a acestei
teorii este aşa – numita “teorema a seriabilităţii” (sau “a
blocării în două faze”):
Dacă toate tranzacţiile unui grup de tranzacţii
concurente sunt bine formate şi respectă protocolul de blocare
în doua faze, atunci orice planificare legală este serializabilă.
Demonstraţia nu este dificilă. Importante sunt
condiţiile:
O tranzacţie este “bine formată” dacă orice operaţie a
tranzacţiei este acoperită de o blocare şi toate blocările sunt
eliberate. O operaţie (citire sau scriere) este “acoperită de o

225
blocare” dacă tranzacţia deţine o blocare suficient de puternică
a obiectului asupra căruia se desfăşoară operaţia.
O planificare este “legală” dacă nu se desfăşoară în
condiţiile unor blocări conflictuale.
Un “protocol de blocare” constă dintr-un set de restricţii
impuse ordinii în care tranzacţiile concurente blochează şi
deblochează obiectele bazei de date. Protocolul de blocare în
două faze (two – phase locking) impune următoarele două
restricţii:
Înainte de a opera asupra oricărui obiect al bazei de
date, o tranzacţie trebuie să obţină blocarea respectivului
obiect.
După ce a eliberat o blocare, o tranzacţie nu va mai
încerca niciodată să obţină noi blocări. Se observă cu uşurinţă
explicaţia denumirii “în două faze” (care n-are nimic în comun
cu comiterea în doua faze): conform acestui protocol orice
tranzacţie trece mai întâi printr-o fază de eliberare a blocărilor.
O scurtă discuţie asupra acestui protocol se impune. În
primul rând trebuie spus că sarcina asigurării respectării acestui
protocol revine Lock Manager-ului (desigur, dacă sistemul
lucrează pe baza acestui protocol). Mai observăm că protocolul
prevede “eliberarea blocărilor”. O regulă de “bun simţ” spune
că un obiect trebuie blocat cât mai puţin timp cu putinţă, pentru
a permite şi accesul altor tranzacţii la acesta. Din păcate,
implementarea acestui protocol în forma sa cea mai eficientă
din acest punct de vedere este extrem de dificilă: LM trebuie
să “ştie” când o tranzacţie a obţinut toate blocările şi nu va mai
avea nevoie de altele (pentru a identifica faza în care se află);
LM trebuie să ştie dacă tranzacţia va mai avea nevoie de un
obiect asupra căruia a efectuat o operaţie, deci dacă poate sau
nu să o elibereze (din acelaşi motiv al identificării fazelor); în
fine, apare problema extrem de dificilă a “anularii în cascadă”

226
a tranzacţiilor: în cazul în care o tranzacţie o fost anulată în
faza a doua, este posibil ca unele date eliberate de aceasta au
fost apoi blocate de alte tranzacţii, caz în care aceste tranzacţii
trebuie la rândul lor anulate. Din cauza acestor dificultăţi,
majoritatea sistemelor implementează o variantă mai restrictivă
a protocolului, în care toate eliberările blocărilor unei tranzacţii
sunt amânate până la terminarea tranzacţiei (fie prin COMMIT
fie prin ROLLBACK). Este deci rezonabil să considerăm că
blocările obţinute de o tranzacţie sunt păstrate până la
terminarea acesteia, cu toate că în felul acesta intervalul de
timp în care un obiect este blocat este de regulă mai lung decât
minimul necesar. Compromisul este si aici prezent:
simplificarea mecanismelor implementate în Lock Manager
compensează scăderea nivelului de concurenţă prin blocări de
mai lungă durata. Există însă situaţii în care se poate admite un
grad oarecare de interferenţă, caz în care nivelul concurenţei
poate fi crescut prin “relaxarea” protocolului de blocare (în
speţă prin admiterea unor condiţii în care anumite blocări pot fi
eliberate înaintea terminării tranzacţiei).
Observaţie: După cum se ştie, toate sistemele
relaţionale majore implementează diverse forme ale
protocolului de blocare în două faze. Sistemele care utilizează
doar blocări şi deblocări explicite lasă implementarea acestui
mecanism în seama proiectanţilor. În orice situaţie, proiectanţii
sunt sfătuiţi să nu lase controlul blocării nici o clipă în seama
utilizatorilor finali, din motive lesne de înţeles (sindromul
“blocării peste pauza de masa”).
Se remarcă cu siguranţă că am evitat sistematic să
precizez ce anume este “obiectul” asupra căreia se aplică
blocarea, iar în exemple am considerat că blocarea se face la
nivelul liniei de tabela (care în sistemele non-relaţionale se
poate chema “articol” sau “înregistrare” - record). Nivelul la
care se face blocarea se numeşte de obicei granulaţie (locking
granularity). Cu cât granulaţia este mai fina, blocarea se face la
227
nivele inferioare (poate să ajungă la nivelul unui câmp al unui
articol). O granulaţie mai grosieră (coarse) se referă la blocarea
unei volume mari de date, care pot să meargă până la nivelul
întregii baze de date.
Granulaţia mai poate fi analizată şi prin prisma
orientării ei logice sau fizice. De pilda unele sisteme aplică
(sau pot aplica) blocarea la nivel de fişier sau “spaţiu de date”.
La majoritatea SGBD-urilor, un fişier poate să conţină mai
multe tipuri de articole (linii din mai multe tabele, în limbaj
relaţional) sau, dimpotrivă, doar o parte din ocurenţele unui tip
de articole (o parte din liniile unei tabele). Un alt caz tipic de
blocare la nivel fizic este cel care se referă la un “bloc de date”,
adică la unitatea de transfer între disc şi memorie. Blocarea la
nivel de “pagina” (page) poate fi logică (cel mai adesea) sau
fizică, în funcţie de accepţiunea care i se dă de către SGBD-ul
în cauză.
Cele mai multe sisteme moderne utilizează blocarea la
nivel logic, cea mai comună fiind actualmente blocarea la nivel
de articol (linie dintr-o tabela). Blocarea unei întregi tabele este
tot o blocare logică, dar mai grosiera. Există şi posibilitatea de
a bloca o submulţime precizată de linii dintr-o tabelă (singurul
sistem care dispune de această abilitate este Tandem NonStop
SQL/NP).
Esenţial este faptul că o granulaţie mai fină a blocării
permite o mai mare concurenţă, şansele ca tranzacţiile
concurente să blocheze aceleaşi date scăzând. Pe de altă parte
nu trebuie uitat că blocarea în sine este o operaţie complexă şi
consumatoare de resurse. O cerere de blocare la nivelul unei
linii dintr-o tabelă implică testarea existenţei unor blocări
conflictuale. Dacă blocarea se face la nivel de tabelă,
încărcarea adusă de mecanismul de blocare este mult mai mică.
Dezavantajul este că doar o singură tranzacţie va avea acces la
datele acesteia la un moment dat.

228
Pentru a permite o echilibrare optimă a acestor avantaje
şi dezavantaje, multe sisteme permit utilizarea simultană a mai
multor granulaţii. Ca exemplu, Oracle suportă blocarea la nivel
de linie şi tabelă, IMB DB2 la nivel de linie, pagină şi fişier
tablespace iar Sybase la nivel de pagină şi tabelă.

229
7.6 Blocare ierarhică
Dacă până acum am folosit în exemple doar blocări la
nivel de articol, în cele ce urmează vom considera şi blocări
aplicate unor porţiuni mai mari (pentru a nu complica
expunerea, ne putem limita la nivel de tabela). Tehnica blocării
ierarhice se referă la sistemele care admit mai multe granulaţii
ale blocării şi a fost introdusă de Jim Gray şi colaboratorii săi
încă din 1975. O descriere mai “didactică“ poate fi consultată
în [GRAY93].
Ideea de la care se pleacă este că pentru a obţine o
blocare la nivel de articol (linie din tabelă), o tranzacţie trebuie
să-şi manifeste această intenţie, cerând mai întâi o blocare la
nivel de tabelă. În felul acesta se simplifică procesul de
detectare a unor cereri conflictuale de blocare la nivel de linie,
deoarece ele trebuie întâi să se manifeste la nivel de tabelă.
Protocolul bazat pe “intenţii de blocare” (intent locking)
introduce trei noi tipuri de blocare (la nivel de tabelă), alături
de cele doua tipuri de blocări uzuale (S-lock si X-lock) care,
aşa cum am arătat deja, au sens şi la nivel de tabelă. Avem
astfel cinci tipuri de blocări pe care o tranzacţie T le poate
solicita la nivelul întregii tabele R, prezentate în ordinea
crescătoare “tăriei” lor relative:
IS – intent shared. Tranzacţia T intenţionează să
blocheze pentru citire (Slock) anumite linii ale tabelei R, pentru
a garanta stabilirea acestora în timpul procesărilor pe care le va
efectua.
IX – intent exclusiv. La fel ca IS, dar T s-ar putea să
vrea să modifice anumite articole şi deci să solicite blocarea
exclusivă a acestora.

230
S – shared. Este obişnuita blocare partajată. T admite
citiri concurente ale tabelei R, dar nu şi scrieri. T nu va face
nici o scriere la nivelul liniilor tabelei.
SIX – shared intent exclusiv. Combină S şi IX. În plus
faţă de S, T s-ar să vrea să modifice anumite linii din R şi, în
consecinţă, să solicite blocarea exclusivă a acestora.
X – exclusive. T nu admite citiri concurente în tabela R.
T ar putea să actualizeze anumite linii ale tabelei R.

Observaţii
Noţiunea de “tărie“ a blocării se referă la faptul că o
cerere de blocare de un anumit tip care eşuează, va eşua cu
siguranţă pentru orice tip mai “tare”.
Tipurile IX şi S sunt egale din punct de vedere a
“tăriei”.
Şi aceste tipuri de blocări sunt în mod obişnuit cerute în
mod implicit. Cu toate acestea, sistemele care implementează
aceste tipuri de blocare (DB2, OpenIngres) oferă de obicei şi o
instrucţiune de blocare explicită pentru aceste tipuri.
Varianta pe care am prezentat-o este mult simplificata.
De fapt blocările se pot referi la orice granulaţii şi orice obiecte
ale bazei de date (inclusiv indecşi).
În fine, protocolul bazat pe intenţii de blocare (intent
locking protocol), impune două reguli care îmbină blocările
nivel de tabelă şi de articol într-o combinaţie care adesea s-a
dovedit mai eficientă în aplicaţii:
Înainte de a obţine o blocare partajată (S) la nivel de
linie, tranzacţia trebuie să obţină o blocare de tip IS (sau mai
tare) la nivelul întregii tabele.

231
Înainte de a obţine o blocare de tip exclusiv (X) la nivel
de linie, o tranzacţie trebuie să obţină o blocare de tip IX sau
mai tare la nivelul întregii tabele.

232
Capitolul VIII. ANOMALII DE
COMPORTAMENT ŞI
ALGORITMI DE CONTROL A
CONCURENŢEI ÎN SGBD
DISTRIBUITE

La sistemele în care o bază de date este accesată simultan de


către mai mulţi utilizatori apar situaţii de contlict datorate accesului
concurent la datele care constituie o resursă comună. Modul de
rezolvare al conflictului depinde de natura cererilor de acces la date,
funcţie de care putem distinge două cazuri extreme:
Dacă cererile de acces sunt de tipul "regăsire", atunci
secvenţializarea accesului la mediul de memorare este suficientă
pentru a nu mai fi nevoie de alte precauţii. Aşa sunt bazele de date
statistice, unde mai mulţi utilizatori interoghează baza de date
simultan. Atâta timp cât nici unul dintre utilizatori nu face modificări
asupra datelor, nu are o importanţă prea mare ordinea în care se
asigură accesul utilizatorilor la date. Ca urmare rezolvarea situatiilor
conflictuale cauzate de operaţiile de citire simultane poate fi lăsată în
seama sistemului de operare care stabileşte ordinea de satisfacere a
cererilor după criteriul asigurării concurenţei maxime de operare
minimizâând timpul global de satisfacere a cererilor.
Situaţia este diferită dacă unele dintre cereri sunt de tipul
"actualizare". În aceste cazuri este necesară aplicarea unor strategii
adecvate de tratare a cererilor de acces. Exemplul tipic pentru această
situaţie îl constituie sistemele de rezervare a locurilor, unde mai
mulţi agenţi fac rezervări simultan şi deci modifică permanent lista
locurilor libere şi lista rezervărilor. În lipsa unui control adecvat al
cererilor de acces există pericolul ca acelaşi loc să fie rezervat de mai

233
multe ori. Acest lucru este posibil deoarece în intervalul de timp de
la acceptarea unei anumite cereri de rezervare pe un loc anume şi
până la rezolvarea acesteia (eliminarea locului cu pricina din lista de
locuri libere) ar putea fi acceptate şi rezolvate alte cereri de rezervare
pentru acelaşi loc. Deci două procese care citesc şi modifică valoarea
aceluiaşi obiect ar putea interacţiona în mod nedorit atunci câând
sunt executate simultan. Pentru a evita interactiunile nedorite este
necesară impunerea unor restricţii asupra execuţiei concurente a
proceselor care execută operaţii de citire şi de modificare a datelor.
Calea cea mai simplă de evitare a interacţiunilor este de a
executa tranzacţiile în mod independent, una după cealaltă. Este clar
că o asemenea alternativă prezintă interes doar din punct de vedere
teoretic şi este practic inacceptabilă, deoarece minimizează eficienţa
sistemului. De fapt, nivelul de concurenţă, măsurat prin numărul de
tranzacţii executate concurent, este unul dintre cei mai importanţi
parametrii pentru caracterizarea unui asemenea sistem.
Din acest motiv, mecanismele de control al concurenţei
urmăresc realizarea unui compromis între menţinerea consistenţei
bazei de date şi obţinerea unui nivel de concurenţă cât mai ridicat.
Din punctul de vedere al tranzacţiilor, controlul concurenţei asigură
proprietăţile de izolare şi consistenţă ale acestora, chiar şi în
condiţiile executării concurente a mai multor tranzacţii.
În cele ce urmează vom presupune că sistemul în discuţie este
absolut sigur, deci ne aflăm în situaţia ideală în care nu sunt posibile
nici un fel de defecte (hardware sau software). Deşi ipoteza este total
nerealistă, ea constituie o simplificare necesară deoarece permite
izolarea aspectelor legate de controlul concurenţei fată de cele
relative la rezistenţa la defecte. Vom renunţa la această ipoteză
atunci când vom trece la prezentarea aspectelor legate de rezistenţa la
defecte a sistemelor, unde vom analiza modificările care trebuie
fâăcute algoritmilor de control al concurenţei pentru a asigura fie
funcţionarea fără întreruperi a sistemului; fie posibilitatea de
recuperare a acestuia la apariţia diverselor defecte.

234
8.1. Anomalii de interferenţă în BD distribuite
Interacţiunea necontrolată a două sau mai multe tranzacţii
poate conduce la apariţia unor stări inconsistente ale bazei de date şi
la producerea unor rezultate eronate. Două tranzacţii T i şi Tj sunt
susceptibile de interferenţă dacă rezultatul
execuţiei concurente a acestora poate fi diferit de rezultatul
execuţiei seriale. Între două tranzacţii poate să apară o interferenţă
dacă acestea efectuează operaţii asupra unor date comune. În plus,
dacă aceste tranzacţii sunt executate în mod concurent, atunci
spunem că sunt conflictuale. Deci două tranzacţii Ti şi Tj sunt
conflictuale dacă sunt concurente şi susceptibile de interterenţă.
În funcţie de natura operaţiilor pe care le efectuează asupra
datelor comune, între două tranzacţii pot să apară mai multe tipuri de
interferenţă. Aceste interferenţe sunt cauza a mai multor anomalii de
interferenţă:

8.1.1 Anomalia de actualizare pierdută

Corespunde unui conflict de tip scriere-scriere şi constă în


faptul că rezultatul actualizării efectuate de o tranzacţie se pierde ca
urmare a reactualizării aceleiaşi date de către o altă tranzacţie, făâră
ca reactualizarea să fie influenţată de rezultatul primei actualizări.

Exemplu:

Fie următoarea execuţie concurentă a două tranzacţii T1 şi T2,

T1 T2
READ A;
READ A;

235
A=A+5;
WRITE A;
A=A+10;
WRITE A;
în urma căreia valoarea lui A apare mărită cu 10, în loc de 15
aşa cum ar fi de aşteptat. Este ca şi cum tranzacţia T1 nu s-ar fi
executat de loc.

8.1.2. Anomalia dată de citiri improprii

Corespunde unui conflict de tip scriere-citire şi apare atunci


când o tranzacţie surprinde o stare temporar inconsistentă a bazei de
date.
Exemplu:
Fie următoarea execuţie concurentă a două tranzacţii T1 şi T2,

T1 T2
READ A;
A=A-10;
WRITE A;
READ A;
READ B;
C=A+B;
WRITE C;
READ B;
B=B+10;
WRITE B;

236
unde se remarcă faptul că valoarea sumei A+B este aceeaşi
înainte şi după execuţia de mai sus. Intenţia este de a reţine în C
valoarea acestei sume, dar datorită interferenţei valoarea din C este
cu 10 mai mică decât cea reală.

8.1.3. Anomalia de citire nereproductibilă

Corespunde unui conflict de tip citire-scriere şi apare atunci


când aceeaşi tranzacţie găseşte valori diferite la citiri repetate ale
aceleiaşi date.
Exemplu:
Fie următoarea execuţie concurentă a două tranzacţii T1 şi T2,
T1 T2
READ A;
B=A;
WRITE B;
READ A;
A=A+10;
WRITE A;
READ A;
C=A;
WRITE C;
unde se observă că deşi valorile rezultate pentru B şi C în urma
execuţiei tranzacţiei T1, ar trebui să fie egale, ele sunt diferite din
cauza interferenţei cu tranzacţia T2.

237
8.2. Introducerea restricţiilor de comportamet
concurent: primitivele LOCK şi UNLOCK

Fie tranzacţiile T1 şi T2 având execuţii diferite ale următoarei


secvenţe de operaţii:
READ A;
A=A+1;
WRITE A;
unde A este o valoare existentă în baza de date. Fiecare din
cele două tranzacţii citeşte valoarea A într-o zonă de lucru proprie
(bufferl, respectiv buffer2), adună 1 la această valoare după care scrie
rezultatul în baza de date. După execuţia tranzacţiilor T1 şi T2 este
de aşteptat ca valoarea lui A să fie mărită cu 2. Totuşi. dacă
tranzacţiile T1 şi T2 sunt executate concurent, este posibil, funcţie de
modul de interferenţă al acestora, ca rezultatul să nu fie cel aşteptat.
De exemplu, după execuţia concurentă din figura 8.1, valoarea lui A
apare mărită doar cu l.
Cea mai simplă metodă de evitare a situaţiilor de genul celei
prezentate este de a permite accesul la valoarea A a unei singure
tranzacţii pe toată durata executării acesteia. Accesul celorlalte
tranzacţii va fi temporar blocat în acest interval de timp. Acest lucru
se poate realiza prin folosirea a două funcţii primitive LOCK() şi
UNLOCK(). Aceste funcţii sunt considerate primitive în sensul că
secvenţa de microoperaţii corespunzătoare executării lor nu poate fi
întreruptă de alte operaţii. Altfel spus LOCK() şi UNLOCK() sunt
operaţii indivizibile.
Dacă o tranzacţie T execută cu succes o primitivă LOCK(A),
atunci componenta lock manager a SGBD asigură accesul exclusiv al
tranzacţiei T la valoarea A, interzicâând accesul la această valoare a
oricărei alte tranzacţii atââta timp câât tranzacţia T nu eliberează
valoarea A prin executarea primitivei UNLOCK(A). Spunem că
valoarea A este blocată în acest interval de timp. O tranzacţie poate
executa cu succes o primitivă LOCK() doar asupra unei valoricare nu

238
este blocată. În acest caz valoarea returnată de funcţia LOCK() este
TRUE. Orice tentativă de a executa primitiva LOCK() asupra unei
valori blocate va eşua, valoarea returnată fiind FALSE. Acesta este
cel mai simplu mecanism de a asigura excluderea mutuală. De
remarcat că problema excluderii mutuale nu este specifică numai
bazelor de date, ci caracterizează orice sistem concurent, limbaje
concurente, sisteme de operare, hardware-uri paralele etc.

Fig. 8.1. Execuţie concurentă a două tranzacţii T1 şi T2


care conduce la un rezultat eronat
.
Primitivele LOCK() şi UNLOCK() pot fi folosite pentru
realizarea mecanismelor de sincronizare a tranzacţiilor. Astfel dacă o
tranzacţie doreşte să acceseze o anumită valoare, ea va trebui să
obţină accesul exclusiv la aceasta prin executarea unei primitive
LOCK(). Dacă valoarea este blocată, atunci accesul exclusiv va fi
refuzat, iar tranzacţia va trebui să aştepte pâână la deblocarea
acesteia, moment în care va putea executa cu succes primitiva
LOCK() asupra acestei valori. Orice tranzacţie care a executat cu
succes o primitivă LOCK() asupra unei valori, va trebui să execute
primitiva UNLOCK() asupra aceleiaşi valori înainte de a-şi încheia
execuţia. Despre orice ordonare secvenţială (eventual intermixată) a
paşilor a două sau mai multe tranzacţii care respectă regulile de mai
sus se spune că este legală.

Pentru tranzacţiile T1 şi T2 considerate anterior secvenţa de


paşi folosind primitivele LOCK() şi UNLOCK() este următoarea:

239
WHILE NOT(LOCK(A));
READ A;
A=A+1;
WRITE A;
UNLOCK(A);
Observăm că dacă una dintre tranzacţii, să zicem T 1, obţine
accesul exclusiv la valoarea A, atunci tranzacţia T 2 va trebui să
aştepte terminarea completă a lui T1 pentru a obţine accesul la
valoarea A. La terminarea tranzacţiei T1 valoarea lui A este mărită
cu 1, iar la terminarea lui T2 valoarea va fi mărită cu 2.
În această ultimă variantă rezultatul este corect, dar execuţia
este pur secvenţială, nu este posibil nici un fel de paraâlelism în
executarea celor două tranzacţii. Din punctul de vedere al timpului
de execuţie această situaţie este inacceptabilă şi de aceea se folosesc
algoritmi care să realizeze ordonări secvenţiale legafe cu un grad de
concurenţă al execuţiei cât mai ridicat, dar şi cu garanţia obţinerii de
rezultate corecte.

Lock Manager
O bază de date este partiţionată în mai multe unităţi de acces
(items). Acestea sunt porţiuni ale bazei de date care pot constitui
obiectul unei. operaţii de blocare (lock). Prin blocarea unei unităţi de
acces o tranzacţie poate împiedica accesul altor tranzacţii la unitatea
blocată pâână în momentul deblocării acestei unităţi de către
tranzacţia care a efectuat blocarea. Gestiunea operaţiilor de blocare,
precum şi arbitrarea cererilor de blocare venite din partea
tranzacţiilor este realizată de către o componentă specială a SGBD
numită lock manager.
Natura şi dimensiunea unităţilor de acces este stabilită de
proiectantul sistemului. De exemplu, în cazul modelului de date
relaţional unităţile de acces pot fi de dimensiuni mari cuprinzând
relaţii întregi ale bazei de date, pot fi grupuri de tuple sau pot fi tuple
individuale sau chiar componente ale tuplelor. Prin alegerea unor

240
unităţi de acces de mari dimensiuni se reduce numărul operaţiilor de
blocare ceea ce înseamnă reducerea excesului de timp consumat de
sistem pentru gestiunea acestor operaţii, precum şi reducerea
spaţiului de memorie necesar înregistrării blocajelor. În schimb
folosind unităţi de acces de mici dimensiuni creşte gradul de
concurenţă suportat de sistem deoarece vor putea fi executate în
paralel un număr mai mare de tranzacţii care operează în unităţi de
acces diferite. În practică dimensiunea potrivită a unităţilor de acces
este dată de extinderea operaţiilor efectuate de tranzacţiile cu cea mai
mare frecvenţă. Astfel dacă tranzacţia tipică presupune efectuarea
unor operaţii de cuplare, atunci unitatea de acces va fi relaţia.
Dacă însă majoritatea tranzacţiilor efectuează operaţii asupra
unor tuple individuale, atunci va fi convenabil să se aleagă tupla ca
unitate de acces.

241
8.3. Serializabilitate: definire şi exemplu
Serializabilitatea este o problemă de concurenţă care prezintă
un interes deosebit în cazul bazelor de date. Aşa cum s-a constatat şi
din exemplele de până acum, prin execuţia concurentă a mai multor
tranzacţii se pot obţine rezultate diferite faţă de situaţia în care
fiecare tranzacţie este executată independent. Dar rezultatele
execuţiilor concurente pot să difere şi între ele şi sunt în general
inconsistente. În mod firesc se consideră corect rezultatul obţinut
prin execuţia independentă a tranzacţiilor. Numim o astfel de
execuţie execuţie serială. Execuţia concurentă a mai multor
tranzacţii este considerată corectă dacă şi numai dacă efectul acesteia
este echivalent cu cel al unei execuţii seriale a aceloraşi tranzactii.
Definiţii
Numim planificare a unui set de tranzacţii o ordine de
execuţie a paşilor elementari (LOCK, READ, WRITE, etc.) ai
tranzacţiilor setului. Ordonarea se referă la paşi din tranzacţii
diferite, ordinea relativă a paşilor aceleiaşi tranzacţii nefiind afectată.
O planificare se numeşte serială dacă toţi paşii oricărei tranzacţii
apar în poziţii consecutive ale planificării. O asemenea planificare
determină o execuţie serială, fâră interferenţe a tranzacţiilor.
O planificare se numeşte serializabilă dacă şi numai dacă
efectul ei este echivalent cu cel al unei planificări seriale.
Exemplu:
Fie două tranzacţii T1 şi T2 definite prin secvenţele:
T1: READ A; A=A-10; WRITE A; READ B; B=B+10;
WRITE B;
T2: READ B; B=B-20; WRITE B; READ C; C=C+20; WRITE
C;
Orice planificare serială a tranzacţiilor T1 şi T2 are proprietatea
că suma A+B+C rămâne nemodificată.
În figurile 8.2 şi 8.3 sunt prezentate două planificări diferite ale
tranzacţiilor T1 şi T2: una serializabilă şi alta neserializabilă.

242
T1 T2

Fig. 8.2. Tranzacţii serializabile

După execuţia planificării neserializabile suma A+B+C este


mărită cu 20 ca urmare a pierderii actualizării lui B (WRITE B) din
tranzacţia T2.

243
T1 T2

Fig. 8.3. Tranzacţii ne-serializabile

244
8.4. Formalizarea conceptului de serializabilitate.
Planificarea operaţiilor concurente în SGBDD

O planificare P (numită şi istorie) este definită peste un set de


tranzacţii T={T1T2,...,Tn} şi o ordine de execuţie specifică, posibil
intercalată, a operaţiilor acestora. Pornind de la definiţia formală a
conceptului de tranzacţie, o planificare P poate fi, la rândul ei,
definită ca o relaţie de ordine parţială peste mulţimea T a
tranzacţiilor componente.
După cum s-a arătat, două operaţii Oij(x) şi Ok1(x) (i şi k nu
neapărat distincte) care accesează aceeaşi entitate x din baza de date,
sunt conflictuale dacă cel puţin una dintre ele este de tip scriere.
Dacă cele două operaţii conflictuale apartin unor tranzacţii diferite T i
şi Tk (i≠k), atunci aceste tranzacţii sunt considerate de asemenea
conflictuale. O planificare completă defineşte ordinea de execuţie
ale tuturor operaţiilor din domeniul său. Formal, o planificare
completă PTc definită peste un set de tranzacţii T={T1,T2,...,Tn}
PTc   T ,  T 
este o relaţie de ordine parţială , unde:

1.  T  i 1,n  i ;

 T   i 1,n  i ;
2.
3. Pentru oricare două operaţii conflictuale
Oij , Ok1   T
,
avem fie
Oij  T Ok 1
fie
Ok1  T Oij
.

245
Prima condiţie defineşte domeniul planificării ca fiind
reuniunea domeniilor tranzacţiilor individuale. Condiţia a doua arată
că relaţia de ordine asociată planificării este un superset al relaţiilor
de ordine ale tuturor tranzactiilor individuale. În sfâârşit, condiţia a
treia precizează faptul că între oricare două operaţii conflictuale din
domeniul planificării trebuie să existe o ordine relativă bine definită.

Exemplu:
Fie tranzacţiile:
T1: READ(x) T2: READ(x)
x<-x+1 x<-x+1
WRITE(x) WRITE(x)
COMMIT COMMIT

O posibilă planificare completă PTc peste setul de tranzacţii


T={T1T2} poate fi specificată formal prin relaţia de ordine parţială:
PTc   T ,  T 
, unde:

  R ,W , C , R ,W , C , 
T 1 1 1 2 2 2 T 
,
{ (R1,R2),(R1,W1),(R1,C1),(R1,W2),(R1,C2),
(R2,W1),(R2,C1),(R2,W2),(R2,C2),
(W1,C1),(W1,W2),(W1,C2),(C1,W2),(C1,C2),(W2,C2)}.
(Pentru simplificarea notaţiei s-a omis specificarea explicită a
argumentului operaţiilor, acesta rezultând fără echivoc din contextul
exemplului prezentat.)
Graful aciclic corespunzător acestei planificări este prezentat
în figura 2.3. (de menţionat faptul că s-au omis din reprezentare
arcele corespunzătoare acelor relaţii care sunt implicate prin
tranzitivitate de către celelalte relaţii.)

246
Ca şi în cazul tranzacţiilor individuale este uzuală folosirea
unei convenţii care simplifică notaţia unei planificări. Conform
acestei convenţii, o planificare este reprezentată sub forma unei liste

a operaţiilor din domeniul T 


, ordinea acestora în listă fiind
aceeaşi cu ordinea lor de execuţie în cadrul planificării. Cu această
convenţie planificarea PTc din exemplul de mai sus se poate specifica
astfel:
PTc= {R1(x),R2(x),W1(x),C1,W2(x),C2}.
O planificare se defineşte formal ca un prefix al unei
planificări complete.
P   , 
Fiind dată o relaţie de ordine parţială , un prefix
P 
'
 ,  , al lui P se defineşte astfel:
' '

l.   '
;
ei , e j   ' ei  ' e j
2. , avem: dacă şi numai dacă
ei  e j
;
ei   ' e j   e j  ei ej  '
3. , dacă şi , atunci .
Primele două condiţii de mai sus definesc prefixul P' ca fiind o

restricţie a lui P la domeniul  '


, toate relaţiile de ordonare din P
fiind menţinute şi în P'. A treia condiţie arată că pentru orice element

din  '
, toţi predecesorii săi din  trebuie să fie incluşi şi în
 '
.
Conceptul de planificare, definit ca un prefix al unei planificări
complete, oferă posibilitatea de a raţiona asupra planificărilor
incomplete. Acest lucru este util din punctul de vedere al teoriei
serializabilită ii deoarece permite luarea în considerare doar a
operaţiilor conflictuale din cadrul tranzacţiilor, neglijând restul

247
operaţiilor care oricum nu au efect asupra serializabilităţii. De
asemenea, capacitatea de a trata planificări incomplete devine
absolut necesară atunci câând se ia în considerare posibilitatea
apariţiei defectelor în sistem.
Exemplu:
Fie tranzacţiile:
T1: READ(x) T2: WRITE(x) T3: READ(x)
WRITE(x) WRITE(y) READ(y)
COMMIT READ(z) READ(z)
COMMIT COMMIT
c
O posibilă planificare completă, P , a celor trei tranzacţii este
dată prin graful aciclic din figura 2.4: O posibilă planificare P, prefix
c
al lui P , este dată prin graful aciclic din figura 2.5.
Aşa cum s-a arătat, o planificare P este serială dacă paşii
tranzacţiilor componente nu sunt intercalaţi. O planificare serială
menţine consistenţa bazei de date deoarece, conform proprietăţii de
consistenţă a tranzacţiilor, orice tranzacţie executată independent pe
o bază de date consistentă va produce o bază de date tot consistentă.
Deci o planificare serială în care tranzacţiile sunt executate pe rând,
una cââte una, va lăsa baza de date într-o stare consistentă dacă,
bineînţeles, starea initială a bazei de date a fost una consistentă.
Pornind de la relaţia de precedenţă, introdusă prin relaţia de
ordine parţială, este posibilă definirea echivalenţei planificărilor pe
baza efectelor acestora asupra bazei de date. Intuitiv, două planificări
P1 şi P2, definite peste acelaşi set de tranzacţii T, sunt echivalente
dacă au acelaşi efect asupra bazei de date. Formal, două planificări
P1 şi P2, definite peste acelaşi set de tranzacţii T, sunt echivalente
dacă pentru orice pereche de operaţii planifcare a conflictuale Oij şi
Ok1 (i≠k), avem:
Oij  1 Ok1  Oij  2 Ok1
,

248
Această formă de echivalenţă poartă numele de echivalenţă la
conflict fiind definită pe baza ordinii relative de execuţie a
operaţiilor conftictuale.
Exemplu:
Fie tranzacţiile T1, T2 şi T3 din exemplul precedent, atunci
planificările P1, şi P2, definite prin:
P1={W2(x),W2(y), R2(z),C2,R1(x),
W1(x),C1,R3(x),R3(y),R3(z),C3),

P2={W2(x),R1(x),W1(x),R2(x),C2,W2(y),R3(v),R2(z),C1,R3(z),C3)
sunt echivalente la conflict, deoarece pentru fiecare pereche de
operaţii conflictuale ordinea relativă de execuţie este aceeaşi în
ambele planificări.
Într-adevăr perechile de operaţii conflictuale sunt:
(W2(x), R1(x), (W2(y), R3(y)) , (W2(x), W1(x)), (R1(x),
W2(x))
iar ordinea relativă de execuţie este cea care apare în aceste
perechi, atât pentru planificarea P1 cât şi pentru P2. Echivalenţa la
conflict permite definirea formală a conceptului de serializabilitate.
O planificare P este serializabilă dacă şi numai dacă este
echivalentă la conflict cu o planificare serială. Aceasta formă de
serializabilitate poarta numele de serializabilitate bazată pe
conflict. Planificarea P1, din exemplul de mai sus este serială
deoarece constă din execuţia pe rând a tranzacţiilor componente, în
ordinea: T2 T1 T3.
Planificarea P2 este serializabilă datorită faptului că este
echivalentă la conflict cu planificarea P1. Conceptul de
serializabilitate permite definirea mai clară a obiectivelor urmărite
prin controlul concurenţei. Funcţia principală a oricărui mecanism
de control al concurenţei este de a genera o planificare serializabilă
pentru execuţia tranzacţiilor active din sistem. Problema principală
care se pune în domeniul controlului concurenţei este de a dezvolta
algoritmi care garantează faptul că orice planificare pe care o produc
este serializabilă.

249
Principalii algoritmi de control al concurenţei cunoscuţi se
clasifică în
 · algoritmi de control al concurenţei prin blocare,
care se bazează pe accesul mutual exclusiv al
tranzacţiilor la datele partajate; excluderea mutuală
este asigurată prin primitive de tip LOCK şi
UNLOCK.
 · algoritmi de control al concurenţei prin mărci de
timp , care încearcă să ordoneze execuţia tranzacţiilor
conform unui set de reguli; ordonarea tranzacţiilor este
asigurată prin mărci de timp asociate atât tranzacţiilor,
cât şi datelor pe care le accesează.

250
8.5 Algoritmi de control al concurenţei şi testare a
seriabilităţii

8.5.1. Controlul concurenţei prin blocare

Algoritmii de control al concurenţei prin blocare îşi propun


prevenirea executării unor secvenţe incorecte de operaţii prin
punerea în aşteptare a tranzacţiilor care execută operaţii conflictuale.
Aceasta se realizează prin folosirea primitivelor LOCK şi UNLOCK.
Simpla folosire a acestor primitive nu este însă suficientă pentru a
obţine execuţii serializabile ale seturilor de tranzacţii. Pentru acesta
este nevoie de mecanisme de control suplimentare sau de restricţii
suplimentare care să elimine planificările neserializabile, forţând
setul de tranzacţii să se execute sub forma unei planificări
serializabile.
Serializabilitatea poate fi asigurată prin impunerea unor
restricţii asupra structurii interne a tranzacţiilor, dec în ce priveşte
secvenţa de paşi pe care o tranzacţie are voie să o execute. Un set de
asemenea restricţii poartă numele de protocol. Orice protocol care
asigură serializabilitatea constituie un algoritm de contro( al
concurenţei. În cazul folosirii primitivelor de blocare apare o
problemă suplimentară şi anume aceea a interblocărilor. Orice
tranzacţie care solicită o resursă care momentan nu este .disponibiliă,
deoarece este blocată de o altă tranzacţie, va fi pusă în aşteptare până
la eliberarea resursei. Dacă, la un moment dat sunt puse în aşteptare
mai multe tranzacţii simultan, atunci este posibilă formarea unui lanţ
circular de aşteptare în care fiecare tranzacţie blochează nişte resurse,
dar nu poate, în nici un fel, să-şi continue execuţia deoarece nu poate
obţine celelalte resurse decare are nevoie. În cele ce urmează
presupunem că este activ unul din algoritmii de prevenire, evitare sau
eliminare a interblocărilor.
Obiectivul urmărit în continuare este asigurarea
serializabilităţii pentru un set de tranzacţii concurente fâră a mai lua
în considerare problema interblocării.

251
Din punctul de vedere al algoritmilor de control al
concurenţei prin blocare prezintă interes acei paşi din cadrul
tranzacţiilor care corespund operaţiilor de tip blocare şi deblocare. În
consecinţă tranzacţiile vor fi privite ca secvenţe de operaţii LOCK şi
UNLOCK. De asemenea presupunem că sunt respectate următoarele
reguli:

1. Orice unitate de acces care este la un moment dat


blocată (prin LOCK) de o tranzacţie, trebuie să fie ulterior
deblocată (prin UNLOCK) de aceeaşi tranzacţie.
2. O tranzacţie nu încearcă să blocheze o unitate de acces
pe care o blochează deja.
3. O tranzacţie nu încearcă să deblocheze o unitate de
acces blocată de o altă tranzactie.\
La regulile de mai sus se adaugă restricţiile care derivă direct
din definiţia primitivelor LOCK şi UNLOCK. O unitate de acces
poate fi la un moment dat blocată de către o singură tranzacţie care
are accesul exclusiv la această unitate. Orice altă tranzacţie care
doreşte accesul la aceeaşi unitate trebuie să aştepte deblocarea
acesteia de către tranzacţia care a blocat unitatea. O planificare a
două sau mai multe tranzacţii care respectă regulile de mai sus este
considerată legală.
Exemplu:
Fie tranzactiile:
T1: LOCK A; LOCK B; UNLOCK A; UNLOCK B;
T2: LOCK A; UNLOCK A;
şi următoarea planificare:

252
T1 T2
LOCK A;
LOCK B;
LOCK A;
UNLOCK A;
UNLOCK A;
UNLOCK B;
Această planificare este ilegală deoarece este unposibil ca
tranzacţia T2 să obţină blocarea valorii A atâta timp cât aceasta este
blocată de către tranzacţia T1, deci operaţia LOCK A din T2 nu
poate fi situată în timp între operaţiile LOCK A şi UNLOCK A din
T1. De asemenea T2 nu poate debloca valoarea A atâta timp cât
aceasta este blocată de către T1.

8.5.2 Algoritm de testare a serializabilităţii

Acest algoritm ne permite să stabilim dacă o anumită


planificare a unui set de tranzacţii este sau nu serializabilă, deci dacă
există sau nu o planificare serială echivalentă cu planificarea dată.
Esenţa algoritmului constă în a examina ordinea în care
diferitele tranzacţii blochează fiecare unitate de acces în cadrul
planificării date. Ordinea în care tranzacţiile din planificarea dată
blochează o anumită unitate de acces determină ordinea de blocare a
acestei unităţi de acces de către tranzacţiile din planificarea serială
echivalentă.
Dar într-o planificarea serială toate unităţile de acces sunt
blocate în aceeaşi ordine care nu este alta decât ordinea de execuţie
serială a tranzacţiilor. Dacă o altă unitate de acces impune o ordonare
a tranzacţiilor diferită de prima, atunci se ajunge la o situaţie de
paradox, în care o anumită tranzacţie din planificarea serială ar trebui
concoinitent să preceadă, dar să şi urmeze unei alte tranzacţii.
Aceasta nu înseamnă altceva decât că nici o planificare serială nu
poate fi echivalentă cu planificarea dată, adică planificarea dată nu
este serializabilă.

253
Algoritmul de testare a serializabilităţii se poate expriina
ca o problemă de găsire a ciclurilor dintr-un graf orientat numit
graful de precedenţă.
Fiind dată o planificare P a unei mulţimi de tranzacţii M se
construieşte graful de precedenţă asociat astfel:
1. Nodurile grafului sunt tranzacţiile din M.
2. Arcul orientat de la nodul Ti la nodul Tj, TiTj, are
semnificaţia că există o unitate de acces pentru care tranzacţia Ti
obţine blocarea (pereche LOCK-UNLOCK) înaintea tranzacţiei Tj,
iar între Ti şi Tj nici o altă tranzacţie nu blochează această
unitate de acces.

Arcul TiTj arată că în orice planificare serială echivalentă


cu planificarea iniţială P, tranzacţia Ti se execută înaintea
tranzacţiei Tj. Este deci evident că dacă în graful de precedenţă
există un ciclu care include tranzacţiile Ti şi Tj, atunci în planificarea
serială echivalentă tranzacţia Ti se execută atât înaintea tranzacţiei T j
cât şi după. Acest lucru este imposibil într-o planificare serială, deci
nu poate exista o planificare serială echivalentă cu planificarea dată.
Dacă graful de precedenţă nu are cicluri, atunci există o planificare
serială echivalentă şi se poate determina o ordonare a tranzacţiilor
astfel încât Ti se execută înaintea lui Tj dacă există un arc TiTj.
Această ordonare se determină prin algoritmul de sortare topologică
definit astfel:
1. Dacă graful de precedenţă nu are cicluri, atunci există
un nod care nu este extremitate a nici unui arc. În caz contrar se
poate demonstra că graful are cicluri. Se localizează acest nod, se
elimină din graf împreună cu arcele adiacente, iar tranzacţia
corespunzătoare se trece în lista de tranzacţii a planificării
seriale.
2. Se reia pasul 1 până la epuizarea tuturor nodurilor.
Ordinea de eliminare a nodurilor din graful de precedenţă este
chiar ordinea de execuţie a tranzacţiilor în planificarea serială.
254
Exemple: 1. Fie tranzacţiile T1, T2, T3 şi următoarea
planificare:

T1 T2 T3
LOCK A;
LOCK B;
UNLOCK B;
LOCK B;
UNLOCK A;
LOCK A;
UNLOCK A;
LOCK A;
UNLOCK B;
UNLOCK A;

Construim graful de precedenţă asociat acestei planificări.


Nodurile sunt T1 T2 şi T3. Avem arcele T1T2 şi T2T3
deoarece tranzacţiile blochează unitatea A în ordinea T1, T2, T3.
Mai apare T3 arcul T2T1 ca o consecinţă a ordinii de blocare
asupra unităţii B. Graful de precedenţă o planifcare neserializabilă
denţă este prezentat în figura de mai jos

Fig. 8.4 Graful de precedenţă din exemplul 1

Se observă existenţa unui ciclu conţinând nodurile T1, şi T2,


ceea ce înseamnă că planificarea dată nu este serializabilă. O

255
planificare serială echivalentă ar trebui să execute tranzacţia T1,
înainte de T2, dar şi pe T2 înainte de T1 ceea ce este imposibil.

Exemplul 2. Fie planificarea:

T1, T2, T3
LOCK A;
UNLOCK A;
LOCK A;
UNLOCK A;
LOCK B;
UNLOCK B;
LOCK B;
UNLOCK B;

Graful de precedentă are nodurile T1 T2 T3


T1< T2< T3 şi
conţine arcele T1T3 (determinat de accesul la A) şi
T2T3 (determinat de accesul la B). Graful de precedenţă este
prezentat în figura 16. Graful nu are cicluri, deci planificarea este
serializabilă, iar planificarea serială echivalentă este (T1, T2, T3).

Fig. 8.5 Graful de precedenţă pentru exemplul 2

256
Algoritmul de testare a serializabilităţii bazat pe detectarea
ciclurilor din graful de precedenţă poate fi folosit, cel puţin teoretic,
pentru elaborarea unui mecanism general de control a concurenţei.
Aceasta ar presupune construirea dinamică a grafului de precedenţă
şi verificarea la fiecare pas a ciclicităţii sale. În cazul apariţiei unui
ciclu ar urma abortarea a cel puţin uneia dintre tranzacţiile vinovate
de apariţia ciclului în graful de precedenţă. Metoda aceasta s-a
dovedit a fi însă neviabilă în practică datorită costurilor mari pe care
le implică. Ori nu este permis ca metoda de control a concurenţei să
implice costuri suplimentare care să depăşească câştigul obţinut
datorită execuţiei concurente. Execuţia concurentă a tranzacţiilor,
împreună cu costurile suplimentare implicate de controlul
concurenţei, trebuie să fie, în orice situaţie, cel puţin la fel de
eficientă ca şi execuţia serială a aceloraşi tranzacţii.
Din acest motiv este preferată o altă abordare a problemei
controlului concurenţei şi anume aceea de a impune asupra
tranzacţiilor suficiente restricţii astfel încât nici o planificare posibilă
a acestora să nu violeze condiţia de serializabilitate. Aceste restricţii,
numite protocoale, reduc nivelul de concurenţă al sistemului, prin
faptul că admit doar un subset al planificărilor serializabile posibile
pentru o mulţime dată de tranzacţii.

8.5.3 Protocolul în două faze pentru asigurarea


serializabilitătii

Cel mai simplu protocol care asigură serializabilitatea unei


mulţimi de tranzacţii este protocolul în două. faze care se poate
formula astfel:
În orice tranzacţie toate operaţiile de blocare se execută
înaintea oricărei operaţii de deblocare.
Aşadar nu este permisă intermixarea operaţiilor de blocare şi
deblocare în cadrul tranzacţiilor. Tranzacţiile care respectă acest
protocol execută întâi toate operaţiile de blocare de care au nevoie,

257
urmează apoi operaţiile propriu-zise specifice fiecărei tranzacţii, iar
în final se execută operaţiile de deblocare.
Distingem deci două faze de execuţie care sunt comune tuturor
tranzactiilor din această categorie:
1. faza de acaparare a tuturor resurselor
necesare (blocările)
2. şi faza de eliberare a acestora
(deblocările).
Aceste tranzacţii poartă numele de tranzacţii în două faze. Se
poate enunţa următoarea teoremă:
TEOREMA 1 Orice planificare legală a unei mulţimi de
tranzactii în două faze este serializabilă.
Demonstratie: Prin reducere la absurd. Presupunem că există o
planificare a unui set de tranzacţii în două faze care nu este
serializabilă. Atunci graful de precedenţă corespunzător acestei
planificări conţine un ciclu:
TiTjTk...Ti.
Înseamnă că există o operaţie de blocare în Tj care este situată
după o operaţie de deblocare din Ti; în Tk există o blocare care
urmează unei deblocări din Tj ş.a.m.d. În final rezultă că Ti conţine o
operaţie de blocare situată după o operaţie de deblocare din cadrul ei,
ceea ce contrazice ipoteza că Ti este în două faze.

Trebuie menţionat faptul că acesta este singurul protocol cu


caracter general care asigură serializabilitatea. Cu alte cuvinte se
poate arăta că dacă T1, este o tranzacţie care nu este în două faze,
atunci se poate găsi o tranzacţie T2 astfel încât pentru T1, şi T2, există
o planificare care nu este serializabilă.
Fie deci T1 care nu este în două faze, atunci va exista o
operaţie de deblocare UNLOCK A care precede o operaţie de blocare
LOCK B. Fie Ti (i=1.2) tranzacţia:
Ti: LOCK A; LOCK B; UNLOCK A; UNLOCK B;

258
şi următoarea planificare:

T1 T2
_____________________________________
LOCK A;
UNLOCK A;
LOCK A;
LOCK B;
UNLOCK A;
UNLOCK B;
LOCK B;
UNLOCK B;

unde se poate observa că planificarea nu este serializabilă.

259
8.6. Tranzacţii cu accese de tip read-only şi read-
write
În cele de mai sus s-a considerat în mod implicit că o
tranzacţie care blochează o unitate de acces modifcă una sau mai
multe valori din cadrul acestei unităţi, cu alte cuvinte s-a considerat
că accesele sunt de tipul read-write. Înpractică însă, sunt foarte
frecvente tranzacţiile care fac acces la date doar pentru consultarea
acestora; este cazul tuturor tranzacţiilor care compun interogările
adresate bazelor de date. Despre aceste tranzacţii se ştie dinainte că
vor accesa datele doar în citire fâră a face modificări asupra lor. Dar
pentru efectuarea operaţiilor de citire nu este obligatorie excluderea
mutuală, aceeaşi dată poate fi citită de către mai multe tranzactii în
mod concurent fără ca acestea să se influenţeze reciproc, ordinea
citirilor find arbitrară. Este, deci, util să se facă distincţie între
accesele numai pentru citire (read-only) şi cele pentru citire-scriere
(read-write), deoarece astfel se pot formula protocoale care permit
un grad mai ridicat de concurenţă a operaţiilor. Într-un sistem care
face această distineţie se folosesc două primitive de blocare:

1. RLOCK - cerere de blocare pentru citire (read-lock)


numită şi cerere de blocare partajată (shared-lock). Este folosită de
tranzacţiile care doresc accesul la o valoare doar pentru operaţii de
citire. Dacă o tranzacţie blochează în citire o unitate de acces,
atunci nici o altă tranzacţie nu poate obţine blocarea în scriere a
acestei unităţi de acces, dar oricâte tranzacţii pot obţine în acest timp
blocarea în citire a aceleiaşi unităţi de acces.

2. WLOCK - cerere de blocare pentru citire-scriere (read-


write lock) numită şi cerere de blocare exclusivă (exclusive-lock).
Este folosită de către tranzacţiile care doresc, eventual, modificarea
unor valori din cadrul unităţii de acces şi este echivalentă cu

260
primitiva LOCK discutată în paragrafele precedente. Dacă o
tranzacţie blochează în citire-scriere o unitate de acces, atunci nici o
altă tranzacţie nu poate obţine blocarea acestei unităţi nici pentru
citire, nici pentru citire-scriere. Atât blocările pentru citire, cât şi
cele pentru citire-scriere sunt anulate prin executarea primitivei
UNLOCK.
O planificare a paşilor unei mulţimi de tranzacţii care conţin
primitiveRLOCK şi WLOCK este legală, dacă sunt respectate
următoarele reguli:
1. Orice unitate de acces blocată de o tranzactie trebuie să
fie deblocată de aceeaşi tranzacţie înainte de terminarea acesteia.
2. Nici o tranzacţie nu încearcă deblocarea unei unităţi de
acces pe care nu o blochează în citire sau citire-scriere.
3. Nici o tranzacţie nu încearcă blocarea pentru citire a
unei unităţi de acces pe care o blochează (fie în citire, fie în citire-
scriere).
4. Nici o tranzacţie nu încearcă blocarea pentru citire-
scriere a une unităţi de acces pe care o blochează în citire-scriere.
5. O tranzacţie poate cere şi obţine blocarea pentru citire-
scriere a unei unităţi de acces pe care o blochează deja în citire.
Această situaţie este posibilă deoarece blocarea în citire-scriere
este mai restrictivă decât blocarea doar pentru citire.

Două planificări ale unei mulţimi de tranzacţii care conţin


primitivele RLOCK şi WLOCK sunt echivalente dacă:

1. Produc aceeaşi valoare finală pentru toate datele accesate.


2. Valorile datelor asupra cărora se execută o primitivă
RLOCK sunt aceleaşi în ambele planificări (cu alte cuvinte valorile
citite de diferitele tranzacţii sunt aceleaşi pentru ambele planificări).

261
Algoritmul de testare a serializabilităţii pentru o planificare a
unui set de tranzacţii care efectuează asupra datelor accese de tip
read-only sau read-write este asemănător cu algoritmul prezentat
pentru cazul acceselor de tip read-write. Deosebirea provine din
faptul că, spre deosebire de accesele de tip read-write a căror ordine
de execuţie nu este indiferentă, operaţiile de tip read-only sunt
permutabile, deci ordinea lor de execuţie nu influenţează rezultatele.

262
Capitolul IX. PROCESAREA

TRANZACTIILOR ÎN PL/SQL

Procesarea tranzactiilor se face folosind instructiunile


COMMIT, SAVEPOINT si ROLLBACK care asigura consistenta
bazei de date. Procesarea tranzactiilor este o caracteristica a
ORACLE, disponibila in toate limbajele de programare, care permite
utilizatorilor sa lucreze concurent pe baza de date, si asigura ca
fiecare utilizator vede o versiune consistenta de date si toate
schimbarile sunt aplicate in ordinea corecta.

9.1 Folosirea comenzii COMMIT in PL/SQL


Comanda COMMIT termina tranzactia curenta, facand
modificari permanente in baza de date si vizibile utilizatorilor.
Tranzactiile nu sunt cuprinse in blocuri BEGIN-END in PL/SQL.
Un bloc poate contine mai multe tranzactii sau o tranzactie poate
imparti mai multe blocuri.

Exemplu: o tranzactie care transferabani dintr-un cont


bancar in altul. Este important ca banii sa fie scosi dintr-un
cont si pusi in altul in acelasi moment. Altfel pot aprea
probleme ca pierderea banilor sau duplicarea lor in ambele
conturi.

CREATE TABLE accounts (account_id NUMBER(6),


balance NUMBER (10,2));
INSERT INTO accounts VALUES (7715, 6350.00);
INSERT INTO accounts VALUES (7720, 5100.50);
DECLARE
transfer NUMBER(8,2) := 250;
BEGIN

263
UPDATE accounts SET balance = balance - transfer
WHERE account_id = 7715;
UPDATE accounts SET balance = balance + transfer
WHERE account_id = 7720;
COMMIT COMMENT 'Transfer From 7715 to 7720'
END;

Clauza optionala COMMENT permite specificarea unui


comentariu asociat tranzactiei. Daca reteaua sau calculatorul
cad in timpul opratiei commit, starea tranzactiei poate fi
necunoscuta. In acest caz Oracle memoreaza textul specificat
de COMMENT in dictionarul de date impreuna cu ID
tranzactiei.

264
9.2 Folosirea comenzii ROLLBACK in PL/SQL
Comanda ROLLBACK termina tranzactia curenta si
anuleaza toate schimbarile facute in timpul tranzactiei. Daca s-a sters
din greseala o inregistrare din tabela, aceasta oparatie anuleaza
efectul stergerii. Daca nu se doreste terminarea unei tranzactii in
momentul in care apare o eroare, operatia rollback permite actiunea
de anulare.

Exemplu: inserarea informatiei despre un angajat in 3 tabele


diferite. Daca se incearca inserarea unui angajat cu id duplicat,
exceptia predefinita DUP_VAL_ON_INDEX este generata. Pentru a
ne asigura ca schmibarile la cele 3 tabele sunt anulate, managerul
erorii va executa operatie ROLLBACK.

CREATE TABLE emp_name AS SELECT employee_id,


last_name FROM employees;
CREATE UNIQUE INDEX empname_ix ON emp_name
(employee_id);
CREATE TABLE emp_sal AS SELECT employee_id,
salary FROM employees;
CREATE UNIQUE INDEX empsal_ix ON emp_sal
(employee_id);
CREATE TABLE emp_job AS SELECT employee_id,
job_id FROM employees;
CREATE UNIQUE INDEX empjobid_ix ON emp_job
(employee_id);

DECLARE
emp_id NUMBER(6);
emp_lastname VARCHAR2(25);
emp_salary NUMBER(8,2);
emp_jobid VARCHAR2(10);
BEGIN
SELECT employee_id, last_name, salary, job_id INTO
emp_id, emp_lastname,emp_salary, emp_jobid FROM
employees WHERE employee_id = 120;

265
INSERT INTO emp_name VALUES (emp_id,
emp_lastname);
INSERT INTO emp_sal VALUES (emp_id, emp_salary);
INSERT INTO emp_job VALUES (emp_id, emp_jobid);
EXCEPTION
WHEN DUP_VAL_ON_INDEX THEN
ROLLBACK;
DBMS_OUTPUT.PUT_LINE('Inserts have been rolled
back');
END;

266
9.3 Fosirea comenzii SAVEPOINT in PL/SQL
SAVEPOINT denumeste si marcheaza punctul curent din
procesarea tranzactiei. Punctele de salvare permit sa nu se anuleaza
efectele intregii tranzactii ci numai o parte din ele sa fie anulate.
Numarul de puncte de salavare dintr-o sesiune este nelimitat.

Exemplu: marcarea unui punct de salvare inainte de o


operatie de insetare. Daca se insereaza o inregistrare duplicat apere
eroarea predefinita DUP_VAL_ON_INDEX. In acest caz se vor
anula efectele pana la punctul de salvare, adica efectele
operatiei de inserare numai.

CREATE TABLE emp_name AS SELECT employee_id, last_name,


salary FROM employees;
CREATE UNIQUE INDEX empname_ix ON emp_name
(employee_id);

DECLARE
emp_id employees.employee_id%TYPE;
emp_lastname employees.last_name%TYPE;
emp_salary employees.salary%TYPE;
BEGIN
SELECT employee_id, last_name, salary INTO emp_id,
emp_lastname,
emp_salary FROM employees WHERE employee_id = 120;
UPDATE emp_name SET salary = salary * 1.1 WHERE
employee_id = emp_id;
DELETE FROM emp_name WHERE employee_id = 130;
SAVEPOINT do_insert;
INSERT INTO emp_name VALUES (emp_id, emp_lastname,
emp_salary);
EXCEPTION
WHEN DUP_VAL_ON_INDEX THEN
ROLLBACK TO do_insert;
DBMS_OUTPUT.PUT_LINE('Insert has been rolled
back');
END;

Cand se anuleaza efectele pana la un punct de salvare, toate


punctele de salvare dupa acesta sunt sterse. Punctul de slvare pana la
267
care s-au anulat efectele nu este sters. Un simplu rollback sau
commit sterg toate punctele de salvare.

Punctele de salvare sunt identificatori nedeclarati. Refolosirea


lor intr-o tranzactie muta punctul de salvare de la vechea pozitie la
pozitia curenta din tranzactie. Aceasta inseamna ca operatia rollback
la punctul de salvare afecteaza numai partea pana curenta din
tranzactie.

Exemplu : refolosirea SAVEPOINT cu ROLLBACK

CREATE TABLE emp_name AS SELECT employee_id, last_name,


salary FROM employees;
CREATE UNIQUE INDEX empname_ix ON emp_name
(employee_id);

DECLARE
emp_id employees.employee_id%TYPE;
emp_lastname employees.last_name%TYPE;
emp_salary employees.salary%TYPE;
BEGIN
SELECT employee_id, last_name, salary INTO emp_id,
emp_lastname,
emp_salary FROM employees WHERE employee_id = 120;
SAVEPOINT my_savepoint;
UPDATE emp_name SET salary = salary * 1.1 WHERE
employee_id = emp_id;
DELETE FROM emp_name WHERE employee_id = 130;
SAVEPOINT my_savepoint; -- move my_savepoint to
current poin
INSERT INTO emp_name VALUES (emp_id, emp_lastname,
emp_salary);
EXCEPTION
WHEN DUP_VAL_ON_INDEX THEN
ROLLBACK TO my_savepoint;
DBMS_OUTPUT.PUT_LINE('Transaction rolled back.');
END;

268
9.4 Setarea proprietăţilor tranzacţiilor cu comanda
SET TRANSACTION

9.4.1. SET TRANSACTION READ ONLY

SET TRANSACTION se foloseste pentru a incepe o


tranzactie read-only sau read-write, pentru a stabili un nivel de
izolare sau pentru a atribui tranzactia curenta unui anumit segment de
rollback. Tranzactiile “read-only “ sunt folosite pentru a executa mai
multe interogari “select” in timp ce alti utilizatori modifica acelasi
tabele.

Exemplu : managerul unui magazin foloseste o tranzactie


read-only pentru a afisa totatulul tranzactiilor pe zi si pe luna trecuta.
Totalurile sunt neafectate de alte modificari pe baza de date in timpul
tranzactiei.

DECLARE
daily_order_total NUMBER(12,2);
weekly_order_total NUMBER(12,2);
monthly_order_total NUMBER(12,2);
BEGIN
COMMIT; -- ends previous transaction
SET TRANSACTION READ ONLY NAME 'Calculate Order
Totals';
SELECT SUM (order_total) INTO daily_order_total FROM
orders
WHERE order_date = SYSDATE;
SELECT SUM (order_total) INTO weekly_order_total FROM
orders
WHERE order_date = SYSDATE - 7;
SELECT SUM (order_total) INTO monthly_order_total
FROM orders
WHERE order_date = SYSDATE - 30;
COMMIT; -- ends read-only transaction
END;

269
Daca o tranzactie este setata READ ONLY, toate interogarile
din tranzactie vor vedea numai schimbarile efectuate inainte de a
incepe tranzactia. Folosirea unei tranzactii READ ONLY nu
afecteaza alti utilizatori sau alte tranzactii.

Restrictiile operaţiei SET TRANSACTION


Numai comenzile SELECT INTO, OPEN, FETCH,
CLOSE, LOCK TABLE, COMMIT si ROLLBACK sunt
permise intr-o tranzactie read-only.

9.4.2. SET TRANSACTION READ WRITE

Acesta este implicit in Oracle. O posibila operatie din


tranzactie poate vizualiza numai datele care au fost deja terminate
(comise) inainte ca opratia respectiva sa inceapa (si nu cand
tranzactia a inceput)

9.4.3. Clauza ISOLATION LEVEL

Folosirea clauzei ISOLATION LEVEL specifică cum sunt


administrate tranzacţiile care conţin modificări ale bazei de date.

 Setarea la SERIALIZABLE : specifica ca o tranzactie care


contine limbaj de manipulare a datelor(DML) care asteapta
modificarea oricarei resurse care a fost modificata intr-o alta
tranzactie neterminata inca la inceputul tranzactiei
serializabile, atunci DML esueaza.
 Setarea la READ COMMITTED: specifică o tranzacţie
care conţine limbaj de manipulare a datelor(DML) şi care
cere blocarea unor înregistrări deţinute de alta tranzacţie; în
acest caz operaţiile DML asteaptă până ce blocările sunt
eliberate.

270
9.5 Blocări explicite
Implicit, Oracle blocheaza structurile de date - o
caracteristica importanta pentru Oracle.

Exista 2 tipuri de blocari:

a. Blocare la nivelul înregistrării


b. Blocare la nivelul tabelei

Se pot cere blocari de date pe anumite inregistrari sau pe tabele


intregi daca este nevoie sa se rescrie blocarile implicite. Blocarile
explicite permit blocarea accesului la date in timpul unei tranzactii.

 Cu comanda LOCK TABLE se poate bloca o tabela


intreaga
 Cu comanda SELECT FOR UPDATE se pot bloca explicit
anumite randuri(rows) pentru a se asigura ca ele nu schimba

Folosirea clauzei FOR UPDATE

Cand se declara un cursor care va fi referit in operatii


UPDATE sau DELETE trebuie folosita clauza FOR UPDATE
pentru a obtine blocare exclusiva pe inregistrari

DECLARE
CURSOR c1 IS SELECT employee_id, salary FROM employees
WHERE job_id = 'SA_REP' AND commission_pct > .10
FOR UPDATE NOWAIT;

Comanda SELECT ... FOR UPDATE identifică


înregistrările care vor fi modificate sau şterse, apoi blochează fiecare
rând din setul rezultat. Aceasta este folositoare cand se doreşte o
modificare pe valorile existente din înregistrare (row). În acest caz

271
trebuie asigurat că nu se efectuează modificări asupra rândului de
către alt utilizator înainte de update.

Cuvântul cheie opţional NOWAIT precizează că nu trebuie


aşteptat dacă rândurile cerute au fost blocate de alt utilizator.
Controlul este imediat intors în program pentru a efectua alte operaţii
până când se vor putea bloca rândurile. Daca se omite NOWAIT,
Oracle va astepta până când înregistrările sunt disponibile.

Cand se interogheaza tabele multiple, rândurile din tabele sunt


blocate numai daca clauza FOR UPDATE OF referenţiază o
coloană din acea tabela. De exemplu, urmatoarea interogare
blocheaza rândurile din tabela employees, dar nu si din tabela
departments.

DECLARE
CURSOR c1 IS SELECT last_name, department_name FROM
employees, departments
WHERE employees.department_id = departments.department_id
AND job_id = 'SA_MAN'
FOR UPDATE OF salary;

Exemplu: folosirea clauzei CURRENT OF intr-o


instructiune UPDATE sau DELETE pentru a referi ultima
inregistrare returnata de un cursor.

DECLARE
my_emp_id NUMBER(6);
my_job_id VARCHAR2(10);
my_sal NUMBER(8,2);
CURSOR c1 IS SELECT employee_id, job_id, salary FROM
employees FOR UPDATE;
BEGIN
OPEN c1;
LOOP

272
FETCH c1 INTO my_emp_id, my_job_id, my_sal;
IF my_job_id = 'SA_REP' THEN
UPDATE employees SET salary = salary * 1.02 WHERE
CURRENT OF c1;
END IF;
EXIT WHEN c1%NOTFOUND;
END LOOP;
END;

Consideram 2 sesiuni SQL:

Sesiunea I

SQL> SELECT Salary


FROM employees
WHERE employee_id = 100
FOR UPDATE OF salary;

Sesiunea II

SQL> update employees


set salary=20000
where employee_id=100;

Tranzacţia va eşua, deoarece în Sesiunea 1 inregistrarea a fost


blocată. Tranzacţia din sesiunea 2 va fi executată dacă înainte
executăm COMMIT sau ROLLBACK pentru a elibera blocarea
asupra înregistrării.

Sesiunea I
SQL> SELECT Salary
FROM employees
WHERE employee_id = 100
FOR UPDATE OF salary;

273
SQL> rollback;

Rollback complete.

Sesiunea II
SQL> update employees
set salary=20000
where employee_id=100;

274
BIBLIOGRAFIE

1. Bâscă, O., Baze de date, Editura All, Bucureşti, 1997;


2. Bot, Ed, Leonhard, Woody, Microsoft Office XP, traducere de
Simona şi Titi Preda, Editura Teora, Bucureşti, 2003;
3. Conolly, T., Begg, C., Strachan, A., Baze de date,.
Proiectare, implementare, gestionare, Editura Teora,
Bucureşti, 2001;
4. Boldea, C, Lupşoiu C, Modelarea şi Proiectarea Bazelor de
Date, Ed. Sitech, Craiova, 2008;
5. Florescu, V., ş.a., Baze de date, Editura Economica,
Bucureşti, 1999;
6. Forta, B., SQL în lecţii de 10 minute, traducere de Mihai
Mănăstireanu, Editura Teora, Bucureşti, 2007;
7. Fotache, M., Baze de date relaţionale. Organizare,
interogare şi normalizare, Editura Junimea, Iaşi, 1997;
8. Fotache, M., SQL. Dialecte DB2, Oracle, Visual FoxPro,
Editura Polirom, Iaşi, 2001;
9. Fotache, M., Proiectarea bazelor de date. Normalizare,
postnormalizare, Editura Polirom, Iaşi, 2005;
10. Hernandez, M. J., Proiectarea bazelor de date, Editura
Teora, Bucureşti, 2003;
11. Năstase, P., Tehnologia bazelor de date, Access 2000,
Editura Economică, Bucureşti, 2000;
12. Oppel, A., SQL fără mistere, traducere de Cristian Mocanu,
Florin Moraru, Editura Rosetti Educational, Bucureşti, 2006;
13. Petrov, G şi alţii, Teoria generală a bazelor de date; Editura
Mirton, 2000;

275
14. Stepan A., Petov G. şi V. Iordan, Fundamentele Proiectării şi
Realizării Sistemelor Informatice, Ed. Mirton, Timişoara,
1995.

276
Anexă: Funcţii predefinite
în PL/SQL
a. Funcţii pentru date:

FUNCŢIE DESCRIERE Tip


SYSDATE Data şi ora curentă Date
MONTHS_BETWEEN(d1,d2) Numărul de luni dif. Number
ADD_MONTHS(d,n) Adaugă o lună la o dată Date
NEXT_DAY(d) Ziua următoare datei specificate Date
LAST_DAY(d) Ultima zi a unei luni Date
ROUND(d[‚’fmt’]) Data „rotunjită” Date
TRUNC(d[,’fmt’]) Data „trunchiată” Date

 MONTHS_BETWEEN(d1,d2)- returnează numărul de


luni dintre d1(data1) şi d2(data2). Rezultatul poate fi o
valoare pozitivă sau negativă. Partea zecimală (în cazul
în care apare) reprezintă o parte dintr-o lună.
 ADD_MONTHS(d,n)- adaugă n luni calendaristice la o
dată d; n trebuie să fie întreg şi poate fi negativ.
 NEXT_DAY(d,’char’)- găseşte data următoarei zile
specificate a săptămânii (‘char’) care urmează datei (d);
char poate fi un număr reprezentând o zi sau un şir de
caractere.
 LAST_DAY(d)- găseşte data ultimei zile a lunii care
conţine data d.
 ROUND(d[,’fmt’])- returnează data d rotunjită la
elementul specificat de formatul fmt. Dacă fmt este
omis, data d e rotunjită la cea mai apropiată dată.

277
 TRUNC(d[,’fmt’])- returnează data d trunchiată la
formatul specificat prin fmt . Dacă fmt e omis, data d e
trunchiată la cea mai apropiată valoare.

b. Fucţii pentru caractere

 LOWER(şir)- transformă caracterele şirului în litere


mici;
 UPPER(şir) - transformă caracterele şirului în
majuscule;
 INITCAP(şir) –transformă primul caracter al fiecărui
cuvânt din şir în majusculă ;
 CONCAT(şir1,şir2) – concatenează cele două şiruri; e
echivalent cu operatorul de concatenare(||);
 SUBSTR(şir,m[,n]) – extrage din şirul de caractere un
subşir de lungime m începând de la poziţia n;
 LENGTH(şir) – returnează lungimea unui şir de
caractere;
 INSTR(şir1,şir2[,n[,m]]) – returnează poziţia celei de-a
m-a apariţii a lui şir2 în şir1 începând cu poziţia n
(implicit m=n=1), iar dacă nu se găseşte întoarce
valoarea 0;
 REPLACE(şir,a[,b]) – înlocuieşte în şirul de caractere
secvenţa a prin secvenţa b, iar dacă lipseşte b, atunci
are loc ştergerea lui a;
 LTRIM(şir) / RTRIM(şir) – şterge spaţiile libere din
stânga şirului de caractere, respectiv din dreapta lui;
 LPAD(şir1,n,şir2) / RPAD(şir1,n,şir2) – şir1 este
completat la stânga, respectiv la dreapta, până la
lungimea n, prin şir2;
 SOUNDEX(şir) – reprezentarea fonetică a şirului de
caractere.

278
c. Fucţii numerice

 ABS(n) – valoarea absolută a numărului;


 CEIL(n) – cel mai mic întreg mai mare sau egal cu n;
 FLOOR(n) – cel mai mare întreg mai mic sau egal cu n;
 MOD(m,n) – restul împărţirii lui m prin n;
 SQRT(m) – rădăcină pătrată din m (null, dacă m<0);
 ROUND(n[,m]) – numărul n este rotunjit la m poziţii
zecimale;
 TRUNC(n[,m]) – numărul n este trunchiat la m poziţii
zecimale;
 LN(x) – implementează funcţia logaritmică
ln(x)(logaritm natural);
 EXP(x) – implementează funcţia exponenţială;
 POWER(m,n) - implementează funcţia putere (m la
puterea n);
 SIGN(n) - implementează funcţia semn asociată lui n;
 GREATEST(m,n) – cel mai mare dintre numerele m şi
n;
 LEAST(m,n) – cel mai mic dintre numerele m şi n;

279
280

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