CAPITOLUL I. SQL ȘI VARIANTE UTILE ALE L IMBAJULUI 6 1.1. Elemente SQL 6 1.1.1. Tabele SQL 6 1.1.2. Tipuri de date de bază 7 1.1.3. Alegerea celui… [627118]

3
Cuprins

INTRODUCERE 5
CAPITOLUL I. SQL ȘI VARIANTE UTILE ALE L IMBAJULUI 6
1.1. Elemente SQL 6
1.1.1. Tabele SQL 6
1.1.2. Tipuri de date de bază 7
1.1.3. Alegerea celui mai bun tip de date pentru o coloană 8
1.1.4. Operatorii SQL 8
1.1.4.1. Operatori unari și o peratori binari 8
1.1.4.2. Precedența operatorilor 9
1.1.4.3. Operatorii aritmetici 9
1.1.4.4. Operatorul de concatenare 10
1.1.4.5. Operatori de set 10
1.1.5. Expresiile SQL 11
1.1.5.1. Expresii simple 12
1.1.5.2. Expresii cursor 13
1.1.5.3. Expresii func ție 13
1.1.5.4. Expresii subinterogări scalare 13
1.1.5.5. Expresii regulare 14
1.1.5.6. Liste de expresii 14
1.1.6. Condițiile SQL 15
1.1.6.1. Precedența condițiilor 17
1.1.6.2. Condițiile de comparație 17
1.1.6.3. Condiții de comparație simple 18
1.1.6.4 . Condiții logice 19
1.1.6.5. Condiții de apartenență 20
1.1.6.6. Condiții de întindere 21
1.1.6.7. Condiții de NULL 21
1.1.6.8. Condiții EXISTS 22
1.1.6.9. Condiții LIKE 22
1.1.6.10. Condiții compuse 23
1.1.7. Funcții SQL 23
1.1.7.1. Funcțiile șir de cara cter 23
1.1.7.2. Funcțiile matematice 23
1.1.7.3. Funcții dată și timp 24
1.1.7.4. Funcții de căutare full -text 25
1.1.8. Tipul de calendar folosit de MySQL 25
1.1.9. Clauze SQL Data Definitio n Language – definirea tabelelor și constrângeri 26
1.1.9.1. Definirea tabelelor 26

4
1.1.9.2. Definirea constrângerilor 26
1.1.10. Interogări și Subinterogări 27
1.1.10.1. Crearea interogărilor simple 27
1.1.10.2. Sortarea rezultatelor interogărilor 27
1.1.10.3. Join 28
1.1.10.4. Utilizarea subinterogărilor 28
1.1.11. Modificarea datelor în SQL 29
1.1.11.1. Inserări 29
1.1.11.2. Actualizări 29
1.1.11.3. Ștergeri 30
1.1.11.4. Commit și Rollback 30
1.1.12. Comentarii asupra tabelelor 30
1.1.12.1. Modificarea definițiilor tabelelor și coloanelor 30
1.1.12.2. Ștergerea unei tabele 30
1.1.13. Vederi 31
CAPITOLUL II. INTEGR AREA SQL ÎN LIMBAJEL E DE NIVEL ÎNALT 32
2.1. Interfețe de programare a aplicațiilor SQL 33
2.1.1 Java Database Connectivity(JDBC) 33
CAPITOLUL III. ELABO RAREA SISTEMULUI INF ORMATIC CU SQL 49
3.1 “Cursuri Traininguri Conferinte” – Prezentare 49
3.1.1 Interfața aplicației 49
3.1.1.1 Header 49
3.1.1.3 Sidebar 50
3.1.1.4 Conținutul 51
3.1.1.5 Footer 51
3.1.2 Adăugare cursuri 51
3.1.3 Cursurile adăugate 52
3.2. “Cursuri Traininguri Conferinte” – design și codul sursa 54
CONCLUZII 55
BIBLIOGRAF IE 56

5
Introducere

Toți sunt em familiari cu termenul de dată. De fapt, fără să ne dăm seama, ne
întâlnim cu date în fiecare zi din viața noastră obișnuită. Vârsta unei persoane, prețul
cartofilor, numărul de studenț i dintr -o facultate, codul po ștal al unui oraș, etc. sunt
câteva exemple de date. În viaț a noastr ă trebuie să reț inem foarte multe date. De
exemplu, s -ar putea să ni se ceară să spunem cu acuratețe vâ rsta, venitul, adresa,
calificarea educa țională, etc. ale părinților noș tri. Dar este prea dificil pentru noi să
memoră m toate aceste informa ții pentru un număr mare de persoane. Dacă luăm
exemplul Universită ții de Vest Timișoara, în fiecare an, mii de candidați se î nscriu
pentru admitere la această universitate. Ar fi imposibil pentru oricare dintre noi s ă
reținem data naș terii, subiectele primite ș i adresa tuturor acestor posibili viitori studenț i.
Pentru a putea face față unor asemenea probleme, construim o baz ă de date și un
sistem prin care să o putem accesa și gestiona. Vom organiz a toate infor mațiile într-o
formă tabelară, î n așa fel încât, în cazul în care suntem întrebați, “Câți candidați sunt
înscriș i pentru Facultatea de Matematică -Informatică, secția Informatică?” să fim
capabili să ră spundem.
Totuși, î n cazul î n care nu sunte m interesați de modul în care a fost concepută baza
de date ș i care sunt structurile si elementele care ne permit obț inerea tuturor datelor
cerute, sau nu știm ce reprezintă o bază de date , ar trebui să avem la dispoziție o
aplicați e care să ne permită să vizualizăm aceste date, fără a fi nevoie să concepe m un
cod complicat de accesare și extragere a informaț iei din baza de date. Majo ritatea
persoanelor care achiziționează un PDA, nu se preocupă de software -ul care
funcționează în sc opul stocării și afișă rii datelor despre întâ lniri sau conferin țe, ci iș i
doresc un mediu prietenos care să le permită obținerea informației în cea mai rapidă și
simplă modalitate. De aceea, odată cu crearea unei baze de date, de cele mai multe ori
este ne cesar ă și crearea unei in terfețe care să permită utilizatorilor obișnuiți să iși
desfășoare activitățile în cel mai plăcut ș i rapid mod relativ la această bază de date .
Definiția interfeței este una largă ș i poate lua mai multe forme î n funcț ie de aria la
care se referă . Ca si concept general, o interfaț ă reprez intă un dispo zitiv sau sistem pe
care entită țile ne înrudite îl folosesc pentru a comunica.
Interfața a fost realizată cu ajutorul limbajelor de programare HTML, PHP,
JavaScript, Json si cu ajutorul bazei de date MySQL.
Titlul lucrării de licență este ”Cursuri, Traininguri Conferinte”.

6
Capitolul I. SQL ș i variante utile ale limbajului

Programa rea SQL a devenit mai importantă azi ca oricând. Când bazele de date
relaționale au fost introdus e pentru prima dată, definiț ia unui bu n programator SQL era
o persoană care putea să dea răspunsul unei probleme cât mai repede posibil. Totuși,
odată cu creș terea importanț ei scrierii unui cod eficient, astă zi, programat orul SQL are
de asemenea atribuț ia de a scrie repede un cod car e să fie executat într -o manieră
optimă .
Acest capitol este dedicat pro blemelor interne de programare î n SQL.
A învăța să gândim î n termenii SQL este un salt destul de brusc pentru fiecare
dintre noi. Mare parte a carierei de p rogramator este petrecută scriind cod procedural și
dintr -o dată, trebuie să facem față codului non -procedural. Ș ablonul de gândire trebuie
să se schimbe de la secvenț e la seturi de date despre anumite elemente.
Ca și exemplu, putem considera un mesaj de pe unul din site -urile Microsoft SQL
Server: “Am nevoie de ajutor cu o propoziție care va returna înregistră ri distincte
pentru primele trei câ mpuri unde toate valorile din câ mpul 4 sunt toate egale cu 0.”
Putem observa că acest text nu este destul de elocv ent și corect. Dar acest lucru este
tipic pentru persoanele ca re scriu mesaje pe Internet cerâ nd ajutor legat de SQL. În
primul rând, într -o bază de date SQL nu există câ mpuri, ci coloane. În momentul în
care o persoană se referă la câmpuri î n loc de colo ane, ne putem da seama că nu
gândește în termenii corecți. Un câ mp este definit în cadrul programului aplicație. O
coloană este definită î n cadrul bazei de da te, independent de codul aplicaț iei. De aceea,
un apel la o rutină a unei librării î ntr-un limbaj pro cedural cum ar fi: “READ a,b,c,d
FROM my_file” este diferit de “ READ d, c, b, a FROM my_file” î n timp ce “SELECT
a,b,c,d FROM my_table” ș i “SELECT d ,c,b,a FROM my_table” reprezintă același
lucru într -o ordine diferită .

1.1. Elemente SQL
1.1.1. Tabele SQL
În sistemel e de baze de date relaț ionale (DBS), datele sunt re prezentate folosind
tabele (relaț ii). O intero gare aplicata DBS -ului generează de asemenea o tabelă . O
tabelă are următoarea structură :

Coloana 1 Coloana 2 Coloana n …

… … …

7
O tabelă este indentificată î n mod unic de către numele său și este alcătuită din
rânduri care c onțin informația depozitată, fiecare rând conținând exact un tuplu (o
înregistrare). O tabelă poate avea una sau mai multe coloane. O coloană este formată
dintr -un nume și un tip de date, ș i des crie un atribut al înregistră rii. Structura unei
tabele , denumită de asemenea schema relațiilor, este așadar definită de atributele sale.
Tipul de informație care trebuie depozitată î ntr-o tabelă este definit de tipurile de date
ale atributelor la momentu l creă rii tabelei.
SQL folosește termenii de tabelă, rând și coloană pentru relații, tuplu ș i respectiv,
atribut. O tabelă poate avea până la 254 de coloane care pot avea aceleași sau diferite
tipuri de date ș i seturi de valori(domenii). Domeniile posibile sunt date
alfanumerice(string), numere ș i formate de date.

1.1.2. Tipuri de date de bază
MySQL suportă un număr de tipuri de date din categorii diferite : tipuri de date
numerice, dată și timp, și tipuri de date șiruri de caractere.
MySQL suportă toate tipurile de d ate numerice standard SQL. Aceste tipuri includ
tipurile de date numerice exacte(INTEGER, SMALLINT, DECIMAL și NUMERIC),
și de asemenea tipurile de date numerice cu virgulă(FLOAT, REAL și DOUBLE
PRECISION). Cuvântul cheie INT este sinonimul pentru INTEGER, iar cuvântul cheie
DEC este sinonimul pentru DECIMAL. Tipul de date numeric folosit pentru rezultatele
calculelor depinde de operațiile care sunt efectuate și de tipurile numerice ale
operanzilor. Ca și extensie la standardul SQL, MySQL suportă de asemene a tipurile
TINYINT, MEDIUMINT si BIGINT.
Tipurile de date date și time pentru reprezentarea valorilor temporale sunt
DATETIME, DATE, TIMESTAMP, TIME șî YEAR. Fiecare tip temporal are un
interval de valori posibile, la fel ca și o valoare « zero » care est e folosită atunci când
specificăm o valoare ilegală pe care MySQL nu o poate reprezenta. Tipul
TIMESTAMP are un comportament special de actualizare automată. Pentru tipul de
date DATE, intervalul suportat este de la ‘1000 -01-01’ la ‘9999 -12-31’. MySQL
afișează valorile în formatul ‘YYYY -MM-DD’, dar permite asignarea valorilor la
coloanele de tip DATE folosind fie șiruri de caractere, fie numere.
O coloană TIMESTAMP este utilă pentru înregistrarea datei și timpului unei
operații de INSERT sau UPDATE. Implici t, prima coloană TIMESTAMP dintr -o
tabelă este setată automat pe data și timpul celei mai recente operații dacă nu ii asignăm
personal o altă valoare. Putem de asemenea seta orice coloană TIMESTAMP la data
curentă asignându -i o valoare NULL.
Funcțiile agre gate SUM() și AVG() nu funcționează cu valori temporale, ele
convertind aceste valori la numere, lucru care pierde parte de după primul caracter non –
numeric. Pentru a soluționa această problemă, putem converti în unități numerice, apoi
putem aplica operați a agregat și apoi să convertim din nou în valoarea temporală.
Tipurile de date șir de caractere sunt următoarele : CHAR, VARCHAR, BINARY,
VARBINARY, BLOB, TEXT, ENUM și SET.

8
Clauza DEFAULT valoare este o specificație pentru tipurile de date care indică o
valoare implicită pentru o coloană. Cu o singură excepție, valoare implicită trebuie să
fie o constantă, nu poate fi o funcție sau o expresie. Acest lucru înseamnă că, de
exemplu, nu putem seta ca valoarea implicită pentru o coloană de tip date să fie o
funcție ca și NOW() sau CURRENT DATE. Excepția este că putem specifica
CURRENT TIMESTAMP ca valoare implicită pentru o coloană TIMESTAMP.
Dacă o definiție de coloană nu include o valoare DEFAULT, MySQL determina
această valoare după cum urmează:
 Dacă coloana poate lua valoarea NULL, coloana este definită cu o
clauză DEFAULT NULL
 În caz contrar, MySQL definește coloana cu o clauză DEFAULT
explicită, utilizând valoare implicită DEFAULT pentru tipul de date al coloanei
respective(de exemplu, pentru tipurile nume rice, tipul implicit este 0 sau
următoarea valoare din secvență pentru tipurile declarate cu atibutul
AUTO_INCREMENT).
Tipurilor de date BLOB și TEXT nu li se poate asigna o valoare implicită. Pentru o
tabelă dată, putem folosi propoziția SHOW CREATE TAB LE pentru a vedea care
coloane au o clauză DEFAULT explicită.
1.1.3. Alegerea celui mai bun tip de date pentru o coloană
Pentru o depozitare cât mai eficientă, trebuie să încercăm sa folosim cel mai precis
tip în toate cazurile. De exemplu, dacă o coloană integer este folosită pentru valori între
1 și 99999, MEDIUMINT UNSIGNE D este cel mai bun tip de date, deoarece dintre
toate tipurile de date care pot reprezenta valorile cerute, acesta folosește cel mai puțin
spațiu de depozitare.
Pentru versiunile MySQL anterio are, reprezentarea precisă a valorilor monetare era
o problemă comună. În aceste versiuni MySQL, ar trebui să folosim și tipul
DECIMAL. În acest caz, valoarea este depozitată ca și un șir de caractere, așa că un ar
trebui să apară vreo pierdere a acurateți i la depozitare. Totuși calculele asupra acestor
valori DECIMAL sunt realizate folosind operații cu dublă precizie. Putem folosi
PROCEDURE ANALYSE atunci când dorim să obținem sugestii pentru găsirea
tipurilor de date optime pentru coloane.
1.1.4. Operatorii SQL
Operatorii manipulează itemi de date individuali denumiț i operanzi sau argumente.
Operatorii sunt reprezentați de că tre caractere speciale sau cuvinte cheie. De exemplu,
operatorul de înmulț ire este reprezent at de că tre un asterisc (*).
1.1.4.1. Operatori un ari și operatori binari
Cele două clase generale de operatori sunt:
 operatorii unari – acei operatori care operează un singur o perand. Un operator
unar apare în general împreună cu operandul să u în urmă torul format:
operator operand

9
 operatorii binari – acei oper atori care operează doi operanzi. Un operator binar
apare împreună cu operanzii săi în urmă torul format:
operand1 operator operand2
Dacă unui operator îi este ataș at un operand NULL, rezultatul este î ntotdeauna
NULL. Singurul operator care nu respectă acea stă regulă este operatorul de concatenare
(||).
1.1.4.2. Precedenț a operatorilor
Precedența r eprezintă ordinea în care MySQL va evalua diferiț i operatori din
aceeaș i expresie. Atunci când evaluează o expresie ce conține mai m ulți operatori,
MySQL evaluează operator ii cu precedență mai mare î nainte de a ev alua acei operatori
cu precedență scă zută. MySQL evaluează operatorii cu aceeași precedență de la stânga
la dreapta î n interiorul unei expresii.

Operator Opera ție
+,-(operatori unari) Identitate, negație
*, / Multiplicare, diviziune
+,-(operatori binari), || adăugare, concatenare
Condiț iile SQL sunt evalua te după operatorii SQL
Tabelul 1 .1. Exemple de operatori
Parantezele pot fi folosite î ntr-o expresie pentru a se suprapune precedenț ei
operatorilor. MySQL evaluează expresii le din interiorul parantezelor î nainte de a evalua
acele expresii din exteriorul parantezelor. MySQL suportă de asemenea operatori de set
(UNION, UNION ALL ), care combină seturi de rânduri returnate de către interogări,
mai mult decât itemi individuali de date. Toți operatorii de set au aceeași precedență .
1.1.4.3. Operatorii aritmetici
Un oper ator aritmetic pote fi folosit î ntr-o expresie pentru a nega, adăuga, scă dea,
multiplica ș i diviza va lori numerice. Rezultatul operaț iei est e de asemenea o val oare
numerică .
Oper
ator Scop Exemplu
+, – Când aceștia exprimă o expresie pozitivă
sau negativă ,sunt operatori unari SELECT * FROM comenzi
WHERE cantitate= -1;
SELECT * FROM angajat i
WHERE –salariu<0;
Când adună sau scad, sunt operatori binar i SELECT da ta_ang
FROM angajat i
WHERE SYSDATE –
data_ang>365
*, / Multiplic ă sau divizează, sunt operatori
binar i UPDATE angaja ti
SET salariu=salariu*1.1;
Tabelul 1. 2. Operatori aritmetici

10

Observaț ie: nu trebuie folo site două semne minus (–) în expresiile ar itmet ice
pentru a indica o negație dublă sau scă derea unei valori negative. Caracterele (–) sunt
folosite pentru a începe comentariile în propozițiile SQL. Î n alte cazuri, ac estea ar
trebui separate de spaț iu sau o paranteză .
1.1.4.4. Operatorul de concatenare
Operato rul de concatenare manipuleaz ă șirurile de caractere și datele de tip CLOB.
Tabelul 1 .3. Operatorul de concatenare
Rezultatul co ncaten ării a două șiruri de caractere este tot un ș ir de caractere. Dacă
ambele ș iruri de caractere sunt de tipul CHAR, rez ultatul are tipul de date CHAR ș i este
limitat la 2000 de caractere . Dacă unul dintre argumente este de tipul CLOB , rezultatul
este u n CLOB temporar. Locurile spațiilor goale sunt pă strate de concatenare,
indiferent de tipurile de date ale ș irurilor sau CLOB.
Pe cele mai multe platforme, operatorul de conc atenare este reprezentat ca două
bare verticale, așa cum este ară tat în tabelul de mai sus. Totuș i, unele platfor me IBM
folosesc bare verticale î ntrerupte pentru acest operator. Atunci câ nd se t ransferă scriptul
SQL între sisteme avâ nd seturi de caractere diferite, cum ar fi între ASCII și EBCD IC,
barele verticale ar putea să nu fie tra nsferate în bara verticală cerută de că tre mediul
MySQL. MySQL asigură funcția CONCAT pentru caractere ca ș i o alternativă la
operatorul format din b are verticale, pentru cazurile î n care este dificil sau imposibil să
se controleze translația efectuată de către siste mele de operare sau uneltele rețelei. Este
recomandată utilizarea acestei funcții în aplicaț iile ca re vor fi mutate î ntre medii cu
seturi de caractere diferite.
Pentru a concatena o expresie care ar putea fi NULL, se folosește funcț ia
IFNULL() pentru a conve rti expresia într -o valoare dorită .

1.1.4.5. Operatori de set
Operatorii de set combină rezultatele a două interogă ri component e într-un singur
rezultat. I nterogările care conț in oper atori set sunt denumite interogă ri compuse.

Operato
rul Returneaz ă
UNION Toate râ ndurile sele ctate de oricare dintre interogă ri
UNION
ALL Toate râ ndurile sele ctate de oricare dintre interogă ri, incluz ând
rândurile duplicate
Tabelul 1.4. Operatorii de set UNION și UNION ALL Ope
rator Scop Exemplu
|| Concatenează șiruri de
caracter e
și date de tip CLOB SELECT ‘Numele este ‘ ||
nume_ang
FROM angajaț i;

11

Mai multe interogă ri pot fi combinate utili zând un set de operator i: UNION,
UNION ALL. Toți operatorii din acest set au acceași precedență. Dacă o propoziție
SQL conț ine mai mul ți operator i din acest set, atunci MySQL îi evaluează începând din
partea stângă că tre partea dreaptă în cazul în care nic i o paranteză nu specifică o altă
ordine.
Expresiile corespunzătoare din lista de selecție a interogă rilor componente ale unei
interogări compuse trebuie să se potrivească în ceea ce privește numă rul și tipul de date.
Dacă interogările componente selecteaz ă date de tip caracter, atunci tipul de date al
valorilor returnate este determinat după cum urmează :
 dacă ambele interogări selectează valori de tipul CHAR, atunci valorile
returnate sunt de tipul CHAR
 dacă una sau amb ele interogări selectează valori de t ipul VARCHAR ,
atunci valorile returnate sun t de tipul VARCHAR

1.1.5. Expresiile SQL
O expresie este o combina ție de una s au mai multe valori, operatori și funcții SQL
care rezultă î ntr-o valoare. O expresie ia de obicei tipul de date al componentelor sale.
Această expresie se evaluează ca fiind 36 ș i are tipul de date NUMBER(același tip
de date ca ș i componentele sale): 6*6.
Urmă toarea expresie este un exemplu de expresie complexă care utilizează atât
funcții cât ș i operatori. Expresia adaugă 10 zile la data cu rentă, î nlătură componenta de
timp din sumă, și converteș te rezultatul la tipul de date CHAR:
TO_CHAR(TRUNC(SYSDATE+10))
Această expresie poate fi folosită î n
 lista de selecție a unei propoziț ii SELECT
 o condiț ie a unei clauze WHERE sau HAVING
 în clauzele CONNECT BY, START WITH ș i ORDER BY
 clauza VALUES a propoziț iei INSERT
 clauza SET a propoziț iei UPDATE
Spre exemp lu, se poate folosi o expresie în locul ș irului citat ‘M aris’ în clauza SET
a urmă toarei propozi ții UPDATE:
SET nume = ‘Maris’;
Această clauză SET are expresia INITCAP(nume) î n loc de ș irul citat ‘Maris’:
SET nume = INITCAP(nume);
Expresiile au mai multe forme, aș a cum este demonstrat în următoarea sintaxă :

12
expresie::=

Figura 1 .5. Tipuri de expresii
În cele ce u rmează , lucrarea prezintă câ teva dintre tipurile de expresii ce vor fi
folosite și î n elaborarea aplicaț iei propuse.
1.1.5.1. Expresii simple
O expresie simplă specifică o coloană, pseudocoloană, constante, număr de
secvență sau NULL:
expresie_simplă ::=

Figura 1 .6. Expresie simplă Expresii simple
Expresii compuse
Expresii cursor
Expresii funcție
Expresii subinterogări
scalare

13

Pe lângă schema unui utilizator, schema poate fi de asemenea “PUBLIC”
(ghilimele sunt necesare), caz în care trebuie să califice un sinonim public pentru o
tabel ă, vedere sau vedere materializat ă. Calificarea unui sinonim p ublic cu “PUB LIC”
este suportată numai î n limbajul de manipulare a datelor(D ML), nu și î n limbajul de
definire a datelor(DDL).
Pseudocoloana poate fi LEVEL, ROWID sau ROWNUM. O pseudocoloană poate
fi folosit ă numai cu o coloană, ș i nu cu o vedere sau vedere materializa tă. NCHAR ș i
NVARCHAR2 nu sunt tipuri valide de pseudocoloane.
Câteva expresii simple valide sunt:
angaja ti.nume
‘acesta este un sir de caractere’
10
1.1.5.2. Expresii cursor
Cursorii sunt suportați în interiorul procedurilor stored sau al funcțiilor și trigger –
elor. Sintaxa în MySQL este la fel ca în SQL embedded. Cursorii au următoarele
proprietăți:
– Asenzitivi: serverul poate sau un să facă o copie a tabelului rezultat
– Sunt read -only: nu pot fi actualizați
– Nu sunt derulabili: pot fi traversați într -o singu ra direcție și nu putem sări peste
rânduri
Cursorii trebuie să fie declarați înainte de a declara handlere. Variabilele și
condițiile trebuie declarate înainte de declararea cursorilor sau handlerelor:
1.1.5.3. Expresii funcț ie
O fun cție creată de SQL sau definită de utilizator poate fi folosită ca ș i expresie.
Câteva dintre expresiile funcț ie SQL sunt:
LENGTH(‘Maris’)
ROUND(12.345*23)
SYSDATE
O expresie funcție definită de utilizator specifică un apel la:
 O funcție î ntr-un pachet oferit de MySQL
 O funcție î ntr-un p achet, tip sau funcț ie independe ntă definite de
utilizator
 O funcț ie sau operator definite de utilizator
Câteva expresii funcții valide definite de utilizator sunt:
arie_cerc(radius)
Fct(DISTINCT coloana)
1.1.5.4. Expresii subinterogă ri scalare
O expresie subintero gare scalară este o subinterogare ce returnează exact o valoare
dintr -o coloană dintr -un rând. Valoarea expresiei subinterogare scalară este valoarea

14
itemului din lista de se lecție a subinterogă rii. Dacă subinterogarea nu returnează nici un
rând, atunci va loarea expresiei subinterogare scalară este NULL..
O expresie subinterogare scalară se poate fol osi î n majo ritatea sintaxelor care
apelează o expresie( expr). Totuși, subinterogă rile scalare nu sunt expresii valide în
urmă toarele locuri:
 Ca și valori implic ite pentru coloane
 În clauza RETURNING a propoziț iilor DML
 Ca și bază a unui index bazat pe o funcț ie
 În constrâ ngerile CHECK
 În clauzele GROUP BY ș i HAVING
 În clauzele START WITH ș i CONNECT BY

1.1.5.5. Expresii regulare
O expresie regulară este o metoda puternică de a specifica un șablon pentru o
căutare complexă. MySQL folosește implementarea lui Henry Spencer a expesiilor
regulare. MySQL utilizează versiunea extinsă pentru a suporta operațiile de potrivire la
șablon cu ajutorul operatorului REGEXP în propozițiil e SQL.
O expresie regulară descrie un set de șiruri de caractere. Cea mai simplă expresie
regulară este una care nu conține caractere speciale. De exemplu, expresia regulară
hello se potrivește numai la hello și la nimic altceva.
Expresiile regulare netriv iale utilizează anumite construcții speciale astfel încât să
se potrivească mai mult de unui singur șir de caractere. De exemplu, expresia regulară
hello|world se potrivește fie șirului de caractere hello fie șirului de caractere world.
O expresie regular ă pentru operatorul REGEXP poate folosi oricare dintre
următoarele caractere speciale și constructori:
^ – potrivește începutul șirului de caractere
$ – potrivește sfârșitul șirului de caractere
. – potrivește orice caracter, incluzând caracterul linie nou ă
a* – potrivește orice secvență de zero sau mai multe caractere a
a+ – potrivește orice secvență de unul sau mai multe caractere a
a? – potrivește zero sau un caracter a
de|abc – potrivește fie secvența de, fie secvența abc
(abc)* – potrivește una sau mai multe apariții ale secvenței abc
1.1.5.6. Liste de expresii
O listă de expresii este o combinaț ie de alte expresii.

lista_de_expresii::=

15

Figura 1.7 Listă de expresii
Listele de expresii pot apărea în condiț iile de comparație și de apartenență și în
clauzele GROUP BY ale interogărilor și subinterogă rilor.
Condițiile de comparație și apartenență apar în condiț iile clauzei WHERE. Ele pot
conține fie una, fie mai multe expresii delimitate prin virgulă , unul sau mai multe seturi
de expresii unde fiecare set conț ine una sau mai mult e expresii delimitate de virgulă. În
acest ultim caz (seturi multiple de expresii):
 Fiecare set este delimitat de paranteze
 Fiecare set trebuie să conțină același numă r de expresii
 Num ărul de exp resii din fiecare set trebuie să fie potr ivit cu numă rul de
expresii d inaintea operatorului din condiția de comparaț ie sau dinaintea
cuvâ ntului cheie IN din condiția de apartenență
O lista de expresii delimitată prin virgula nu poate conț ine mai mult de 1000 de
expresii. O listă de seturi de expresii delimitate prin virgulă poate conține orice număr
de seturi, dar fiecare set în parte nu poate conț ine mai mult de 1000 de expresii.
Urmă toarele expresii sunt liste de expresii valide în condiț ii:
(10, 20, 40)
(‘Maris’, ‘Diana’, ‘Ramona’)
((‘Maris’, ‘ Popescu’, ‘Ionescu’), (‘Dorin’, ‘Mihai’, ‘Bogdan’))

Într-o clauză GROUP BY simplă , se poate f olosi fie forma cea mai ridicată fie cea
mai sc ăzută a listei de expresii:
SELECT id_dept, MIN(salariu), MAX(salariu)
FROM angajati
GROUP BY id_dept, salariu;
SELECT id_dept, MIN(salariu), MAX(salariu)
FROM angajati
GROUP BY(id_dept, salariu);

1.1.6. Condiț iile SQL
În SQL, condiț iile pot avea mai multe forme, aș a cum este demonstrat în schema
de mai jos .
În această secțiune vor fi prezentate condițiile utilizate în dezv oltarea aplicației ce
reprezintă partea practică a lucrării de față.

16
O condiție poate fi folosită în clauza WHERE a următoarelor propoziții:
 DELETE
 SELECT
 UPDATE
O condiție poate fi folosită în oricare dintre următoarele clauze ale propoziției
SELECT:
 WHER E
 START WITH
 CONNECT BY
 HAVING
condiț ii::=

Figura 1 . 8 Condiții SQL

Următoarele condiț ii mai complexe adaugă valoarea salariu la valoarea
coloanei(s ubstituind NULL cu valoarea 0) și determină dacă suma este mai mare decât
numă rul constant 7000:
IFNULL(s alariu, 0)+ IFNULL (salariu+(salariu*pct_comision,0)>7000)

17

Condi țiile log ice pot combina mai multe condiții î ntr-una singur ă.
1.1.6.1. Precedența condiț iilor
Precedenț a este ordinea în care MySQL evaluează diferite condiții în aceeaș i
expresie. Atunc i când evaluea ză o expresie ce conține mai multe c ondiții, MySQL
evaluează condiț iile cu precedență mai mare î nainte de a le evalua pe cele cu
precedență mai mică, iar pe cele cu aceeași precedență le evaluează de la stânga la
dreapta î n interiorul unei e xpresii. MySQL evaluează operatorii î nainte a condițiilor.
Următorul tabel prezintă condițiile în ordinea precedenț ei lor.

Tipul de Condiț ie Scopul
=, !=, <, >, <=, >= Comparaț ie
IS [NOT] NULL, LIKE, [NOT]
BETWEEN
[NOT] IN, EXISTS, IS OF tip Comparaț ie
NOT Negare logi că
AND Conjuncț ie
OR Disjuncț ie
Tabelul 1.9 Condiții SQL
1.1.6.2. Condițiile de comparaț ie
Condi țiile de comparație compară o expresie cu alta. R ezultatul unei asemenea
comparaț ii poate fi TRUE, FALSE sau UNKNOWN.
Observaț ie: Obiectele m ari (LOB) nu sunt suport ate de că tre condițiile de
comparați e. Totuși, se pot folosi progra me PL/SQL pentru a compara datele CLOB.
Următorul tabel listează condițiile de comparați e și scopul lor, precum și câ teva
exemple semnificative:

Condiț ia Scopul Exemplu
= Testul de egalit ate SELECT * FROM
angajati
WHERE
salariu=500;
!=
<>
Testul de inegalitate. Unele forme ale condi ției pot fi
indisponibile pe unele platforme SELECT * FROM
angajati
WHERE
salariu!=500;
<
> Testul de “mai mic” ș i “mai mare” SELECT * FROM
angajati
WHERE
salariu>500;
SELECT * FROM

18
angajati
WHERE
salariu<500;
<=
>= Testul de “mai mic sau egal cu” ș i “mai mare sau
egal cu” SELECT * FROM
angajati
WHERE
salariu<=500;
SELECT * FROM
angajati
WHERE
salariu>=500;
ANY

SOME Compară o valoare cu fiecare valoare dintr-o listă
sau returnată de că tre o interogare.
Trebuie să fie precedată de că tre =, !=, <, >, <=, >=
Retur nează FALSE dacă interogarea nu returnează
nici un râ nd. SELECT * FROM
angajati
WHERE
salariu=ANY
(SELECT salariu
FROM angajati
WHERE
id_dept=30);
ALL Compară o valoare cu fiecare valoare dintr -o
listă sau returnată de că tre o interogare.
Trebuie să fie precedată de că tre =, !=, <, >, <=,
>=
Returnează TRUE dacă interogarea nu
returnează nici un râ nd. SELECT * FROM
angajati
WHERE salariu>=
ALL(1400, 3000)
Tabelul 1 .10. Condițiile de comparație
1.1.6.3. Condi ții de comparaț ie simple
O condi ție de comparație simplă specifică o comparaț ie cu expresii sau re zultate de
subinterogă ri.
condiț ie_de_compara ție_simplă ::=

Figura 1 .11. Condiția de comparație simplă

19
Mai există și un al doile a tip de condiții de comparație, condițiile de comparație
grup care specifică o compara ție cu oricare sau toți membrii într -o listă sau
subinterogare.
1.1.6.4. Condiț ii logice
O condiție logică combină rezultatele a doua condiț ii componente p entru a produce
un singur rezultat bazat pe acestea sau pentru a invers a rezultatul unei singure condiț ii.
Tabelul de mai jos listează condiț iile logice:

Con
diție Operaț ie Exemple
NOT Returnează TRUE dacă acea condiție ce îi
urmează returnează FALSE. Re turnează FALSE
dacă aceasta este TRUE. Dacă este
UNKNOWN, atunci rămâ ne UNKNOWN. SELECT *
FROM angajati
WHERE NOT
(functie IS NULL);
SELECT *
FROM angajati
WHERE NOT (salariu
BETWEEN 100 AND
200);
AND Returneaz ă TRUE dacă ambele
componente ale condiț iei sunt TRUE.
Returnează FALSE dacă una dintre e le este
FALSE. Altfel returnează UNKNOWN. SELECT *
FROM angajati
WHERE
functie=’manager’ AND
id_dept=30;
OR Returnează TRUE dac ă una dintre
componentele condiț iei este TRUE. Returnează
FALSE dacă ambe le sunt FALSE. Altfel
returnează UNKNOWN. SELECT *
FROM angajati
WHERE
functie=’manager’ AND
id_dept=10;
Tabelul 1 .12. Condiții logice
Urmă torul tabel arat ă rezultatele aplicării condiț iei NOT unei expresii:
– TRUE FALSE UNKNOWN
NOT FALSE TRUE UNKNOWN
Tabelu l 1.13 Condiția NOT
În cele ce urmează este prezentat un tabel care arată rezultatele combinării
condiției AND cu două expresii:
AND TRUE FALSE UNKNOWN
TRUE TRUE FALSE UNKNOWN
FALSE FALSE FALSE FALSE
UNKNOWN UNKNOWN FALSE UNKNOWN
Tabelul 1.13. Condiția AND

20

Tabelul de mai jos arat ă aplicarea condiției OR la două expresii:
OR TRUE FALSE UNKN
OWN
TRUE TRUE TRUE TRUE
FALSE TRUE FALSE UNKNOWN
UNKN
OWN TRUE UNKNOWN UNKNOWN
Tabelul 1 .14. Condiția OR
1.1.6.5. Condiț ii de apartenență
O condiție de apartenență testeaz ă apartenența la o listă sau la o subinterogare.
condiție_apartenență ::=

Figura 1. 15. Condiția de apartenență
Următorul tabel prezintă lista condițiilor de apartenență :

Con
diție Operaț ie Exemplu
IN Testul “egal cu orice membru”
Echivalent cu “ = ANY” SELECT * FROM angajati
WHERE functie IN
(‘manager’, ‘asistent’);
SELECT * FROM angajati
WHERE salariu IN
(SELECT salariu
FROM angajati
WHERE id_dept=30);
NOT IN Echivalent cu “ != ALL”
Returnează FALSE dacă unul dintre
membrii setului este NULL. SELECT * F ROM angajati
WHERE salariu NOT IN
(SELECT salariu
FROM angajati
WHERE id_dept=30);
SELECT * FROM angajati
WHERE functie NOT IN
(‘manager’, ‘asistent’);
Tabelul 1 .16. Condiții de apartenență

21

Dacă orice item din lista următoare unei operaț ii NOT IN este e valuat ca fiind
NULL, atunci toate r ândurile sunt evalua te ca fiind FALSE sau UNKNOWN, ș i nici un
rând nu este returnat.
1.1.6.6. Condiții de î ntindere
O condiție de întindere testează includerea într-un anumit interval.
condiție_de_î ntindere::=

Figura 1.16. Condiția de întindere
Următorul tabel listează condițiile de î ntindere:
Condiț ie Operaț ie Exemplu
[NOT] BETWEEN x
AND y [Nu] este mai mare sau
egal
decât x și mai mic sau
egal cu y SELECT * FROM
angajati
WHERE salariu
BETWEEN 500 AND
1000;
Tabelul 1 .17. Condiția de întindere
1.1.6.7. Condiț ii de NULL
O condi ție de NULL testează valorile NULL.

condiț ie_de_NULL::=

Figura 1.18. Condiția de NULL
Condițiile de NULL sunt listate î n tabelul de mai jos:
Condiț
ie Operaț ie Exemplu
IS[NOT]
NULL Testează valorile NULL. Aceasta este singura
operație recomandată pentru testarea valorilor
NULL. SELECT nume
FROM angajati
WHERE
pct_comision
IS NULL ;
Tabelul 1 .19. Condițiile de NULL

22
1.1.6.8. Condiț ii EXISTS
O condiție EXISTS testează existenț a rândurilor într-o subinterogare.
condiț ie_EXISTS::=

Figura 1.20. Condiția EXISTS

În următorul tabel sunt afișate condiț iile EXISTS:
Condiț ie Operaț ie Exemplu
EXISTS TRUE dacă o
subinterogare
returnează cel puțin un
rând SELECT id_dept
FROM departamente d
WHERE EXISTS
(SELECT * FROM
angajati a
WHERE d.id_dept=e.id_dept);
Tabelul 1.21. Condiția EXISTS
1.1.6.9. Condiț ii LIKE
Condițiile LIKE specifică un test ce implică potrivirea la un ș ablon. În timp ce
operatorul de egalitate (=) potriveș te exact valoarea unui car acter la valoarea altuia,
condițiile LI KE verifică potrivirea unei porț iuni din v aloarea unui caracter la alta
căutând prima valoare pentru ș ablonul specificat de c ătre a doua. LIKE calcule ază șiruri
folosind caractere așa cum sunt definite de că tre setul de caractere inserat.

condiț ie_LIKE::=

Figura 1 .22. Condiția LIKE

Cu ajutorul condiț iilor LIKE, se poate compara o valoare cu un șablon mai degrabă
decât cu o constantă . Șablonul trebuie să apară după cuvâ ntul cheie LI KE. De exemplu,
putem scrie urmă toarea interogare pe ntru a găsi salariile tuturor angajaților al căror
nume î ncepe cu litera “M”:
SELECT salariu FROM angajati
WHERE nume LIKE ‘M%’;

23
1.1.6.10. Condiț ii compuse
O condiț ie compus ă specifică o combinație de mai multe condiț ii.
condiție_compusă ::=

Figura 1.24. Condiția compusă
1.1.7. Funcț ii SQL
Funcțiile sunt asemănătoare cu ope ratorii în sensul că manipulează itemi de date și
returnează un rezultat. Funcțiile diferă de operatori î n formatul argumentelor lor. Acest
format le permite să opereze cu zero, unul, două sau mai multe argumente.
funcț ie(ar gument1, argument2,…)
Există atât funcții SQL cât și funcț ii definite de utilizator:
Funcț iile SQL sunt construite în MySQL și sunt disponibile pentru utilizarea î n
divers e propoziț ii SQL potrivite. Funcț iile SQ L nu trebuie confundate cu funcțiile
utilizat or scrise î n PL/SQL.
Dacă o funcție SQL este apelată cu un arg ument de un alt tip de date decât acela
așteptat de funcția SQL, atunci MySQL converteș te implicit argumentu l la tipul de date
așteptat înainte de a aplica funcț ia SQL. Dacă o funcție SQL este a pelată cu un
argument NULL, atunci această funcție returnează automat NULL .
1.1.7.1. Funcțiile șir de caracter
Printre cele mai utilizare funcții din această categorie se numără:
 CHAR() – returnează caracterul pentru fiecare întreg transformat
 CHARACTER_LENGTH() – returnează lungimea unui șir de caractere
 CONCAT() – folosit pentru concatenarea șirurilor de caractere
 LCASE() – sinonimul pentru LOWER(), returnează șirul de caractere scris cu
litere mici
 NOT LIKE – reprezintă negarea apartenenței la un șablon
 REGEXP – potrivirea la șablon folosind expresii regulate
 SPACE() – returneaza un șir de caractere din atâtea spații câte sunt specificate
 SUBSTR() – returneaza subistringul precizat
 UPPER() – returnează șirul scris cu caractere mari
Funcțiile cu valori șiruri de ca ractere returnează NULL dacă lungimea rezultatului
va fi mai mare decât valoarea sistem max_allowed_packet .
1.1.7.2. Funcțiile matematice
Toate funcțiile matematice returnează NULL în cazul apariției unei erori.

24
Printre cele mai utilizate funcții matematice se numa ră:
 ABS(x) – returneaza valoarea absolută a lui x. Este o funcție care permite
manevrarea datelor de tip BIGINT.
 ACOS(x) – returneaza arccos pentru valoarea lui x. Returnează NULL dacă x
nu se află în intervalul [ -1, 1]. ASIN(x) are aceeași proprietate, da r returneaza
arcsin pentru valoarea lui x .
 CEILING(x) – returnează cea mai mică valoare întreagă mai mare decât x
 CONV(N, a, b) – convertește numerele dintr -o bază numerică în alta.
 CONV() funcționează într -o precizie de 64 -biți.
 EXP(x) – returnează valo area lui e(baza algoritmilor naturali), ridicată la
puterea x. Inversul acestei funcții este funcția LOG(x) .
 FLOOR(x) – returnează cea mai mare valoare întreagă mai mică decât x .
 POW(x,y) – returnează valoarea numărului x, ridicat la puterea y.
 ROUND(x,D) – rotunjește valoarea lui x, la D zecimale.
 SIGN(x) – returnează semnul lui x.
 SQRT(x) – returnează radical din x, dacă x este un număr nenegativ.
1.1.7.3. Funcții dată și timp
Următorul exemplu prezintă funcții de tip date. Următoarea interogare selectează
toate r ândurile dintr -o valoare date_col din ultimele 30 de zile:
SELECT ceva FROM nume_tabelă
WHERE DATE_SUB(CURDATE(), INTERVAL 30 DAY)<=date_col;
Putem observa că interogarea selectează de asemenea date care sunt din viitor.
Funcțiile care așteaptă valori dat e, acceptă de obicei valori datetime și ignoră
partea legată de timp. Funcțiile care așteaptă valori timp acceptă de obicei valori
datetime și ignoră partea legată de dată.
Funcțiile care returnează data curentă sau momentul curent sunt evaluate o singură
dată per interogare și anume la începutul execuției interogării. Acest lucru înseamnă că
mai multe referințe la aceeași funcție, cum ar fi NOW(), într -o singură interogare
produc mereu același rezultat. Acest principiu se aplică și la funcțiile CURDATE(),
CURTIME(), UTC DATE(), UTC TIME(), UTC TIMESTAMP() și la oricare dintre
sinonimele lor.
Începând cu MySQL 3.23, aritmetica asupra datelor poate fi realizată utilizând
INTERVAL împreuna cu operatorul + sau -.
date + INTERVAL expr unit
date – INTERVAL expr unit
INTERVAL expr unit este permis de orice parte a operatorului + dacă expresia din
cealaltă parte este o expresie date sau datetime. Pentru operatorul -, INTERVAL expr
unit este permis numai de partea dreaptă, deoarece nu are sens să extragem o valoare
date sau datetime dintr -un interval.
Deoarece expr este tratată ca un șir de caractere, trebuie să avem grijă când
specificăm o valoare non -șir de caractere pentru INTERVAL.
mysql> SELECT 6/4;
-> 1.50

25
mysql> SELECT DATE_ADD('1999 -01-01', INTERVAL 6 /4
HOUR_MINUTE);
-> '1999 -01-01 01:50:00'
Daca adăugăm sau extragem dintr -o valoare date ceva ce conține o parte timp,
rezultatul va fi automat convertit la o valoare datetime:
mysql> SELECT DATE_ADD('1999 -01-01', INTERVAL 1 DAY);
-> '1999 -01-02'
mysql> SELECT DATE_ADD('1999 -01-01', INTERVAL 1 HOUR);
-> '1999 -01-01 01:00:00'
Dacă adăgăm MONTH, YEAR_MONTH sau YEAR iar data rezultată conține o zi
care este mai mare decât numărul de zile maxim pentru luna respectivă, ziua este
ajustată la num ărul maxim de zile al noii luni:
mysql> SELECT DATE_ADD('1998 -01-30', INTERVAL 1 MONTH);
-> '1998 -02-28'
1.1.7.4. Funcții de căutare full -text
Începând cu MySQL 3.23.23, MySQL are suport pentru indexarea și căutarea
full-text. Un index full -text în MySQL este un index de tipul FULLTEXT. Indecșii full –
text pot fi folosiți numai cu tabele MyISAM, și nu pot fi creați decât pentru coloane
CHAR, VARCHAR sau TEXT. Definirea unui index FULLTEXT poate fi dată în
propoziția CREATE TABLE când este creată o tabelă, sau adăug ată mai târziu folosind
ALTER TABLE sau CREATE INDEX
1.1.8. Tipul de calendar folosit de MySQL
MySQL utilizează ceea ce este numit calendarul Gegorian proleptic.
Fiecare țară care a schimbat din calendarul Julian în calendarul Greogorian a
trebuit să piardă cel p uțin 10 zile în timpul schimbării. Pentru a vedea cum
funcționează, considerăm luna Octombrie din 1582, când prima schimbare de la Julian
la Gregorian a avut loc:
Luni Marți Miercuri Joi Vineri Sâmbătă Duminică
1 2 3 4 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31
Tabelul 1.24. Schimbarea Julian -Gregorian

Nu există date între 4 Octombrie și 15 Octombrie. Această discontinuitate este
denumită « the cutover ». Orice date înainte de acest cutover sunt în sistemul Julian, și
orice date după cutover su nt Gregoriene. Datele din timpul unui cutover sunt
inexistente.
Un calendar aplicat datelor când nu era de fapt în utilizare se numește proleptic.
Așadar, dacă presupunem că nu a existat niciodată un cutover și regulile Gregoriene au

26
guvernat întotdeauna, avem un calendar Gregorian proleptic. Acest calendar este
utilizat de MySQL, și este cerut de standardul SQL.
1.1.9. Clauze SQL Data Definition Language – definirea
tabelelor ș i constrâ ngeri
1.1.9.1. Definirea tabelelor
Comanda SQL pentru crearea unei tabele goale are ur mătoarea formă :
CREATE TABLE <tabela> (
<coloana 1> <tip de date> [NOT NULL] [UNIQUE][<constrâ ngere pentru
coloană ],
…………………………………………………………………………….
<coloana n> <tip de date> [NOT NULL] [UNIQUE][<constr ângere pentru tabelă ],
[<constrâ ngere pentru tabelă ]
);
Pentru fiecare coloană, trebuie specificat un nume ș i un tip de date , iar numele
coloanei trebuie să fie unic î n interiorul definiț iei tabelei.
1.1.9.2. Definirea constr ângerilor
Pentru a defini o constrângere de integritate, adică o regulă care restricționează
valorile dint r-o bază de date se folosesc anumite constr ângeri SQL. MySQL permite
crearea câtorva tipuri de constr ângeri:
 O constrâ ngere NOT NULL interzice ca o valoare din baza de date să fie NULL
 O constrâ ngere UNIQUE interzice ca mai multe rânduri să ai bă aceeaș i valoare
în aceeași coloană sau combinaț ie de coloane dar permite ca anumite valori să fie
NULL
 O constrângere de cheie primară combină c onstrângerile NOT NULL și
UNIQUE într-o singură declarație în scopul de a interzice ca mai multe rânduri să
aibă aceea și valoare în aceeași coloană sau combinație de coloane și nu permite
prezenț a valorii NULL
 O constr ângere de cheie străină (foreign key) ce re ca valorile dintr -o tabela să se
potrivească valorilor dintr -o altă tabelă
Din pu nct de ve dere sintactic , constrângerile pot fi definite în două modalităț i:
 Ca parte a definiț iei unei tabele. Aceasta este numită specificaț ia out-of-line.
 Ca parte a definiț iei unei coloane individuale sau atribut individual. Aceasta este
o specificaț ie inline.
O constrângere N OT NULL trebuie să fie declarată inline. Toate celelalte
constrâ ngeri pot fi definite fie inline, fie out -of-line.
Constrângerile se pot aplica în următoarele propoziț ii SQL: CREATE TABLE,
ALTER TABLE, CREATE VIEW, ALTER VIEW.
Const rângerile asupra vederil or pot fi forț ate prin constrângeri asupra tabelelor de
bază.

27
1.1.10. Interog ări și Subinterogă ri

Pentru a obține informațiile depozitate î n baza de date este folosit limbajul de
interogare SQL.
O interogare este o operație care primeș te date dintr -una sau mai m ulte tabele sau
vederi. O propozi ție SELECT de pe nivelul de sus este denumită interogare, și o
interogare inserată într -o altă propoziț ie SQL este denum ită sub-interogare. În această
secțiune su nt descrise tipurile de interogări și sub -interogări și felul în care trebuie
utilizate.
În SQL, o interogare are următoarea formă, simplificată (elementele cuprinse între
parantezele drepte sunt opț ionale):
select [distinct] <coloana 1>, <coloana 2>,…,<coloana n>
from <tabela>
[where <conditie>]
[order by <colo ana 1, coloana 2,…,coloana n[ asc|desc]>]
Coloanele care trebuie selectate dintr -o tabelă sunt specificate după cuvântul cheie
SELECT. Această operație este denumită și proiectare. De exemplu, interogarea:
SELECT * FROM angajati;
returnează toate tuplele cu toate coloanele din tabela angajati . În loc de un nume de
atribut, clauza SELECT poate să conțină de asemenea expresii aritmetice care implică
operatori aritmetici, etc.
1.1.10.1. Crearea interogă rilor simple
Lista de expresii care apare dupa cuvântul cheie SELECT și înainte de clauza
FROM s e numeș te listă select. În interiorul listei de selecție, se specifică una sau mai
multe coloane în set ul de rânduri pe care dorim ca interogarea să le returneze dintr -una
sau mai multe tabele sau vederi. Numărul de coloane, la fel ca și tipul de date pe care îl
conțin acestea ș i lungimea lor, sunt determinate de elementele listei select.
Dacă două sau mai multe tab ele au anumite nume de coloane î n comun, atunci
numele de coloane trebuie calificate cu numele de tabele. Altfel, nu mele de coloane
calificate total su nt opționale
Pentru a transmite instrucț iuni sau sugestii optimizatorului MySQL , se pot folosi
comentarii într -o propoziț ie SELECT. Optimizatorul foloseș te sugestiile pentru a alege
un plan de execuție al propoziț iei.

1.1.10.2. Sortarea rezultatelor interogă rilor
Pentru ordonarea rândurilor selectate de că tre o interogare se poate folosi clau za
ORDER BY. Sortarea dupa poziție este utilă în urmă toarele cazuri:
 Pentru a ordona după o expresie lista de selecție lungă, se poate specifi ca
poziț ia acesteia în loc de duplicarea întregii expresii, folosind clauza ORDER
BY;

28
 Pentru interogă ri compuse( care con țin operatorii UNION sau UNION
ALL), clauza ORDER BY trebuie să folosească poziții mai degrabă decâ t expresii
explicite.
1.1.10.3. Join
Un join este o interogare care combină rânduri din dou ă sau mai multe tabele sau
vederi. MySQL efectuează un join atunci câ nd mai multe tabele apar în clauza FROM a
interogă rii. Lista de selec ție a interogă rii poate selecta orice coloană din oricare dintre
aceste tabele. Dac ă oricare două dintre aceste tabele au un nume de coloan ă în comun,
atunci t rebuie calificate toate referinț ele la ace ste coloane de -a lungul interogă rii cu
numele tab elelor, pentru evitarea ambiguităț ii.
1.1.10.4. Utilizarea subinterogă rilor
O subinterog are răspunde la întrebă ri compuse din mai multe par ți. De exemplu,
pentru a determina cine lucrează î n departamentul lui Popescu , poate fi folosită mai
întâi o subinterogare pe ntru a determina departamentul în care lucrează Popescu. Se
poate apoi răspunde la întrebarea originală prin propoziția părinte SELECT. O
subinterogare în clauza FROM a unei propoziț ii SELECT este denumit ă și vedere
inline . O subinterogare în clauza WHERE a unei propoziț ii SELECT mai este denumit ă
și subinterogare nested.
O subinterog are poate conține o altă subinterogare. MySQL nu impune nici o
limit ă la numărul de nivele de subinterogări î n clauza FROM a in terogă rii de pe nivelul
cel mai de sus. Se pot încorpora până la 255 de nivele de su binterogări î n clauza
WHERE.
MySQL realizează o subinterogare corelată atunci c ând subinterogarea face
referință la o coloană a unei tabele referită în propoziția pă rinte. O subinterogare
corelată este evaluată o dată pentru fiecare r ând procesat de către propoziția pă rinte.
Propozi ția părinte poate fi o propoziț ie SELECT, UPDATE sau DELETE.
O subinterogare corelată răspunde la o întrebare complexă alcătuită din mai multe
părți al c ărei răspuns depinde de valoarea fiecă rui r ând procesat de către propoziția
părinte.

Folosirea subinterogă rilor este re comandată pentru urmă toarele scopuri:
 Pentru a defini un set de r ânduri care să fie inserate în tabela țintă a unei
propoziț ii de tip INSERT sau CREATE TABLE.
 Pentru a defini un set de r ânduri care s ă fie incluse într-o vedere print r-o
propoziț ie de tipul CREATE VIEW sau CREATE MATERIALIZED VIEW.
 Pentru a defini una sau mai multe valori care s ă fie asignate la r ânduri existente
printr -o propoziț ie UPDATE.
 Pentr u a asigura valori pentru condiț iile din clauza WHERE, clauza HAVING
sau c lauza START WITH din pro pozițiile SELECT, UPDATE ș i DELETE.
 Pentru a defini o tabelă care să fie operată de către o interogare conținută . Acest
lucru se face prin plasarea subinterogării în clauza FROM a interogării ce o conține
ca și când am pune un nume de tabelă.

29
1.1.11. Modificarea datelor în SQ L

După ce o tabelă a fost creată folosind comanda CREATE T ABLE, valorile pot fi
inserate î n tabelă , pot modificate sa u șters e.
1.1.11.1. Inseră ri
Cea mai ușoară cale de a insera o valoare într-o tabelă este utilizarea propoziț iei
INSERT:
INSERT [LOW_PR IORITY | DELAYED | HIGH_PRIORITY] [IGNORE]
[INTO] tbl_name [(col_name ,…)]
{VALUES | VALUE} ({ expr | DEFAULT},…),(…),…
[ ON DUPLICATE KEY UPDATE
col_name =expr
[, col_name =expr] … ]

O inserție nu trebuie neapă rat s ă urmeze ordinea atributelor așa cum este
specificată în propoziția CREATE TABLE. Dacă o coloană este omisă, valoarea NULL
este inserată în locul ei. Dacă nu este specificată nici o listă de coloane, trebuie dată o
valoare pentru fiecare col oană în ordinea în care este definită în propoz iția CREATE
STATEMENT.
1.1.11.2. Actualiză ri
Pentru a modifica valor ile atributelor pentru anumite înregistrări din tabele se
folosește propoziț ia UPDATE:

UPDATE [LOW_PRIORITY] [IGNORE] tbl_name
SET col_name1 =expr1 [, col_name2 =expr2 ] …
[WHERE where_condition ]
[ORDER BY …]
[LIMIT row_count ]
O expresie este fie o constantă (o nouă valoare), o operație aritmetică sau aplicată
unui ș ir, sau o interogare SQL. Trebuie neapărat ca noua valoare asignată unei coloane
să aibă tipul de date potrivit.
O propozi ție UPDATE f ără clauza WHERE generează schimbarea respectivelor
atribute ale tuturor înregistrărilor din tabelă, deși numai o parte din tabelă are nevoie de
actualizare.
Exemplu: Toti angajații care lucrează în vânză ri în departamentul 20 primesc
același salariu ca ș i managerul c u cel mai mic salariu dintre toț i managerii.
UPDATE angajati SET
salariu=(SELECT MIN(salariu) FROM angajati
WHERE functie=’manager’)
WHERE functie=’vazantor’ AND nr_dept=20;
Este de asemenea posibil s ă specifică m o interogare ce returneaz ă mai mult de o
singură valoare(dar totuș i o singur ă înregistrare!). În acest caz, clauza SET are forma:

30
SET(<coloana i,…,coloana j>) = <interogare>.
Este importan t ca ordinea tipurilor de date ș i a valorilor r ândului selectat să
corespundă exact la list a de coloane din clauza SET.
1.1.11.3. Ștergeri
Toate atributele selectate pot fi ștrese dintr -o tabelă utiliz ând comanda DELETE:

DELETE [LOW_PRIORITY] [QUICK] [IGNORE] FROM tbl_name
[WHERE where_condition ]
[ORDER BY …]
[LIMIT row_count ]
Dacă omitem clauz a WHERE, toate atributele sunt ș terse din tabel ă.
Pentru stergere aplicată mai multor tabele se folosește:
DELETE [LOW_PRIORITY] [QUICK] [IGNORE]
tbl_name [.*] [, tbl_name [.*]] …
FROM table_references
[WHERE where_condition ]
1.1.11.4. Commit ș i Rollback
O secven ță de modif icări ale bazei de date, de exemplu o inserare sau actualizare,
sau o propoziție DELETE se numeșt e tranzacț ie.
Atâta timp câ t utilizatorul nu a aplicat propoziția COMMIT, este posibilă anularea
tuturor modificărilor de după ultimul COMMIT. Pentru anularea modific ărilor, trebuie
aplicată propoziț ia ROLLBACK.
Este recomandat să î ncheiem fiecare modificare a bazei de date cu un
COMMIT(atâta timp cât modificarea are efectul așteptat).
1.1.12. Comentarii asupra tabelelor
1.1.12.1. Modificarea definițiilor tabelelor ș i coloanelo r
Este posibil să modific ăm structura unei tabele (schema de re lații) chiar dacă
rândurile au fost deja inserate în această tabelă . O coloană poate fi adaugată utilizâ nd
comanda ALTER TABLE:
ALTER TABLE <tabela>
ADD(<coloana> <tip de da te> [DEFAULT <valoar e>][<constrâ ngere pentru
coloană >]);
Dacă mai mult de o coloană trebuie adăugată la un anumit moment, cl auzele ADD
respective trebuie să fie separate de virgule. O constrâ ngere asupra tabelei poate fi
adăugată unei tabele folosind
ALTER TABLE <tabela> ADD (<constrangere pentru tabela>);
1.1.12.2. Ștergerea unei tabele
O tabelă și râ ndurile sale pot fi șterse prin aplicarea unei comenzi
DROP TABLE <tabela> [constr ângeri cascadă ];

31
1.1.13. Vederi
În Oracle, comanda SQL de creare a unei vederi( tabela virtuală ) are forma :
CREAT E
[OR REPLACE]
[ALGORITHM = {UNDEFINED | MERGE | TEMPTABLE}]
[DEFINER = { user | CURRENT_USER }]
[SQL SECURITY { DEFINER | INVOKER }]
VIEW view_name [(column_list )]
AS select_statement
[WITH [CASCADED | LOCAL] CHECK OPTION]
Clauza opțională OR REPLACE recr ează vederea dacă ea a existat î nainte.
<lista de coloane > numeș te coloanele vederii. Dacă <lista de coloane > nu este
specificată în definiț ia vederii, co loanele vederii vor primi același nume ca și atributele
listate în propoziț ia SELECT( dacă este posibi l).
O vedere este evaluată din nou de fiecare dată când este accesată . În My SQL nu
sunt permise modifică rile INSERT, UPDATE sau DELETE care folosesc una dintre
următoarele construcții în definiț ia vederii:
 Join
 Funcț ii agregat cum sunt SUM, MIN, MAX, etc.
 Subinterogă ri de tipul IN, ANY, ALL sau teste de existen ță(EXISTS)
 Clauza GROUP BY sau clauza DISTINCT
Vederea poate fi ștearsă utilizâ nd comanda DELETE <nume_vedere> ;.

32
Capitolul II. Integrarea SQL în limbajele de nivel înalt

SQL -ul embedded s -a născut din primele î ncercar i de a extinde SQL cu capabilităț i
ale limbajelor procedurale. Funcția sa de bază a fost să ducă mai departe controlul și
administrația internă a RDBMS. Cel de -al doilea scop a fost să asigure abilitatea de a
scrie pr ograme ce se pot conecta la ba za de date, pot primi, procesa ș i modifica date,
etc. SQL embedded este de fapt o metod ă de a combina puterea d e calcul a unui limbaj
de nivel înalt cum ar fi C/C++ ș i caracteristicile de manipulare a datelor pe care le are
SQL. El permite executarea oric ărei propoziții SQL dintr -un program aplicaț ie.
Prima ț intă pentru care a fost creat este delegată î n mod gradua l procedurilor
depozitate, funcțiilor, și trigger -elor care deț in mecanisme mai bune pentru a face acest
lucru. A l doilea scop este înca făcut î n mare parte utiliz ând diver se limbaje de
programare, totuș i, mecanismele bazelor de date evolueaz ă în mod constant. Cele mai
moder ne limbaje de programare asigură diferite (uneori mai eficiente ș i mai usor de
utilizat) mijlo ace de accesare a RDBMS. A cestea includ ODBC, JDBC, CLI, împreuna
cu interfeț ele orientate obiect (cum ar fi Microsoft ADO).
Timp de 50 de ani, programatorii au scris cod astfel încât noi tehnolo gii continuă să
iși facă loc, să se dezvolte și să se maturi zeze î ntr-o viteză uimitoare. În prezent există
mai mult de 2500 de limbaje de programare documentate!
Un limbaj de nivel î nalt este un limbaj de programare care, în comparaț ie cu
limbajele de programare de nivel j os, pot fi mai abstracte, mai ușor de util izat ș i mai
portabile peste platforme. Termenul de “limbaj înalt” nu implică neapărat că limbajul
este î ntotdeauna superior limbaje lor de nivel mai jos, de fapt, în termeni ai cunoștințelor
legate despre cum lucrează computerele c ărora le este cerut să pro ducă programe într –
un limbaj dat, propoziția inversă ar putea fi adevarată . “Limbaj de nivel înalt” se referă
mai mult la un nivel de abstractizare mai mare relativ la limbajul mașin a
Ca ș i stereotip, este co nsiderat că limbajele de nivel înalt fac progra marea
complexă să pară mai simpl ă, în timp de limbajele de nivel jos tind s ă produc ă un cod
mai eficient. Totu și, odat ă cu creșterea complexităț ii arhitecturilor microprocesoarelor
moderne, compilatoarele bine construite pentru limbajele de nivel înalt pro duc î n mod
frecvent cod ma i eficient, dec ât ar putea produce manual programatorii cu limbajele de
nivel jos.
Așa cum am precizat deja, SQL nu este un limbaj procedural. Procedurile
depozitate, funcț iile definite de utilizator, trigger -ele sun t depozitate î năuntrul RDBMS.
Această abordare, deși foarte populară până î n anii ’ 90, nu a fost prima î ncercare de a
da SQL -ului capacităț i de limbaj procedural. Ideea de SQL embedded s -a ridicat înainte
ca extensiile procedurale ale SQL să fie d ezvoltate. A fost intro dus de către IBM la
începu tul anilor 1980 ș i apoi implementat de mulți alț i vânzători de SQL. SQL -ul
dinamic a fost continuarea logică a principiilor SQL -ului embedded care au ridicat
anumite limit ări și inconveniențe ale acestuia din urmă .
Trebuie să ne întreb ăm care este mai ef icient, SQL -ul embedded sau dinamic? Cele
mai multe surse (cărți SQL, site -uri web, etc.) r ăspund acestei întrebă ri, făra a fi
ambiguë, în favoarea SQL -ului embedded. Motivul este simplu, în SQL -ul embedded,

33
primii patru pa și ai pr ocesării propoziț iilor SQL s unt efectuați în timpul compilării și nu
trebuie să fie repetaț i la rulare.
Cheia pentru a înț elege aceast ă problemă este reprezentat ă de Pasul 3, ș i anum e
pasul de optimizare al procesă rii SQL. Cele mai moderne RDBMS -uri au co mponente
built-in speciale de numite optimizatori care creează un plan de execuție pentru fiecare
propoziț ie SQL, baz ându-se pe informa ția din catalogul sistemului dinamic. Asta
înseamnă că planul de execuție pentru o propoziț ie SQL care a fost optim într-o zi poate
fi departe de optim după o lună, și chiar mai puțin după un an. Utilizarea celor doi pa și
dinamici SQL ar putea ajuta la îmbun ătățirea performanței ș i mai mult, adic ă am putea
să pregă tim (PREPARE) propozi țiile SQL o singur ă dată și apoi s ă le ex ecutăm
(EXECUTE) de c âte ori este nevoie în timpul rul ării programului.
Răspunsul final este că eficien ța SQL -ului embedded în faț a SQ L-ului dinamic
depinde de anumiț i factori, iar dezvoltatorii vor trebui s ă aleagă pentru fiecare caz
particular în parte.

2.1. Interfe țe de programare a aplica țiilor SQL

Înainte ca o singur ă propozi ție SQL să poată fi executat ă, o aplicaț ie client care se
potriveș te acestei propozi ții trebuie s ă stablieasc ă o conexiune cu RDBMS într-un fel
oarecare. Conexiunea poate fi stabilit ă printr-o varietate de mecanisme, începând cu
interfaț a de la nivelul de apel al proprietarului la “buzz -of-the-day” cum este cazul Java
Database Connectivity și .NET Providers.
Conceptele de interfață de programare a aplicaț iilor, deș i nu sunt în domeniu l SQL,
trebuie s ă fie in țelese de către oricine este dornic de a învăța ș i lucra cu RDBMS -uri și
SQL -ul lor nativ.
SQL -ul embedded și -a dobâ ndit numele datorit ă faptului c ă propoziț iile SQL erau
direct încorporate în programul limbajului gazdă . Înainte ca o aplicație care conț inea
SQL embedded s ă fie compilat ă și executat ă, trebuia s ă treac ă printr -un proces de
precompilare, utilizâ nd un precompilator oferit de alte companii.
Limbajul Modul se referă la modulele compilate depozitate pe server, utiliz ând C,
Cobol sau Java, la fel ca și limbajele proprietate a v ânzătorilor cum este PL/SQL oferit
de Oracle sau Microsoft/Sybase Transact -SQL.
Standardul interfeț ei de la nivelul ape l(CLI/SQL) permite o independență relativă
de o interfață la bază de date proprieta te a v ânzătorului, prin î ncapsularea tuturor
detaliilor specifice vânză torilor într-un num ăr de funcț ii uniforme cum ar fi
SQLAllocConnect() – care aloca resurse de conexiu ne, SQLConnect() – se conectează
la un anumit driver, SQLDescribeParam() – descrie un anumit parametru din
propoziț ie, etc.
2.1.1 Java Database Connectivity(JDBC)
JDBC a fost propusă ( și implementată) de că tre Sun Corporatio n pentru a asigura
limbajului să u de programar e foarte popular, Java, un set î ntreg de metode de a accesa
bazele de date. Utiliz ând JDBC se poate efectua conexiunea la o surs ă de date( care nu

34
trebuie s ă fie neap ărat o sursă de date RDBMS), s e pot executa interogă ri SQL( sunt
trimise mai departe sistemului ce procesează SQL , cum ar fi RDBMS, pentru execuție)
și se poate procesa rezultatul acestor interogă ri. Cel mai nou standar d JDBC este JDBC
v.3.0, inclus î n J2SE(Java 2 Standard Edition) și J2EE(Java 2 Enterprise Edition),
versiunea 1.4.
JDBC asigură două seturi de interfeț e : una pentru programatorii aplicației bază d e
date ș i una pentru programatorii driverelor bazei de date.
Funcționalitatea JDBC – de bază și extinsă – este conținută î n pach etul java.sql și
în pachetul javax.sql. În urmă torul tabel sunt listate aceste funcționalități ș i pachetul din
care provin:

Caracteristică Pachet Descriere
Manipulă ri mai bune
ale setului de rezul tate: set de
rezultate asupra că ruia se pot
efectua actu alizări și derulă ri java.sql Faciliteaz ă manipularea programatică a
setului de rezultate obț inut în urma aplicării
propoziț iilor S QL sau a procedurilor
depozitate.
Suportul unor noi tipuri
de date java.sql Abilitatea de a manipula pe partea de
server tipuri le de date structurate cum ar fi
CLOB ș i BLOB , făra a le transfera pe
aplicaț ia client.
Dozarea actualiz ărilor java.sql Abilita tea de a combina propoziții SQL
într-o singură doză , pentru a reduce traficul
în rețea ș i a controla excesele.
Suport tranzac țional java.sql Declară, efectuează roll back și commit
pentru tranzacții pe partea client, incluzâ nd
suport SAVEPOINT.
Suport JNDI (Java
Naming and Directory
Interface) javax.sql Facilitează desfașurarea aplicaț iilor Java
abstractiz ând driverul JDBC î n componente
gestionate independent.
Întrunirea conexiunilor javax.sql Menț ine un cache al conexiunii la baza de
date pentru o util izare ulterioară .
Suport pentru
tranzacț iile distribuite javax.sql Asigură suportul pentru procesarea
tranzacț iilor distribuite.
Java Beans javax.sql Încapsulează date și funcționalităț i.
Referinț e la Rowset -ul JDBC javax.sql Încapsulează un driver ca ș i componenta
Java Bean .
Tabelul 2.1 Caracteristicile JDBC

Primii pași
Pentru a seta un mediu de dezvoltare JDBC, trebuie urmaț i următorii pași:
1. Instalarea ultimei versiuni a platformei Java. Dacă nu avem deja o bază
de date, este recomandată instalarea u ltimei versiuni a NetBeans™ IDE si a

35
Sun Application Server, care vine odată cu Java DB. JDBC include pachetele
java.sql și javax.sql , care conțin interfețele și clasele necesare pentru
dezvoltarea aplicațiilor JDBC.

2. Instalarea unui driver pe computer. D acă NetBeans a fost instalat cu Sun
Application Server, atunci vom avea inclus driverul necesar.

Tipuri de drivere
Există mai multe implementări posibile ale driverelor JDBC. Aceste implementări
fac parte din următoarele categorii :
 Tipul 1 – drivere care implementează API JDBC ca și o mapare la o altă
API de acces la date, cum ar fi ODBC. Driverele de acest tip sunt dependente de
o librărie nativă în general, fapt care limitează portabilitatea lor. Puntea JDBC –
ODBC este un exemplu de driver de Tipul 1.
 Tipul 2 – drivere care sunt scrise parțial în limbajul de programare Java
și parțial în cod native. Aceste drivere folosesc o librărie client nativă specifică
sursei de date la care se conectează. Din nou, din cauza codului nativ,
portabilitatea lor este lim itată.
 Tipul 3 – drivere care folosesc client Java pur comunicând de asemenea
cu un server de mijloc utilizând un protocol independent de baza de date. Acest
server comunică apoi crererile clientului sursei de date.
 Tipul 4 – drivere care sunt Java pur și implementează protocolul de
rețea specific pentru o sursă de date. Clientul se conectează direct la sursa de
date.

3. Instalarea SGBD -ului(Sistemului de Gestiune a Bazelor de Date) dacă
este necesar

Setarea unei baze de date
Înainte de a scrie o aplicație J DBC, trebuie setată o bază de date denumită spre
exemplu Pauza_de_Cafea.
Să presupunem că exemplul nostru de bază de date este folosit de proprietarul unei
mici cafenele denumită “Pauza de Cafea”, unde boabele de cafea sunt vândute la
kilogram și cafeaua f iartă este vândută la cana. Pentru a păstra lucrurile simple, să
presupunem de asemenea că proprietarul are nevoie de doar două tabele, una pentru
tipurile de cafea și alta pentru furnizorii de cafea.
Pentru a depozita datele în baza de date, trebuie să cr eăm tabelele.
Odată ce baza de date și tabelele sunt create pentru depozitarea datelor, va trebui
deschisă o conexiune cu SGBD -ul nostru. Vom avea nevoie de asemenea de cod SQL și
să descoperim cât este de ușor să utilizăm JDBC pentru a transmite propoziți ile SQL
catre SGBD și apoi să procesăm rezultatele care sunt returnate.

Stabilirea unei conexiuni

36
Mai întâi va trebui stabili tă o conex iune cu SGBD pe care dorim să -l folosim. În
general, o aplicație JDBC se conectează la o sursă de date utilizând unul di ntre
următoarele două mecanisme:
 DriverManager : este o clasă implementată care cere unei aplicații să
încarce un driver specific, utilizând un URL hardcoded. Ca și parte a inițializării
sale, clasa DriverManager încearcă să încarce clasele driverului refer it în
proprietatea jdbc.drivers a sistemului. Acest lucru ne permite particularizarea
driverelor JDBC utilizate de aplicațiile nostre.
 DataSource : această interfață este preferată în locul DriverManager
deoarece permite detalii despre sursa de date de bază astfel încât să fie
transparentă pentru aplicația noastră. Proprietățile obiectelor DataSource sunt
setate astfel încât să aceasta să reprezinte o sursă de date particulară.
Stabilirea unei conexiuni implică doi pași: Încărcarea driverului și Efectuarea
conexiunii.

Încărcarea driverului
Încărcarea driverului pe care dorim să -l folosim este foarte simplă. Implică o
singură linie de cod în program. Pentru a utiliza driverul Java DB, trebuie scrisă
următoarea linie de cod:

Class.forName(“org.apache.derby.j dbc.EmbeddedDriver”);

Documentația referitoare la fiecare driver precizeaza numele clasei pe care să -l
folosim. În exemplul de mai sus, EmbeddedDriver este unul dintre driverele pentru
Java DB.
Apelul automat al Class.forName creează o instanță a unui dri ver și îl înregistrează
cu DriverManager pentru a nu fi nevoiți să creăm o instanță a clasei. Dacă ar trebui să
creăm propria instanță, am crea un duplicat inutil, dar acesta nu ar cauza nici un rău.
După încărcarea driverului, putem efectua o conexiune la SGBD(DBMS).

Efectuarea conexiunii
Al doilea pas este să conectăm driverul dorit la SGBD.

Prin utilizarea clasei DriverManager
Clasa DriverManager funcționează cu interfața Driver pentru a gestiona driverele
disponibile unui client JDBC. Atunci când un c lient cere o conexiune și oferă un URL.
DriverManager este responsabil cu găsirea unui driver care recunoaște URL -ul și cu
folosirea lui pentru conectarea la sursa de date corespunzătoare. URL -urile de conectare
au următoarea formă:

jdbc:derby:<NumeBD>[Li stă de proprietăți]

Porțiunea cu NumeBD a URL -ului indentifică o bază de date specifică. O bază de
date poate fi într -una din următoarele locații: în directorul curent de lucru, în classpath,

37
într-un fișier JAR, într -un director în care se află o anumită bază de date Java DB, sau
într-o locație absolută în sistemul nostru de fișiere.
Metoda getConnection stabilește o conexiune:

Connection conn = DriverManager.getConnection("jdbc:derby:CAFELE");

În loc de “LoginPersonal” trebuie inserat numele pe care î l folosim pentru a face
log in la SGBD, iar în loc de “ParolaMea” va trebui inserată parola pentru SGBD.
Așadar, dacă ne logăm la SGBD folosind numele “Diana” și parola “M4”, doar
următoarele două rânduri de cod vor stabili o conexiune la baza de date:

String url = "jdbc:derby:CAFELE";
Connection con = DriverManager.getConnection(url, "Diana", "M4”");

Dacă unul dintre driverele pe care le -am încărcat recunoaște URL -ul JDBC oferit
metodei DriverManager.getConnection, acel driver stabilește conexiunea la SG BD-ul
specificat în URL -ul JDBC. Clasa DriverManager, așa cum spune și numele ei,
gestionează toate detaliile stabilirii conexiunii în locul nostru, fără a ne implica în
detalii. În afara cazului în care scriem un driver, probabil nu vom folosi nici una di ntre
metodele interfeței Driver, și singura metodă DriverManager pe care trebuie să o
cunoaștem cu adevărat este DriverManager.getConnection .

MySQL Connector/J
MySQL asigură conectivitate pentru aplicațiile client dezvoltate în limbajul de
programare Java prin intermediul unui driver JDBC, denumit MySQL Connector/J.
MySQL Connector/J este un driver Java de Tipul 4. Sunt disponibile diferite
versiuni care sunt compatibile cu specificațiile JDBC -3.0 și JDBC -4.0. Faptul că este de
tipul 4 înseamnă că driveru l este o implementare Java pură a protocolului MySQL și nu
se bazează pe librăriile client MySQL.
În prezent sunt patru versiuni disponibile de MySQL Connector/J, dintre care cea
recomandată este Connector/J 5.1.

Stabilirea unei conexiuni folosind un dr iver MySQL
Folosirea diferitelor tipuri de drivere implică doar schimbarea numelui clasei ce
reprezintă driverul și a modalității de specificare a bazei de date.

String url = "jdbc:mysql://localhost/test" ;
// sau url = "jdbc:mysql://localhost/test?user=d uke&password=java";
try {
Class.forName("com.mysql.jdbc.Driver") ;
} catch(ClassNotFoundException e) {

O conexiune va fi folosită pentru:

38
 Crearea de secvențe SQL utilizate pentru interogarea sau actualizarea
bazei.
 Aflarea unor informații legate de ba za de date (meta -date).
De asemenea, clasa Connection asigură facilități pentru controlul tranzacțiilor din
memorie către baza de date prin metodele commit, rollback, setAutoCommit.
Închiderea unei conexiuni se realizează prin metoda close .

O dată facută conectarea cu metoda DriverManager.getConection, se poate folosi
obiectul Connection rezultat pentru a se crea obiecte de tip Statement,
PreparedStatement sau CallableStatement cu ajutorul cărora putem trimite secvențe
SQL către baza de date. Cele mai uzua le comenzi SQL sunt cele folosite pentru:
 Interogarea bazei de date: SELECT
 Actualizarea datelor: INSERT, UPDATE, DELETE
 Actualizarea structurii: CREATE, ALTER, DROP – acestea mai sunt
numite
instrucțiuni DDL (Data Definition Language)
 Apelarea unei proced uri stocate: CALL
După cum vom vedea, obținerea și prelucrarea rezultatelor unei interogări este
realizată prin intermediul obiectelor de tip ResultSet.

Crearea tabelelor
Pentru următoarele exemple, trebuie să creăm câteva tabele în baza noastră de date.
Prima tabelă, CAFELE , conține informații esențiale despre cafelele vândute la “ Pauza
de Cafea” , incluzând numele cafelei, prețurile, numărul de kilograme vândute în
săptămâna curentă și numărul de kilograme vândute în total până în present. Tabela
CAFELE, are urmâtoarea structură:

Nume_Cafea ID_Fur
nizor P
reț Vâ
nzări T
otal
Columbiană 110 5.69 0 0
Franceză 10 6.69 0 0
Espresso 150 10 0 0
Columbiană_decaf 110 7.89 0 0
Franceză_decaf 10 8.89 0 0
Coloana ce depozitează numele cafelei este Nume_Cafea și co nține valori de tipul
VARCHAR cu o lungime maximă de 32 de caractere. Din timp ce numele sunt diferite
pentru fiecare tip de cafea vândut, numele identifică în mod unic o anumită cafea și
servește ca PRIMARY KEY. A doua coloană, numită ID_Furnizor, deține un număr
care identifică furnizorul de cafea și are tipul INTEGER. A treia coloană, denumită
Preț, depozitează valori de tipul FLOAT deoarece trebuie să țină valori cu punct
zecimal. Coloana denumită Vânzări depozitează valori INTEGER și indică numărul de
kilograme de cafea vândute în timpul săptămânii curente. Ultima coloană, TOTAL,
conține valori INTEGER, care arată numărul total de kilograme de cafea vândute până
la data curentă.

39

Furnizori, a doua tabelă din baza de date, oferă informații despre fiecare dintre
furnizori:

ID_Furnizor Nume_Furnizor Strada Oras Tara Cod_Postal
110 Acme, Inc. Lipovei Timisoara Romania 335200
10 Superior Coffee Rue Café Paris Brasil 95460
150 Café Italiano Isla Roma Italia 23478

Atât tabela CAFELE cât și tabela FURNIZOR I conțin o coloană ID_Furnizor .
Aceste două tabele pot fi folosite în propoziții SELECT pentru a obține date bazându -se
pe informații din ambele tabele. Coloana ID_Furnizor este cheia primară în tabela
FURNIZORI, astfel că ea indentifică în mod unic fiecar e dintre furnizorii de cafea. În
tabela CAFELE , ID_Furnizor este o cheie străină (putem să ne gândim la ea ca fiind
importată dintr -o altă tabelă).
Putem crea tabele în trei feluri:
 Prin folosirea unei interfețe grafice IDE sau a bazei de date
 Folosind AN T
 Folosind JDBC SQL scris într -o aplicație
În cele ce urmează voi descrie ce de -a treia variantă deoarece voi folosi această
metodă.
Următoarea propoziție SQL crează tabela denumită CAFELE:
CREATE TABLE cafele (
Nume_Cafea VARCHAR(32),
ID_Furnizor INTEGER ,
Pret FLOAT,
Vanzari INTEGER
Total INTEGER)
Acest cod nu se încheie cu un terminator de propoziții SGBD, care variază de la un
SGBD la altul. De exemplu, Oracle folosește ; pentru a indica sfârșitul unei propoziții,
iar Sybase folosește cuvântul go. Drive rul pe care îl folosim va asigura automat
terminatorul de propoziție potrivit și nu va trebui să îl includem în codul nostru JDBC:
SELECT Nume_Furnizor, Oras
FROM furnizori
WHERE Nume_Furnizor LIKE “Acme, Inc”

Interfața Statement
Interfața Statement oferă metodele de bază pentru trimiterea de secvențe SQL către
baza de date și obținerea rezultatelor, celelalte două interfețe: PreparedStatement și
CallableStatement fiind derivate din aceasta.
Crearea unui obiect Statement se realizează prin intermediul meto dei
createStatement a clasei Connection, fără nici un argument:
Connection con = DriverManager.getConnection(url);
Statement stmt = con.createStatement();

40
Execuția unei secvențe SQL poate fi realizată prin intermediul a trei metode:

1. executeQuery
Este fol osită pentru realizarea de interogări de tip SELECT.Metoda returnează
un obiect de tip ResultSet ce va conține sub o formă tabelară rezultatul interogării.

String sql = "SELECT * FROM persoane";
ResultSet rs = stmt.executeQuery(sql);

2. executeUpdate
Este folosită pentru actualizarea datelor (INSERT, UPDATE, DELETE)
sau a structurii bazei de date (CREATE, ALTER, DROP). Metoda va returna un întreg
ce semnifică numărul de linii afectate de operațiunea de actualizare a datelor, sau 0 în
cazul unei instrucțiu ni DDL.
String sql = "DELETE FROM persoane WHERE cod > 100";
int linii = stmt.executeUpdate(sql);
// Nr de articole care au fost afectate (șterse)
sql = "DROP TABLE temp";
stmt.executeUpdate(sql); // returneaza 0

3. execute
Această metodă va fi folosită doar dacă este posibil ca rezultatul unei interogări să
fie format din două sau mai multe obiecte de tip ResultSet sau rezultatul unei
actualizări să fie format din mai mule valori, sau o combinație între aceste cazuri.
Această situație, deși mai rară, este po sibilă atunci când sunt executate proceduri
stocate sau secvențe SQL cunoscute abia la momentul execuției, programatorul neștiind
deci dacă va fi vorba de o actualizare a datelor sau a structurii. Metoda întoarce true
dacă rezultatul obținut este format di n obiecte de tip ResultSet și false dac ă e format din
întregi.
În funcț ie de aceasta, pot fi apelate metodele: getResultSet sau getUpdateCount
pentru a afla efectiv rezultatul comenzii SQL. Pentru a prelua toate rezultatele va fi
apelat ă metoda getMoreResu lts, dup ă care vor fi apelate din nou metodele amintite,
până la obț inerea valorii null, respectiv −1.

Obținerea rezultatelor din ResultSet
Interfața ResultSet asigură metode pentru obținerea datelor și manipularea
rezultatelor interogărilor executate, și obiectele ResultSet pot avea funcționalități și
caracteristici diferite. Aceste caracteristici sunt tipul setului de rezultate, concurența
setului de rezultate și sprijinirea cursorului.
JDBC returnează rezultatele într -un obiect ResultSet, așadar trebui e să declarăm o
instanță a clasei ResultSet pentru a ține rezultatele. În plus, ambele metode Statement:
executeQuery și getResultSet retunează un obiect ResultSet, așa cum fac și mai multe
metode DatabaseMetaData. Următorul cod demonstrează declararea obi ectului

41
ResultSet, rs, și asignarea rezultatelor interogării de mai sus la acest obiect folosind
metoda executeQuery.

Utilizarea metodelor ResultSet
Variabila srs, care este o instanță a ResultSet, conține rândurile cu valori ale
cafelelor și prețurilor a rătate în setul de rezultate din exemplu de mai sus. Pentru a
accesa numele și prețurile, un obiect ResultSet menține un cursor, care indică la rândul
curent de date.
Când un obiect ResultSet este creat pentru prima dată, cursorul este poziționat
înainte d e primul rând. Pentru a muta cursorul, putem folosu următoarele metode:
 next() – mută cursorul în față cu un rând. Returneză true dacă acest cursor
este poziționat acum pe un rând și false în cazul cursorul este poziționat după
ultimul rând.
 previous() – mută cursorul în spate cu un rând. Returnează true în cazul în
care cursorul este poziționat acum pe un rând și false dacă este poziționat înainte
de primul rând
 first() – mută cursorul pe primul rând în obiectul ResultSet . Returnează true
în cazul în care cur sorul este poziționat pe primul rând și false dacă obiectul
ResultSet nu conține nici un rând
 last() – mută cursorul pe ultimul rând din obiectul ResultSet . Returnează
true în cazul în care cursorul este acum poziționat pe ultimul rând și false dacă
obiectu l ResultSet nu conține nici un rând.
 beforeFirst() – poziționează cursorul la începutul obiectului ResultSet ,
înainte de primul rând.
 afterLast() – poziționează cursorul la sfârșitul obiectului ResultSet , după
ultimul rând. relative(int rows) – mută cursoru l relativ la poziția sa curentă
 absolute(int row) – poziționează cursorul pe rândul al row-lea al
obiectului ResultSet

Utilizarea metodelor getXXX
Interfața ResultSet declară metode de “achiziționare” (getBoolean, getLong ,
ș.a.m.d.) pentru a primit valor ile coloanelor din rândul curent. O aplicație poate returna
valori fie folosind numărul de indexare al coloanei, fie numele coloanei. Indexul
coloanei este de obicei mai eficient. Coloanele sunt numerotate începând cu 1. Pentru
portabilitate maxima, coloan ele ce alcătuiesc setul de rezultate din fiecare rând ar trebui
citite în ordine de la stânga la dreapta și fiecare coloană ar trebui citită o singură dată.
Numele coloanelor folosite ca și input al metodelor de achiziționare sunt case
sensitive. Când o a stfel de metodă este numită cu un nume de coloană si alte câteva
coloane au același nume, va fi returnată valoarea primei coloane care se potrivește.
Opțiunea de nume al coloanei este creată pentru a fi folosită când numele de coloane
sunt folosite în inte rogări SQL care au generat setul de rezultate. Pentru coloane care nu
sunt denumite explicit în interogare, este cel mai bine să folosim numere de coloane.
Dacă sunt folosite nume de coloane, programatorul ar trebui să aibă grijă să garanteze
referirea la coloanele potrivite, lucru asigurat prin clauza SQL AS.

42
Metoda getXXX de tipul potrivit primește valoarea în fiecare coloană. De exemplu,
prima coloană din fiecare rând al srs este COF_NAME, care depozitează o valoare de
tipul SQL VARCHAR. Metoda folosită pentru a primi o valoare de tipul VARCHAR
este getString. A doua coloană din fiecare rând depozitează o valoare de tipul SQL
FLOAT, și metoda pentru returnarea valorilor de acest tip este getFloat . Metoda
getString este invocată pentru obiectul de tip Resu ltSet srs, așadar getString primește în
rândul curent al srs valoarea depozitată în coloana Nume_Cafea. Valoarea pe care o
returnează getString a fst convertită de la tipul VARCHAR la tipul String al limbajului
de programare Java, și este asignat obiectulu i String s.
Trebuie precizat faptul că deși metoda getString este recomandată pentru a retuna
tipurile SQL CHAR și VARCHAR, este posibil să returneze oricare dintre tipurile SQL
de bază. Obținerea tuturor valorilor cu getString poate fi foarte utilă, dar a re limitările
ei. De exemplu, dacă este folosită pentru obținerea unui tip numeric, getString
convertește valoarea numerică la un obiect String Java, și valoarea trebuie convertită
din nou în tip numeric înainte să se poată opera asupra ei ca și număr. În cazul în care
valoarea este totuși tratată ca și un string, nu este nici un dezavantaj. Următorul
exemplu se referă la utilizarea functiei getString pentru obținerea valorilor de orice tip:

Statement stmt = con.createStatement(ResultSet.TYPE_SCROLL_SENSI TIVE,
ResultSet.CONCUR_READ_ONLY);
ResultSet srs = stmt.executeQuery("SELECT Nume_Cafea, Pret FROM
CAFELE");
while (srs.next()) {
String nume= srs.getString("NUME_CAFEA");
float pret = srs.getFloat("PRE T");
System.out.println(nume + " " + pret);
}

Rezultatul va arăta astfel:
Columbiana 5.69
Franceza 6.69
Espresso 10
Columbiana_decaf 7.89
Franceza_decaf 8.89
Toate rândurile pot fi procesate în srs de la sfârșit către început, dar pentru a face
acest lucru, cursorul poate începe după ultimul rând. Putem muta cursorul explicit la
poziția de după ultimul rând cu metoda afterLast . Atunci, metoda previous() mută
cursorul de la această poziție pe ultimul rând, și apoi pe rândul preceden t cu fiecare
iterație a buclei while. Bucla se încheie atunci când cursorul ajunge la poziția dinaintea
primului rând, unde metoda previous() va returna false.

Statement stmt = con.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_READ_ONLY);
ResultSet srs = stmt.executeQuery("SELECT Nume_Cafea, Pret FROM
CAFELE");

43
srs.afterLast();
while (srs.previous()) {
String nume = srs.getString("Nume_Cafea");
float pret = srs.getFloat ("PRET");
System.out.println(nume + " " + pret);
}

Rezultatul va arăta astfel:
Franceza_decaf 8.89
Columbiana_decaf 7.89
Espresso 10
Franceza 6.69
Columbiana 5.69

Valorile se păstrează aceleași, dar ordinea rândurilor este invers ă.
JDBC oferă două modalități de a identifica coloana din care a obținut metoda
getXXX o valoare. O modalitate este oferirea unui nume de coloană, cum a fost cazul
exemplului anterior. A doua modalitate este să oferim un index de coloană(numărul
coloanei), cu 1 însemnând prima coloană, 2, a doua coloană, și așa mai departe.
Folosirea numărului de coloană, în locul numelui coloanei arată astfel:

String s = srs.getString(1);
float n = srs.getFloat(2);

Prima linie de cod primește valoarea din prima coloană a rândului curent
srs(coloana Nume_Cafea), o convertește î ntr-un obiect de tip String Java, și o asignează
lui s. A doua linie de cod primește valoarea depozitată în a doau coloană a rândului
curent srs, o convertește în tipul float Java și o asignează lu i n. Trebuie remarcat faptul
că numărul coloanei se referă la coloana din setul de rezultate, nu din tabela originala.
Putem muta cursorul la un rând anume în obiectul ResultSet . Metodele first, last,
beforeFirst și afterLast mută cursorul la rândul indica t în numele lor. Metoda absolute
va muta cursorul la numărul rândului indicat în argumentul care îî este dat. dacă
numărul este pozitiv, cursorul se mută de la început, adicaă apelul absolute(1) pune
cursorul pe primul rând. Dacă numărul este negative, cur sorul se mută de la sfârșit,
adică apelul absolute( -1) pune cursorul pe ultimul rând.
Următoarea linie de cod mută cursorul pe al patrulea rând al srs:
srs.absolute(4);
Dacă srs are 500 de rânduri, următoarea linie de cod mută cursorul pe rândul 497:
srs.absolute( -4);
Există trei metode care mută cursorul la o poziție relativă la poziția curentă. După
cum am prezentat mai sus, metoda next mută cursorul un rând înainte și metoda
previous mută cursorul cu un rând înapoi. Cu metoda relative se poate specifica
numărul de rânduri peste care să fie mutat cursorul relativ la poziția curentă și de
asemenea direcția în care să se deplaseze. De exemplu, în următorul fragment de cod,

44
cursorul se mută pe al patrulea rând, apoi pe primul rând, și în cele de urmă pe al t reilea
rând:

srs.absolute(4); // cursorul este pe al patrulea rând
. . .
srs.relative( -3); // cursorul este pe primul rând
. . .
srs.relative(2); // cursorul este pe al treilea rând

Metoda getRow ne permite să verificăm numărul rândului pe care se găs ește
cursorul. De exemplu, putem folosi getRow pentru a verifica poziția curentă a
cursorului în exemplul precedent, după cum urmează:

srs.absolute(4);
int rowNum = srs.getRow(); // rowNum ar trebui să fie 4
srs.relative( -3);
int rowNum = srs.getRow(); // rowNum trebuie să fie 1
srs.relative(2);
int rowNum = srs.getRow(); // rowNum trebuie să fie 3

Există patru metode adiționale pentru verificarea unei poziții anume a cursorului.
Poziția este indicată chiar în numele lor: isFirst , isLast , isBeforeFirst , isAfterLast .
Aceste metode returnează un tip Boolean și datorită acestui fapt pot fi folosite în
propoziții condiționale
Ca și concluzie, JDBC permite fie folosirea unui nume de coloană fie a unui numă r
de coloană ca și argument al unei funcții getXXX . Utilizarea numărului de coloană este
ușor mai eficientă, și sunt câteva cazuri în care numărul de coloană este obligatoriu.
Totuși, în general, oferirea numelui coloanei este echivalentă cu oferirea numărului
coloanei.
JDBC permite o multitudine de posibili tăți în ceea ce privește folosirea metodelor
getXXX pentru a obține diferite tipuri de date SQL. De exemplu, metoda getInt poate fi
folosită pentru a obține oricare dintre tipurile numerice sau caracter. Datele pe care le
primește vor fi convertite la tipu l int. Metoda getInt este recomandată pentru a obține
numai tipuri INTEGER SQL, dar nu poate fi folosită pentru tipurile SQL BINARY,
VARBINARY, LONGVARBINARY, DATE, TIME sau TIMESTAMP.

Actualizarea tabelelor
În cele ce urmează voi prezenta elementele le gate de actualizarea rândurilor dintr –
un set de rezultate, utilizând metodele din limbajul de programare Java în locul
trimiterii unei comenzi SQL.
Actualizarea unui rând dintr -un obiect ResultSet se efectuează în două faze. Mai
întâi, noua valoare pentru fiecare coloană ce trebuie actualizată este setată, iar apoi
schimbarea este aplicată rândului. Rândul din sursa de date de bază nu este actualizat
până la terminarea celei de a doua faze.

45
Interfața ResultSet conține două metode de actualizare pentru fieca re tip JDBC, una
care specifică acea coloană ce trebuie actualizată ca și un index și una care specifică
numele coloanei așa cum apare în lista de selecție. Numele de coloane transmise
metodelor de actualizare nu sunt case sensitive. Dacă o listă de selecț ie conține aceeași
coloană de mai multe ori, va fi actualizată prima instanță a coloanei.
Mai întâi trebuie să creăm obiectul ResultSet care este actualizabil. Pentru a face
acest lucru, trebuie să transmitem constanta ResultSet : CONCUR_UPDATABLE,
metodei createStatement . Obiectul Statement creat de această metodă produce un obiect
actualizabil ResultSet de fiecare dată când execută o interogare. Următorul fragment de
cod ilustrează crearea obiectului uprs actualizabil ResultSet . Codul face de asemenea ca
obiectul uprs să fie derulabil, deoarece când vom aplica modificări la un set de rezultate
com dori să ne putem mișca în interiorul lui. Cu un set de rezultate rerulabil, putem să
ne deplasăm la un rând pe care dorim să îl modificăm, iar dacă tipul este
TYPE_SCROLL_SENSITIVE, putem obține noua valoare într -un rând după ce l -am
modificat.

Connection con =
DriverManager.getConnection("jdbc:mySubprotocol:NumeSubMeu");
Statement stmt = con.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,
ResultSet.CONCUR_UPDATABLE);
ResultSet uprs = stmt.executeQuery("SELECT Nume_Cafea, Pret FROM
CAFELE");

Obiectul ResultSet uprs va arăta astfel:

NUME_CAFEA PRET
–––––– –––
Columbiana 5.69
Franceza 6.69
Espresso 10
Columbiana_Decaf 7.89
Franceza_Decaf 8.89

Metoda updateRow va aplica toate modificările coloanei la rândul curent.
Modificările nu sunt aplicate rândului decât la apelul metodei updateRow . Metoda
cancelUpdates poate fi folosită pentru a retrage modificările asupra rândului înainte ca
metoda updateRow să fie apelată.

Statement stmt = conn.createStatement(ResultSet.TYPE_FORWARD_ONLY,
ResultSet.CONCUR_UPDATABLE);
ResultSet srs = stmt.executeQuery("select Nume_Cafea from CAFELE " +
"where pret = 7.99");
srs.next();
srs.updateString("Nume_Cafea", "Nescafe");
srs.updateRow();

46

O actualizare este modificarea valorii unei coloane în rândul curent. Putem
presupune că vre m să ridicăm prețul cafelei franceze decofeinizate la 10.99:

uprs.last();
uprs.updateFloat("Pret”, 10.99);

Operațiile de actualizare afectează valorile coloanelor în rândul în care este
poziționat cursorul, așadar în prima linie obiectul uprs apelează me toda last pentru a
muta cursorul pe ultimul rând(adică rândul care conține valoarea Franceza_Decaf
pentru coloana Nume_Cafea). Odată ce cursorul este poziționat pe ultimul rând, toate
metodele de actualizare vor opera asupra acetui rând până când vom muta cursorul
asupra altuia. A doua linie modifică valoarea din coloana Pret la 10.99, apelând metoda
updateFloat . Această metodă este utilizată pentru că valoarea din coloana pe care vrem
să o actualizăm este de tipul float în limbajul de programare Java.
Meto dele updateXXX primesc doi parametrii: coloana care trebuie actualizată și
noua valoare ce trebuie pusă în respectiva coloană. Ca și în cazul metodelor getXXX ,
parametrul care desemnează coloana poate fi ori numele coloanei, ori numărul coloanei.
Există o metodă diferită pentru a actualiza fiecare tip de date( updateString ,
updateBigDecimal , updateInt , etc.) la fel ca și în cazul metodelor getXXX .
Ordonarea rândurilor din setul de rezultate nu are nici o legătură cu ordinea
rândurilor din tabela de bază. De fapt, ordinea rândurilor din tabelele bazei de date este
nedeterminată. SGBD -ul reține care rânduri au fost selectate, și efectuează actualizările
asupra rândurilor corecte, dar ele pot fi localizate oriunde în tabelă. Când un rând este
inserat, de exemplu , un putem ști unde în tabelă a fost el inserat.

Folosirea PreparedStatement
Până acum au fost prezentate câteva elemente de bază JDBC. În cele ce urmează
voi prezenta câteva elemente mai complexe referitoare la elementele JDBC folosite în
aplicația p ractică.
Uneori este mai convenabilă folosirea obiectului PreparedStatement pentru
trimiterea propozițiilor SQL la baza de date. Acest tip special de propoziție este derivat
din clasa mai generală, Statement . Dacă dorim să utilizăm obiecte Statement de mai
multe ori, timpul de execuție ar fi redus prin utilizarea obiectului PreparedStatement .
Principala caracteristică a obiectului PreparedStatement este că, spre deosebire de
obiectul Statement , îî este dată o propoziție SQL la creare. Avantajul este că în c ele mai
multe cazuri, această propoziție SQL este trimisă la SGBD imediat, loc unde este
compilată.

Crearea unui obiect PreparedStatement

47
Ca și la crearea obiectelor Statement , obiectele PreparedStatement sunt create cu o
metodă Connection . Utilizând con exiunea con din exemplele precedente, putem scrie
cod cum ar fi următorul exemplu de obiect PreparedStatement care primește doi
parametrii:
PreparedStatement updateVanzari = con.prepareStatement(
"UPDATE CAFELE SET Vanzari = ? WHERE Nume_Cafea LIKE ?");
Variabila updateVanzari conține acum propoziția SQL “UPDATE CAFELE SET
Vanzari=? WHERE Nume_Cafea LIKE ?”, care a fost deja trimisă SGBD -ului și
compilată.

Furnizarea valorilor pentru parametrii PreparedStatement
Va trebui să furnizăm valori pentru a fi fo losite în locul semnelor de întrebare(dacă
acestea există) înainte de executarea unui obiect PreparedStatement . Facem acest lucru
prin apelul uneia dintre funcțiile setXXX definite în clasa PreparedStatement . Dacă
valoarea pe care dorim să o substituim pen tru un semn de întrebare este un tip int Java,
va trebui să apelăm metoda setInt . În general există o metodă setXXX pentru fiecare tip
de dată declarat în limbajul de programare Java.
Exemplu:
updateVanzari.setInt(1, 75)
Primul argument transmis unei metod e setXXX indică semnul de întrebare care
trebuie înlocuit, iar al doile argument indică valoarea care trebuie setată pentru acesta.
Metoda executeUpdate este folosită atât pentru execuția obiectelor Statement cât și
pentru execuția obiectelor PreparedStat ement.
Folosirea unei bucle pentru a seta valorile
De multe ori se poate folosi o bucla for sau o bucla while pentru a seta valorile
parametrilor.
Următorul fragment de cod este folosit pentru a demonstra utilizarea unei bucle for
pentru a seta valorile p entru parametrii în obiectul PreparedStatement denumit
updateVanzari . Vectorul vanzariPerSaptamana va deține volumul vându per săptămână.
Aceste volume de vânzări corespund numelor cafelelor listate în vectorul cafele, așa
încât primul volum din vanzariPer Saptamana(175) se aplică primei cafele din
cafele(“Columbiana”), etc. Următorul fragment de cod demonstrează actualizarea
coloanei Vanzari pentru toate tipurile de cafele din tabela CAFELE:

PreparedStatement updateVanzari;
String updateString = "update CA FELE " +
"set Vanzari = ? where Nume_Cafea like ?";
updateVanzari = con.prepareStatement(updateString);
int [] vanzariPerSaptamana = {175, 150, 60, 155, 90};
String [] cafele = {"Columbiana", "Franceza", "Espresso",
"Columbiana_Decaf", "Franceza_Decaf"};
int len = cafele.length;
for(int i = 0; i < len; i++) {
updateVanzari.setInt(1, vanzariPerSaptamana[i]);
updateVanzari.setString(2, cafele[i]);

48
updateVanzari.executeU pdate();
}

Când proprietarul va dori să actualizeze volumul de vânzări pentru săptămâna
următoare, poate folosi același cod ca și template. Tot ce trebuie să facă este să intre
noile volume în ordinea corespunzătoare în vectorul vanzariPerSaptaman a. Numele
cafelelor din vectorul cafele rămâne constant, așa că nu va trebui schimbat. În
aplicațiile reale, valorile ar putea fi introduse mai bine introduse de utilizator decât
dintr -un vector Java inițializat.

Returnarea valorilor de la metoda executeU pdate
Fie că executeQuery returnează un obiect ResultSet ce conține rezultatele
interogării trimise la SGBD, valoarea returnată pentru executeUpdate este un int care
indică numărul de rânduri actualizate dintr -o tabelă. De exemplu, următorul cod arată
cum valoarea de returnare a metodei executeUpdate este asignată variabilei n:
updateVanzari.setInt(1, 50);
updateVanzari.setString(2, "Espresso");
int n = updateVanzari.executeUpdate();
//n ia valoarea 1 deoarece un singur rând a fost actualizat
Atunci când metoda executeUpdate este folosită pentru a executa o propoziție
DDL,cum ar fi crearea unei tabele, ea returnează valoare de tip int, 0.
Observatie: când valoarea returnată de executeUpdate este 0, poate însemna doua
lucruri:
 propoziția executată a fost o propoziție de actualizare care nu a afectat
nici un rând
 propoziția executată a fost o propoziție DDL
Interfața CallableStatement
Interfața CallableStatement este derivată din PreparedStatement, instanțele de acest
tip oferind o modalitate de a apela o pro cedur ă stocat ă într-o baz ă de date, într-o
manier ă standar d pentru toate SGBD -urile.
Crearea unui obiect CallableStatement se realizeaz ă prin metoda prepareCall a
clasei Connection:
Connection con = DriverManager.getConnection(url);
CallableStatement cstm t = con.prepareCall("{call proceduraStocata(?, ?)}");
Trimiterea parametrilor de intrare se realizeaz ă întocmai ca la PreparedStatement,
cu metode de tip setXXX.
Este posibil ca un parametru de intrare să fie și parametru de ieșire. În acest caz el
trebui e să primească o valoare cu setXXX și, de asemenea, va fi înregistrat cu
registerOutParameter, tipurile de date specificate trebuind să coincidă.

Așadar, folosind JDBC este ușor să transmitem secvențe SQL către baze de date
relaționale. Cu alte cuvinte, nu este necesar să scriem un program pentru a accesa o
bază de date Oracle, alt program pentru a accesa o bază de date MySQL și asa mai
departe.

49
Capitolul III. Elaborarea sistemului informatic cu SQL
3.1 “Cursuri Traininguri Conferinte” – Prezentare
Curs uri Traininguri Conferi nte este o aplica ție web de tip portal , care implementeaz ă
adăugarea cursurilor, trainingurilor și conferin țelor. Interfa ța este specific ă acestui tip și
este foarte u șor de accesat.
Pentru a accesa aplica ția este necesar ă prezen ța unui browser web pe calcul atorul
clientului, cum ar fi:
– Google Chrome
– Mozilla Firefox
– Safari
– Internet Explorer
– Opera
3.1.1 Interfa ța aplica ției
Toate paginile sunt realizate dupa un model unitar. Astfel:
3.1.1.1 Header
3.1.1.3 Sidebar
3.1.1.4 Con ținut
3.1.1.5 Footer

Fig. 3.1 – Interfata aplicatiei
3.1.1.1 Header
Conține toate legaturile unde utilizatorul aplica ției are acces, adic ă meniul aplica ției,
zona de autentificare și de înregistrare.

50
Zona de înregistrare (fig.3.2) con ține un formular unde to ate câmpurile marcate cu *
sunt obligatorii. În cazul in care nu a ți completat un c âmp obligatoriu v ă da o eroare.
După înregistrare merge ți la zona de autentificare unde v ă autentificati cu username
și o parola.

Fig.3.2

Zona de autentificare (fig.3.3) conține un formular pentru care utilizatori au acces de
a adăuga cursuri, traininguri, conferin țe și audio. Formularul con ține dou ă câmpuri
(utilizator și parola). În func ție de numele utilizatorului și de parola introdus ă un script
php evalueaza în datele din baza de date. Dac ă datele nu sunt corecte va aparea o
eroare, iar dac ă datele sunt corecte v a aparea un submeniu unde sunt adaugate toate
cursurile , trainingurile, conferintele, audio dumneavoastra și o zona de logout.

Fig.3.3
3.1.1.3 Sidebar
Este situat în partea dreapta a site -ului și con ține bara de meniu unde pute ți să
adăugați cursurile.

51

Fig.3.4
3.1.1.4 Con ținutul
Conține toate informa țiile despre sec țiunea pe care a ți accesat.

Fig.3.5

3.1.1.5 Footer
Este subsolul pagini , textul este sepa rat de con ținutul pagini și este situate in partea
de joi.

Fig.3.6
3.1.2 Ad ăugare cursuri
În partea dreapt ă a site -ului avem butoane pentru ad ăugarea cursurilor. Aceste
butoane deschid o alt ă pagina unde pute ți să adauga ți cursuri (fig.3.8). În cazul în care
nu v-ați autentificat o sa va apara o eroare (fig.3.7). Toate c âmpurile marcate cu * sunt
obligatorii.

52

Fig.3.7 Eroare în cazul în care nu v -ați autentificat

Fig. 3.8 Ad ăugare cursuri

3.1.3 Cursurile ad ăugate
În sec țiunea aceasta apar toate curs urile ad ăugate pe site. Aceast ă sectiune nu
necesit ă autentificare pe site, dar în cazul în care dori ți să vede ți numai cursurile

53
dumneavoastra v ă autentifica ți și în partea dreapta va apare un submeniu (cursurile
mele , trainingurile mele , conferintele mele, audio, logout).

Fig.3.9

În cazul în care dori ți să cauta ți cursuri în funcție de organizator sau de localitate
puteți să folosiți una din sec țiunile “filtru organizator” sau “filtru localitate”

Fig.3.11 Rezultatul filtrului dup ă localitatea Timi șoara

În cazul în care dori ți să edita ți sau s ă șterge ți cursurile dumneavoastr ă aveți
posibilitatea accesand submeniul “Cursurile Mele”. În aceasta sec țiune o s ă vă apară
numai cursurile ad ăugate de dumneavoastr ă, la fiecare curs ad ăugat ave ți în partea
dreapta joi dou ă butoane cum ar fi “Editare curs” și “Sterge” .

54

Fig.3.12 Editare sau ștergerea unui curs.

3.2. “Cursuri Traininguri Conferinte” – design și codul sursa
Aplica ția web de tip portal a fost dezvoltat ă în limbajul de programare PHP
(Hypertext Preprocessor) , HTML ( HyperText Markup Language ), CSS3 ( Cascading
Style Sheets ), Javascript si Json ( JavaScript Object Notation )
Design -ul aplica ției web a fost dezvoltat î n CSS și o mica parte în Photoshop pentru
o mai bun ă accesabilitate și rapiditate.
Iar pe partea de baza de date s -a folosit MySQL .

55
Concluzii

Dezvoltatea aplica ției se poate face și ulterior datorită structurări bazei de date si a
codului PHP.
SQL este un limbaj proiectat pentru returnarea și managementul datelor în sist emele
de baze de date relațioanale, în crearea și modificarea schemei bazei de date și în
managementul controlului accesului la obiectele bazei de date.
Din punct de vedere tehnic, SQL este un limbaj de programare declarativ pentru
utilizarea în “baze de d ate SQL”. Teoreticienii și anumiți practicieni notează faptul că
multe dintre capacitățile originale SQL au fost inspirate de modelul relațional pentru
managementul bazelor de date și de realizarea calculului de tuple dar au contribuit în
același timp și l a încălcarea acestor modele. Extensiile recente ale SQL au atins
completitudinea relațională dar au înrăutățit încălcările regulilor.
Aplicația realizată pentru susținerea temei lucrării de față are scopul de a oferi o
interfață, adică un intermediar între sistemul de gestionare a datelor și extragerea
datelor dorite de fiecare utilizator în parte.
Dacă adăugăm func ții suplimentare în codul aplica ției web se pot face multe
îmbunata țiri dar fără a modifica structura aplica ției.
Datorită realizării acestei i nterfețe în PHP, se rezolvă atât problema portabilității, cât
și cea a simplificării accesului la date, oferind un mediu plăcut și simplu de a ne
organiza activitățile, fără a trebui să ne facem probleme în privința datelor “tehnice” din
spatele monitorulu i. Așadar, aplicația își atinge scopul propus, de a oferi utilizatorului
un acces ușor la date
.

56
Bibliografie

 Gheorghe Petrov, Ioan Despi, Robert Reisz, Aurel Stepan, Teoria Generală a
Bazelor de Date , Ed. Mirton, Timișoara, 2001 (2002)

 Thomas Connolly, Carolyn Begg DATABASES SYSTEMS, A practical approach
to Design Implementation and Management , ADISON WESLY 3ED 2001.

 John Jones, Simon Monk, DATABASES Theory and practice ITC1998

 Popescu Ileana, Baze de date relaționale , E.U.B, 1997

 Ion Lungu, Constanța Bodea, Georgeta Bădescu, Cristina Ioniță – Baze de date
– Organizare, proiectare și implementare , ALL EDUCAȚIONAL, 1995

 Dan L.Lacrămă, Tiberiu M. Karnyanszky, Maria Deac, Baze de date – MySQL
în aplicații comerciale , Editura Mirton, Ti mișoara 2004

 Date, C.J. An Introductio n to Database Systems 3rd Ed. , Addison Wesley, 1982

 Donald K. Burleson, Joe Celko, John Paul Cook, Peter Gulutzan – Advanced
SQL Database Programmer Handbook, Rampant Techpress , August, 2003 for First
Edition

Similar Posts