Sunteți pe pagina 1din 48

Baze de date Capitolul 4

Capitolul 4. Iniţiere în limbajul SQL

În acest capitol vom studia elementele de bază ale limbajului de interogare şi


manipulare a bazelor de date SQL. Vom folosi acest limbaj pentru a scoate
informaţii dintr-o bază de date, pentru a modifica datele tabelelor şi chiar pentru
crearea de noi tabele sau ştergerea lor din baza de date. Abordarea limbajului se
va face de la simplu spre complex, iar exemplele prezentate vor fi foarte sugestive
pentru înţelegerea operaţiunilor executate.

Prezentare generală
Limbajul SQL este abrevierea de la Structured Query Language (limbaj
structurat de interogare) şi este un limbaj conceput special pentru
comunicarea cu bazele de date.

Spre deosebire de alte limbaje de programare, SQL se compune din foarte


puţine cuvinte (instrucţiuni), ceea ce face să fie uşor de învăţat şi folosit.
Toate bazele de date importante acceptă limbajul SQL, aşa că învăţarea lui
este de un real folos. În ciuda aparentei simplităţi, SQL este un limbaj
foarte puternic, cu care, dacă-i utilizaţi cu inteligenţă facilităţile, puteţi
efectua operaţii complexe şi sofisticate cu bazele de date.

Limbajul SQL este un limbaj neprocedural sau declarativ deoarece nu


conţine instrucţiuni precum IF, GOTO, WHILE sau altele care să ofere un
flux de control; utilizatorul lui descrie numai informaţiile pe care vrea să le
obţină în urma interogării bazei de date, fără a fi nevoie să stabilească şi
modalităţile de a ajunge la rezultatele dorite. Este ceea ce visează fiecare
dintre noi, nu?

Există un anumit grad de standardizare a limbajului SQL, mai multe


SGBDR recunoscând principalele instrucţiuni ale acestuia. Pe plan
mondial, standardul în domeniu este considerat ANSI (American National
Standards Institute) SQL care are în vedere atât aspectele de definire,
interogare, manipulare a datelor, procesare a tranzacţiilor, cât şi
caracteristicile complexe privind securitatea informaţiilor.
120
Baze de date Capitolul 4
Se cunosc în literatura de specialitate trei metode de bază privind
implementarea limbajului SQL şi anume: cea prin apelare directă, cea
modulară şi cea de tip încapsulat. Prima metodă costă în introducerea
instrucţiunilor SQL de la prompter, cea de a doua foloseşte anumite
proceduri apelate de programele aplicaţiei, iar cea de a treia variantă de
implementare are în vedere instrucţiuni încapsulate în codul program, fiind
de tip static şi dinamic.

Instrucţiunile SQL se grupează astfel:


 Instrucţiuni de definire a datelor;
 Instrucţiuni de manipulare a datelor (adăugare, modificare,
ştergere);
 Instrucţiuni de selecţie a datelor (consultare a bazei de date);
 Instrucţiuni de procesare a tranzacţiilor.

După cum spuneam, instrucţiunile SQL sunt puţine, dar ele sunt
completate cu clauze care le măresc puterea. Practic, noi trebuie să
înţelegem şi să folosim clauzele care însoţesc instrucţiunile. Sintaxa
folosită nu este pretenţioasă, singura noastră grijă este să folosim expresii
lizibile, prin evidenţierea instrucţiunilor şi a parametrilor lor.

În cadrul acestui curs vom folosi limbajul SQL corespunzător programului


ACCESS. În acest capitol vom învăţa folosirea limbajului scriind expresii
SQL pe hârtie folosind o bază de date existentă, completată cu date. Abia
în capitolul următor vom folosi limbajul SQL în cadrul programului
ACCESS.

Baza de date pe care o vom folosi în acest capitol, cea pe care o să ne


exersăm talentele, este cea proiectată în capitolul anterior şi se numeşte
BD_ITM, a cărei structură este cunoscută. Pentru unele instrucţiuni vom
folosi şi alte baze de date dacă necesităţile vor impune acest lucru.

Metoda pe care o vom folosi pentru a învăţa limbajul SQL este cea a
învăţării „din mers” a instrucţiunilor şi clauzelor, adică executăm
operaţiuni şi învăţăm instrucţiunile folosite. Operaţiunile vor fi în aşa fel
alese ca să acopere tot spectrul practic pe care o să-l întâlniţi în realitate.
Într-o anexă vor fi sistematizate instrucţiunile SQL cu clauzele şi sintaxa
lor. Această anexă vă va fi de un real folos după ce veţi dobândi o anumită
experienţă în utilizarea limbajului SQL.

121
Baze de date Capitolul 4
Operaţiuni simple folosind limbajul SQL

Regăsirea datelor

Regăsirea datelor se face cu instrucţiunea SELECT, folosită pentru a regăsi


una sau mai multe coloane. Aceasta este cea mai folosită instrucţiune din
SQL.

Din tabelul tblStudenti prezentat în figura 4.1 ne propunem să extragem


numele şi prenumele studenţilor.

StudID Nume Init Prenume Sectia An Grupa Stare


1 Bogdan P. Mircea Florin IEI 1 1311 Bugetar
2 Meruta I. Cosmin IEI 3 1332 Bugetar
3 Pop T. Marius Traian IEI 2 1321 Bugetar
4 Bucur P. Mihaela IEI 2 1321 Bugetar
5 Chirila I. Laura IEI 3 1331 Bugetar
6 Cotirla L. Raluca Adina TCM 1 1111 Bugetar
7 Cotoara G. Ovidiu TCM 1 1111 Bugetar
8 Cozma D. Dumitru TCM 2 1121 Bugetar
9 Damian N. Daniel MEC 4 1241 Bugetar
10 Farcas I. Calin Florin MEC 4 1241 Taxa

Fig. 4.1. Tabelul tblStudenti simplificat

Expresie SQL:
SELECT Nume, Prenume
FROM tblStudenti;

Rezultat:

Nume Prenume
Bogdan Mircea Florin
Meruta Cosmin
Pop Marius Traian
Bucur Mihaela
Chirila Laura
Cotirla Raluca Adina
Cotoara Ovidiu
Cozma Dumitru
Damian Daniel
Farcas Calin Florin

122
Baze de date Capitolul 4
Observaţi expresia SQL care se citeşte astfel: selectează coloanele Nume şi
Prenume din tabelul tblStudenti. S-a folosit şi clauza FROM, aşa cum se
vede. Rezultatul obţinut este evident.

Dacă doriţi să selectaţi toate coloanele tabelului se foloseşte expresia


următoare:

Expresie SQL:
SELECT *
FROM tblStudenti

În locul listei de coloane se pune acest simbol „ * ”.

Sortarea datelor

Prin sortarea datelor se înţelege aranjarea înregistrărilor unui tabel într-o


anumită ordine, de regulă, alfabetică sau crescătoare/descrescătoare.
Sortarea datelor se face cu ajutorul clauzei ORDER BY a instrucţiunii
SELECT.

La tabelul din figura 4.1 ne propunem să scoatem numai numele şi


prenumele studenţilor dar în ordine alfabetică.

Expresie SQL:
SELECT Nume, Prenume
FROM tblStudenti
ORDER BY Nume;

Rezultat:

Nume Prenume
Bogdan Mircea Florin
Bucur Mihaela
Chirila Laura
Cotirla Raluca Adina
Cotoara Ovidiu
Cozma Dumitru
Damian Daniel
Farcas Calin Florin
Meruta Cosmin
Pop Marius Traian

123
Baze de date Capitolul 4
Observaţi clauza ORDER BY care ordonează înregistrările în ordine
alfabetică după valorile din câmpul Nume. Se pune întrebare, ce ne facem
dacă vrem să ordonăm invers alfabetic (de la Z la A)? Sau dacă avem un
câmp numeric şi dorim să ordonăm descrescător după acest câmp. Iată
răspunsul:
 Pentru a indica ordinea descrescătoare de sortare se foloseşte
cuvântul cheie DESC.
 Dacă câmpul după care se face sortarea este alfanumeric, sortarea
se face alphabetic, iar dacă este numeric sau de dată
calendaristică, sortarea se face crescător/descrescător.
 Dacă nu se indică direcţia de sortare, se ia sortarea crescătoare
care este implicită. (Cazul prezentat.)

Iată cum arată o expresie SQL în care apare şi cuvântul cheie DESC:

Expresie SQL:
SELECT Nume, Prenume
FROM tblStudenti
ORDER BY Nume DESC

Reţineţi că rezultatul sortării datelor este un tabel care are acelaşi număr de
înregistrări ca şi originalul.

Filtrarea datelor

Prin filtrarea datelor se înţelege extragerea dintr-un tabel numai a anumitor


înregistrări de care avem nevoie, de exemplu, din tabelul de studenţi avem
nevoie numai de cei din anul 2. Pentru a executa această operaţiune veţi
folosi clauza WHERE a instrucţiunii SELECT.

Regăsirea numai a înregistrărilor dorite, presupune includerea în expresia


SQL a unui criteriu de căutare a înregistrărilor dorite. Într-o instrucţiune
SELECT, datele sunt filtrate prin specificarea criteriilor de căutare în
clauza WHERE. Locul acesteia este imediat după numele tabelului (clauza
FROM), ca în exemplul următor. Fie tabelul din figura 4.1.

124
Baze de date Capitolul 4
Ne propunem să filtrăm studenţii din anul 2. expresia SQL este
următoarea:

Expresie SQL:
SELECT StudID, Nume, Init, Prenume, Sectia, Grupa
FROM tblStudenti
WHERE An = ”2”;

Rezultat:
StudID Nume Init Prenume Sectia Grupa
3 Pop T. Marius Traian IEI 1321
4 Bucur P. Mihaela IEI 1321
8 Cozma D. Dumitru TCM 1121

Operatorii clauzei WHERE

Clauza WHERE pe care am examinat-o a testat egalitatea – determină dacă


o coloană conţine valoarea specificată. Limbajul SQL acceptă mai mulţi
operatori condiţionali, după cum urmează:
 = Egalitate
 <> Non-egalitate
 != Non-egalitate
 < Mai mic decât
 <= Mai mic sau egal cu
 !< Nu mai mic decât
 > Mai mare decât
 >= Mai mare sau egal cu
 !> Nu mai mare decât
 BETWEEN Între două valori specificate
 IS NULL Este o valoare NULL

Observaţi că pentru non-egalitate există două simboluri, aceasta pentru că


diversele SGBDR-uri acceptă pe unul sau altul dintre ele.

125
Baze de date Capitolul 4
Iată câteva cazuri concrete de folosire a operatorilor:

Interval de valori: WHERE Pret BETWEEN 2.5 AND 10; (afişează toate
înregistrările care au în coloana „Pret” valori între 2.5 şi 10).

Valoare NULL: WHERE Pret IS NULL; (afişează toate înregistrările care


nu au preţ).

Non-egalitate: WHERE Stare <> ”Bugetar”; (afişează toate înregistrările din


tabelul studenţi, folosit mai înainte, care nu sunt bugetari). Este evident că
putem formula şi altfel condiţia, dar aici am folosit non-egalitatea.

Ceilalţi operatori se folosesc la fel ca cel de egalitate prezentat puţin mai în


faţă.

Filtrare avansată

Filtrările prezentate mai sus se întâlnesc mai rar în practică deoarece sunt
foarte simple. Filtrările pe care le veţi folosi în mod curent, sunt filtrări mai
complicate la care criteriile sunt exprimate prin expresii complexe. Aceste
criterii creează condiţii puternice de căutare. Vom folosi alţi operatori cum
sunt AND, OR, NOT şi IN.

De multe ori, filtrarea după o coloană nu rezolvă problema pe care o avem.


Pentru a filtra după mai multe coloane se foloseşte operatorul AND. Fie
tabelul din figura 4.2. Ne propunem să facem diferite filtrări.

StudID Nume Init Prenume Sectia An Grupa Stare


1 Bogdan P. Mircea Florin IEI 1 1311 Bugetar
2 Meruta I. Cosmin IEI 1 1312 Taxa
3 Pop T. Marius Traian IEI 2 1321 Bugetar
4 Bucur P. Mihaela IMPI 2 1321 Bugetar
5 Pop I. Laura IEI 3 1331 Taxa
6 Cotirla L. Raluca Adina TCM 1 1111 Bugetar
7 Cotoara G. Ovidiu TCM 1 1111 Bugetar
8 Cozma D. Dumitru TCM 2 1121 Bugetar
9 Damian N. Daniel MEC 4 1241 Bugetar
10 Cozma I. Calin Florin MEC 4 1241 Taxa

Fig. 4.2. Tabel cu studenţi

126
Baze de date Capitolul 4
Operatorul AND. Prima filtrare ar fi studenţii de la IEI din anul 1. Iată
expresia SQL:

Expresie SQL:
SELECT Nume, Prenume, Grupa, Stare
FROM tblStudenti
WHERE Sectia=”IEI” AND An = ”1”;

Rezultat:
Nume Prenume Grupa Stare
Bogdan Mircea Florin 1311 Bugetar
Meruta Cosmin 1312 Taxa

Urmăriţi expresia SQL şi verificaţi rezultatul obţinut. Încercaţi şi alte


filtrări asemănătoare. Observaţi folosirea operatorului AND. Cum ar trebui
modificată expresia SQL, pentru a afişa rezultatul în ordine alfabetică
inversă?

Operatorul OR. O altă filtrare pe care ne-o propunem, este să filtrăm


studenţii din anul 2 de la IEI sau TCM.

Expresie SQL:
SELECT Nume, Prenume,Sectia, Grupa, Stare
FROM tblStudenti
WHERE (Sectia=”IEI” OR Sectia=”TCM”) AND An = ”2”;

Rezultat:
Nume Prenume Sectia Grupa Stare
Pop Marius Traian IEI 1321 Bugetar
Cozma Dumitru TCM 1121 Bugetar

Observaţi folosirea parametrilor OR şi AND, respectiv apariţia celor două


paranteze. Aceste paranteze au legătură cu ordinea operaţiilor OR şi AND.
În ordinea operaţiilor, operatorul AND se execută înaintea operatorului
OR, ceea ce ar duce la rezultate eronate, de aceea a fost pus operatorul OR
în paranteză, ca să-l execute primul, ştiut fiind că parantezele au prioritate
la execuţie.

Operatorul IN. Folosirea acestui operator are ca scop specificarea unui


domeniu de condiţii, oricare dintre ele putând fi îndeplinite. Operatorul IN
127
Baze de date Capitolul 4
necesită o listă de valori valide, care să fie separate prin virgule şi cuprinse
între paranteze.

Ne propunem să alegem din tabelul din figura 4.2 toţi studenţii care au
numele Pop şi Cozma.

Expresie SQL:
SELECT Nume, Prenume,Sectia, Grupa, Stare
FROM tblStudenti
WHERE Nume IN (“Pop”, “Cozma”);

Rezultat:
Nume Prenume Sectia Grupa Stare
Pop Marius Traian IEI 1321 Bugetar
Pop Laura IEI 1331 Taxa
Cozma Dumitru TCM 1121 Bugetar
Cozma Calin Florin MEC 1241 Taxa

Din analiza acestui exemplu, putem observa fără greutate că operatorul IN


face cam acelaşi lucru ca şi operatorul OR, deci se poate scrie o expresie
SQL cu acesta. Care este această expresie?

Se pune, pe bună dreptate, întrebarea de ce mai avem nevoie de încă un


operator dacă avem unul care face acelaşi lucru. Răspunsul este că
operatorul IN are unele avantaje care îl fac de preferat faţă de operatorul
OR. Iată aceste avantaje:
 Când lucraţi cu liste lungi de opţiuni valide, sintaxa operatorului
IN este mai simplă şi uşor de citit, principalul avantaj.
 Ordinea de evaluare este mai simplu de gestionat, când operatorul
IN este folosit în asociaţie cu operatorii AND şi OR.
 Aproape totdeauna, operatorii IN se execută mai rapid decât
listele de operatori OR.
 Un mare avantaj este că operatorul IN poate să conţină o altă
instrucţiune SELECT, şi astfel vă permite să construiţi clauze
WHERE foarte dinamice. Acest aspect va fi reluat mai târziu.

Operatorul NOT. Acest operator al clauzei WHERE are o singură funcţie


– neagă orice condiţie care îl urmează. Deoarece NOT nu este utilizat
niciodată în sine (totdeauna se foloseşte în asociaţie cu alt operator),
sintaxa lui e diferită de toţi ceilalţi operatori. Spre deosebire de alţi
128
Baze de date Capitolul 4
operatori, cuvântul cheie NOT poate fi utilizat înaintea coloanei după care
se face filtrarea, nu imediat după aceasta.

Iată un exemplu sugestiv, extragerea studenţilor nebugetari din tabelul din


figura 4.2.

Expresie SQL:
SELECT Nume, Prenume,Sectia, Grupa, Stare
FROM tblStudenti
WHERE NOT Stare=”Bugetar”;

Rezultat:
Nume Prenume Sectia Grupa Stare
Meruta Cosmin IEI 1312 Taxa
Pop Laura IEI 1331 Taxa
Cozma Calin Florin MEC 1241 Taxa

După cum se vede, acelaşi lucru îl puteam obţine şi cu operatorul „<>”.


Iarăşi se pune întrebarea de ce să folosim, totuşi, operatorul NOT? Într-
adevăr, pentru clauzele WHERE simple, cum e cea prezentată, nu se poate
spune că ar exista un avantaj real în folosirea operatorului NOT. Acesta
este însă foarte util în clauzele mai complexe. De exemplu, dacă folosiţi
operatorul NOT în asociaţie cu un operator IN, va fi mult mai simplu să
găsiţi toate înregistrările care nu corespund cu o listă de criterii.

Operatorul LIKE. Aici veţi învăţa ce sunt caracterele de înlocuire, cum se


folosesc ele şi cum să faceţi căutări cu ajutorul lor. Până acuma, toţi
operatorii, foloseau valori cunoscute, iar ei se ocupau de căutarea
corespondenţelor dintre valori, dacă sunt mai mari sau mai mici decât
altele, dacă verifică un domeniu de valori etc. De multe ori apare
necesitatea filtrării înregistrărilor după unele criterii care nu folosesc valori
cunoscute în totalitate. De exemplu, doriţi să căutaţi nume de persoane care
încep cu o literă, care conţin un grup de litere etc. Acest lucru nu se poate
face cu criterii simple comparare.

O soluţie, pe care ne-o propune SQL, este folosirea caracterelor de


înlocuire. Caracterele de înlocuire sunt caractere ce au înţelesuri speciale
în clauzele WHERE din SQL, iar limbajul SQL acceptă diverse tipuri de
caractere de înlocuire.

129
Baze de date Capitolul 4

Pentru a utiliza caracterele de înlocuire în clauzele de căutare, trebuie


utilizat operatorul LIKE. Acesta anunţă sistemul de gestiune a bazei de
date că în următorul model de căutare se va folosi o potrivire după
caractere de înlocuire, nu o simplă potrivire de egalitate.

Căutarea cu caractere de înlocuire poate fi utilizată numai cu câmpuri de


tip text. Reţineţi acest lucru!

În continuare vor fi prezentate caracterele de înlocuire folosite de


programul ACCESS.

Caracterul de înlocuire *. Este cel mai frecvent utilizat. Într-un şir de


căutare, „ * ” înseamnă „corespunde cu oricâte apariţii a oricărui
caracter”. Exemplul care urmează vă va ajuta să înţelegeţi acest caracter.

StudID Nume Init Prenume Sectia An Grupa Stare


1 Bogdan P. Mircea Florin IEI 1 1311 Bugetar
2 Brustur I. Cosmin IEI 1 1312 Taxa
3 Popescu T. Marius Traian IEI 2 1321 Bugetar
4 Brucan P. Mihaela IMPI 2 1321 Bugetar
5 Pop I. Laura IEI 3 1331 Taxa
6 Cotirla L. Raluca Adina TCM 1 1111 Bugetar
7 Popa G. Ovidiu TCM 1 1111 Bugetar
8 Popovici D. Dumitru TCM 2 1121 Bugetar
9 Branea N. Daniel MEC 4 1241 Bugetar
10 Cozma I. Calin Florin MEC 4 1241 Taxa

Fig. 4.3. Tabel cu studenţi

130
Baze de date Capitolul 4
Ne propunem să filtrăm toate înregistrările în care numele studenţilor, din
tabelul din figura 4.3, începe cu „Pop”.

Expresie SQL:
SELECT Nume, Prenume,Sectia, Grupa, Stare
FROM tblStudenti
WHERE Nume LIKE ”Pop*”
ORDER BY Nume;

Rezultat:
Nume Prenume Sectia Grupa Stare
Pop Laura IEI 1331 Taxa
Popa Ovidiu TCM 1111 Bugetar
Popescu Marius Traian IEI 1321 Bugetar
Popovici Dumitru TCM 1121 Bugetar

Observaţi ghilimelele care se pun şi ordonarea rezultatului după câmpul


Nume. Încercaţi şi alte filtrări folosind această tehnică.

Caracterul de înlocuire „ ? ”. Acest caracter (semnul întrebării) este


utilizat la fel ca simbolul „ * ”, dar nu asigură corespondenţa mai multor
caractere, ci numai a unuia singur. Exemplul care urmează vă ajută să
înţelegeţi folosirea lui.

Folosind tabelul din figura 4.3, scrieţi expresii SQL care să ilustreze
folosirea acestui caracter de înlocuire.

Observaţie! În diferite SGBDR semnele de înlocuire ar putea să fie


diferite. Astfel, în Oracle „ * ” este înlocuit cu „ % ”, iar „ ? ” este înlocuit
cu liniuţa de subliniere „ _ ”. Pentru a nu avea probleme este bine să
studiaţi documentaţia SGBDR-ului pe care îl veţi folosi.

131
Baze de date Capitolul 4
Operaţiuni avansate folosind limbajul SQL

Câmpuri calculate

După ştiţi de la proiectarea bazelor de date, o regulă de bază ne spune că


fiecare câmp trebuie să fie independent, adică valoare sa să nu depindă de
valorile din alte câmpuri. Exemplul clasic care se poate da aici este cel al
câmpului Valoare care nu trebuie să apară într-un tabel care are Pretul
unitar şi Cantitatea, dar avem nevoie de acest câmp care este rezultatul
înmulţirii dintre preţ şi cantitate. Ei bine, acest câmp trebuie calculat. Un
alt exemplu este cel al adresei care se compune din concatenarea
rezultatelor din mai multe câmpuri.

În ambele exemple, datele stocate în tabele nu sunt exact ceea ce are


nevoie aplicaţia dumneavoastră. În loc să regăsiţi datele aşa cum sunt,
pentru ca după aceea să le reformataţi în aplicaţia client sau în raport, doriţi
să regăsiţi datele transformate, calculate sau reformatate direct din baza de
date.

Aici intervin câmpurile cu valori calculate, pe care le vom numi în


continuare câmpuri calculate. Spre deosebire de toate coloanele de până
acum, câmpurile calculate nu există, de fapt, în baza de date. Un câmp
calculat este creat din mers, în interiorul unei instrucţiuni SELECT din
limbajul SQL.

De menţionat faptul că numai baza de date ştie care coloane dintr-o


instrucţiune SELECT sunt realmente coloane din tabele şi care sunt
câmpuri calculate. Din perspectiva unui client, datele unui câmp calculat
sunt returnate în acelaşi mod ca şi datele din oricare coloană.

Cel mai simplu mod de a înţelege crearea câmpurilor calculate este de a


alege exemple sugestive pe care să le comentăm.

Câmpuri calculate prin concatenare. De multe ori apare necesitatea


concatenării valorilor text din mai multe coloane. De exemplu, într-un
raport trebuie să scriem identitatea unei persoane formată din numele
complet, aşa cum se obişnuieşte în practică. Să scriem expresia SQL care
face acest lucru pentru persoanele din tabelul din figura 4.3.

132
Baze de date Capitolul 4
Expresie SQL:
SELECT Nume + “ “ + Init + “ “ + Prenume AS Student, Sectia, An, Grupa, Stare
FROM tblStudenti
ORDER BY Nume;

Rezultat:

Student Sectia An Grupa Stare


Bogdan P. Mircea Florin IEI 1 1311 Bugetar
Branea N. Daniel MEC 4 1241 Bugetar
Brucan P. Mihaela IMPI 2 1321 Bugetar
Brustur I. Cosmin IEI 1 1312 Taxa
Cotirla L. Raluca Adina TCM 1 1111 Bugetar
Cozma I. Calin Florin MEC 4 1241 Taxa
Pop I. Laura IEI 3 1331 Taxa
Popa G. Ovidiu TCM 1 1111 Bugetar
Popescu T. Marius Traian IEI 2 1321 Bugetar
Popovici D. Dumitru TCM 2 1121 Bugetar

Observaţi sintaxa folosită şi ceva nou a apărut, cuvântul cheie AS după


care urmează cuvântul Student, pe care îl regăsim în capul de tabel, ca
nume a noului câmp, obţinut prin concatenarea celor trei. Cuvântul cheie
AS introduce un alias care este un nou nume dat unui câmp. Reţineţi
această tehnică de creare a unor câmpuri.

Câmpuri calculate aritmetic. Aceste câmpuri calculate rezultă după


efectuarea unor calcule aritmetice asupra datelor regăsite. Pentru a înţelege
mecanismul creării acestor câmpuri, vom lua un exemplu practic.
Presupunem că avem un tabel în care ţinem intrările într-o magazie de
produse, al unei firme de comerţ cu piese auto. Tabelul se numeşte
tblProduse şi are coloanele Cod, Denumire, Furnizor, PU, Cantitate. Se
cere un raport al intrărilor în magazie în care apare şi câmpul Valoare,
obţinut prin produsul câmpurilor PU şi Cantitate. În figura 4.4 este
prezentat acest raport.

133
Baze de date Capitolul 4

Cod Denumire Furnizor PU Cantitate Valoare


1001 Bujie DK1 Sinterom SA 12 30 360
1023 Acumulator 56A Rombat SA 124 25 3100
1231 Parbriz VW Cobra SRL 512 12 6144
1089 Antigel -30 Promaxim SRL 5.2 50 26
1904 Ulei PKT 1 Calota SRL 6.4 60 384

Fig. 4.4. Raport cu câmpul valoare calculate

Expresie SQL:
SELECT Cod, Denumire, Furnizor, PU, Cantitate, PU*Cantitate AS Valoare
FROM tblProduse;

Observaţi şi reţineţi sintaxa folosită pentru crearea noului câmp


VALOARE.

Funcţii pentru manipularea datelor

Ca aproape toate limbajele de programare, SQL acceptă folosirea funcţiilor


pentru manipularea datelor. Funcţiile sunt operaţii care, de obicei, se
efectuează asupra datelor, în general pentru a facilita transformarea şi
manipularea acestora.

Trebuie să aveţi în vedere că fiecare SGBDR are propriile funcţii şi propria


sintaxă, chiar dacă ele seamănă foarte mult, există mici diferenţe pe care
trebuie să le ştiţi studiind documentaţia sistemului pe care îl folosiţi.
Descrierea funcţiilor din acest paragraf nu o să vă creeze probleme în
folosirea funcţiilor pentru orice SGBDR întâlnit în practică.

Majoritatea implementărilor SQL acceptă următoarele tipuri de funcţii:


 Funcţiile text sunt folosite la manipularea şirurilor de text (de
exemplu, pentru ajustarea sau completarea valorilor în majuscule
şi minuscule).
 Funcţiile numerice sunt folosite pentru operaţii matematice cu
date numerice (de exemplu, pentru returnarea valorilor absolute şi
efectuarea de calcule algebrice).

134
Baze de date Capitolul 4
 Funcţii de dată şi timp sunt folosite la manipularea valorilor
calendaristice de dată şi oră, şi la extragerea unor componente
caracteristice din aceste valori (an, lună, zi, oră) pentru a verifica
validitatea unor date introduse.

Funcţiile text. În această categorie vom regăsi clasicele funcţii de text care
se găsesc în toate limbajele de programare. Iată-le pe cele mai folosite:
 LEFT() - returnează caracterele indicate din stânga
şirului.
 RIGHT() - returnează caracterele indicate din dreapta şirului.
 LENGTH() - returnează lungimea unui şir.
 LOWER() - transformă toate caracterele şirului în minuscule.
 UPPER() - transformă toate caracterele şirului în majuscule.
 LTRIM() - înlătură spaţiile albe din stânga şirului.
 RTRIM() - înlătură spaţiile albe din stânga şirului.

Funcţiile numerice. În această categorie intră funcţiile folosite pentru


calcule algebrice, geometrice şi trigonometrice. Sunt mai puţin folosite la
bazele de date decât celelalte tipuri. Iată-le pe cele mai folosite:
 ABS() - returnează valoarea absolută a unui număr.
 COS() - returnează cosinusul unui unghi indicat.
 SIN() - returnează sinusul unui unghi indicat.
 TAN() - returnează tangenta unui unghi indicat.
 SQRT() - returnează rădăcina pătrată a unui număr
indicat.
 PI() - returnează valoarea lui PI.
 AVG() - returnează valoarea medie a unei coloane.
 COUNT() - returnează numărul de linii dintr-o coloană.
 MAX() - returnează valoarea cea mai mare dintr-o
coloană.
 MIN() - returnează valoarea cea mai mică dintr-o
coloană.
 SUM() - returnează suma valorilor unei coloane.

135
Baze de date Capitolul 4
Ultimele cinci funcţii se mai numesc şi funcţii agregat, deoarece au în
spate algoritmi complecşi.

Funcţiile de dată şi timp. Valorile datei şi orei sunt stocate în baza de date
în formate speciale, de aceea este nevoie de funcţii speciale pentru a le
manipula. Ele sunt cele mai importante funcţii din limbajul SQL. Aceste
funcţii ne ajută să extrageţi ora, luna, ziua, anul dintr-o astfel de dată şi să
faceţi diferenţa dintre două date calendaristice. Cele mai importante sunt:
 Date() - returnează data curentă a sistemului.
 DateAdd(interval, numar, data) – returnează o dată rezultată din
adăugarea unui interval la data specificată. Parametrul “interval”
poate avea valorile: yyyy – an, q – trimestru, m – lună, d – zi etc.
Exemple: DateAdd(„yyyy‟,3,#22/11/2003#) – returnează 22/11/2006
DateAdd(„m‟,5,#22/11/2003#) – returnează 22/04/2004

 DateDiff(interval, data1, data2) – returnează diferenţa dintre două


date calendaristice, bazate pe intervalul specificat.
Exemple: DateDiff(‘d’,#15/10/2003#,#22/11/2003#) – returnează 38

 Day(data) – returnează numărul de ordine al zilei lunii dintr-o


dată calendaristică. Exemplu Day(#15/10/2003) – returnează
15.
 Hour(data) – returnează ora dintr-o dată calendaristică.
 Month(data) - returnează luna dintr-o dată calendaristică.
 Now(data) – returnează data şi ora curentă a calculatorului pe care
lucraţi.
 Time() – returnează ora calculatorului dumneavoastră.
 Year(data) – returnează anul dintr-o dată calendaristică.

Alte funcţii de dată şi sintaxa lor puteţi găsi în documentaţia SGBDR pe


care îl folosiţi.

136
Baze de date Capitolul 4

Gruparea datelor

Crearea grupurilor

Am văzut în paragraful precedent că funcţiile agregat din SQL pot fi


utilizate pentru a genera sumare de date. Aceasta vă permite să număraţi
liniile, să calculaţi sume şi medii, respectiv să obţineţi valorile cele mai
mari sau cele mai mici, fără necesitatea regăsirii tuturor datelor.

Toate calculele de până acum au fost efectuate asupra tuturor datelor dintr-
un tabel, sau asupra datelor ce corespundeau clauze WHERE specifice.
Dacă aţi dori să faceţi asemenea calcule asupra unor seturi logice se
înregistrări? Aici intervine gruparea datelor. De exemplu, gruparea
vânzărilor săptămânale după numele vânzătorului care le-a făcut.

Grupurile sunt create folosind clauza GROUP BY în instrucţiunea


SELECT. Modul cel mai simplu de a înţelege crearea şi utilitatea lor este
un exemplu practic. Presupunem că avem într-o bază de date un tabel în
care ţinem evidenţa produselor vândute de mai mulţi vânzători şi dorim la
un moment dat să vedem cât a vândut fiecare, pentru a face o analiză a
activităţii, nu-i aşa? Tabelul se numeşte tblProduse şi se vede în figura 4.5.

Cod_produs Cod_vinzator Denumire produs Pret produs


100001 MR-01 Acumulator 250
100345 KL-02 Capota fata 120
100037 MR-01 Set motor 356
100445 MR-01 Cauciuc R13 65
100090 PR-02 Ulei M30 50
100552 GH-04 Antigel 34 20

Fig. 4.5. Tabelul tblProduse

O înregistrare din acest tabel reprezintă o vânzare a unui produs, făcută de


un anumit vânzător. Ne propunem să aflăm câte vânzări a făcut fiecare
vânzător.

Expresie SQL:
SELECT Cod_vinzator, COUNT(*) AS Numar_vinzari
FROM tblProduse
GROUP BY Cod_vinzator;

137
Baze de date Capitolul 4
Rezultat:
Cod_vinzator Numar_vinzari
MR-01 3
KL-02 1
PR-02 1
GH-04 1

Clauza GROUP BY instruieşte sistemul de gestionare a bazei de date să


sorteze datele şi să le grupeze după coloana Cod_vinzator. În felul acesta,
numărul de vânzări va fi calculat câte o dată pentru fiecare vânzător în
parte. După cum se vede şi în rezultat, vânzătorul MR-01 a făcut 3 vânzări,
iar colegii săi, câte una.

Deoarece aţi folosit clauza GROUP BY, n-a trebuit să specificaţi fiecare
grup care trebuie evaluat şi calculat, acest lucru s-a făcut în mod automat.
Clauza GROUP BY instruieşte sistemul de gestionare a bazei de date să
grupeze datele şi apoi să aplice funcţia agregat fiecărui grup, nu asupra
întregului set de rezultate.

Iată câteva reguli pe care trebuie să le ştiţi despre utilizarea clauzei


GROUP BY:
 Clauzele GROUP BY pot conţine oricâte coloane doriţi. Asta vă
permite să imbricaţi grupuri, asigurându-vă mai mult control
asupra felului în care sunt grupate datele.
 Orice coloană enumerată în clauza GROUP BY trebuie să fie o
coloană originală sau o expresie validă (calculată, dar nu o funcţie
agregat). Dacă o expresie este utilizată în instrucţiunea SELECT,
aceeaşi expresie trebuie să fie specificată şi în clauza GROUP
BY. Nu pot fi folosite aliasuri.
 Dacă o coloană grupată conţine o linie cu o valoare NULL,
NULL va fi returnată ca grup. Deci, dacă există mai multe linii cu
valoarea NULL, ele vor fi grupate laolaltă, ceea ce este foarte
important din punct de vedere practic. De multe ori dorim să
vedem liniile cu valori nule pe o coloană, de exemplu, când
dorim să vedem integritatea datelor.
 Clauza GROUP BY trebuie plasată după toate clauzele WHERE
şi înainte de orice clauză ORDER BY.

138
Baze de date Capitolul 4
Filtrarea grupurilor

Pe lângă faptul că este capabil să grupeze datele folosind clauza GROUP


BY, limbajul SQL vă permite, de asemenea, să filtraţi grupurile pe care le
includeţi sau le excludeţi. De exemplu, dacă doriţi lista tuturor
cumpărătorilor care au emis minimum 2 comenzi, trebuie să efectuaţi o
filtrare bazată pe grupul complet, nu pe linii individuale.

După cum ştim clauza WHERE filtrează liniile întregului tabel, nu a unui
grup aşa cum am dori noi. Pentru filtrarea grupurilor, limbajul SQL ne
pune la dispoziţie clauza HAVING, care este foarte asemănătoare cu
clauza WHERE. Prin urmare, clauzele WHERE şi HAVING se ocupă de
acelaşi lucru, filtrare, singura diferenţă este că prima filtrează linii, iar a
doua grupuri.

Clauza HAVING acceptă toţi operatorii clauzei WHERE. Tot ce am


învăţat despre WHERE este valabil şi pentru HAVING.

Pentru a înţelege clauza HAVING, să reluăm exemplul precedent şi să


filtrăm numai acei vânzători care au făcut mai mult de 2 vânzări. Iată
cazul:

Expresie SQL:
SELECT Cod_vinzator, COUNT(*) AS Numar_vinzari
FROM tblProduse
GROUP BY Cod_vinzator
HAVING COUNT(*) > 2;

Rezultat:
Cod_vinzator Numar_vinzari
MR-01 3

Primele trei rânduri ale instrucţiunii SELECT sunt similare cu cele


anterioare, ultimul rând, însă, adaugă o clauză HAVING care filtrează
grupurile respective cu o clauză COUNT(*) > 2 – adică 3 sau mai multe
vânzări.

După cum se vede, clauza WHERE nu funcţionează în cazul acesta,


deoarece filtrarea se bazează pe valoarea agregată a grupului, nu valorile
unor linii specifice.

139
Baze de date Capitolul 4
De multe ori, în practică, apare necesitatea folosirii ambelor clauze, ceea ce
duce la mărirea vitezei de execuţie. În acest caz ordinea de execuţie ar fi
WHERE, GROUP BY şi HAVING. De exemplu, un caz real ar fi acela de
a vedea ce cumpărători au depus la noi mai mult de 2 comenzi în ultimele
12 luni. E clar că nu vom face grupuri din tot tabelul de cumpărători, ci
numai după ce i-am filtrat cu o clauză WHERE numai pe cei din ultimul
an. Încercaţi să concepeţi un astfel de tabel şi să-i aplicaţi expresia SQL
care să facă aceste lucruri.

Reţineţi că clauza HAVING se foloseşte numai în asociere cu clauza


GROUP BY. Pentru a nu confunda ordinea de folosire a clauzelor
instrucţiunii SELECT studiate până acum, iată această ordine:

SELECT
FROM
WHERE
GROUP BY
HAVING
ORDER BY

140
Baze de date Capitolul 4
Lucrul cu subselecţii

Instrucţiunile SELECT sunt interogări SQL. Toate instrucţiunile SELECT


de până acum, regăseau date din tabele izolate ale bazei de date. Limbajul
SQL vă permite, de asemenea, să creaţi subselecţii: interogări înglobate în
alte interogări. De ce ar fi nevoie de aşa ceva? Exemplele care vor urma vă
vor edifica asupra acestui lucru.

Presupunem că avem structura de tabele din figura 4.6.

tblDetaliiCom
tblComenzi
DetComID ChP
Nr_comanda ChP Nr_comanda ChE
DataCom ArticolID ChE
CumparatorID ChE PretArt
Cantitate

tblCumparatori
Fig. 4.6. Diagrama de relaţii
CumparatorID ChP
NumeCump
Oras

Se vede că avem 3 tabele, câte unul pentru cumpărători, comenzi şi detalii


comenzi, între care există relaţiile desenate. Pentru a înţelege mai bine
conceptul de subselecţii vom completa aceste tabele cu date. În figura 4.7
se văd aceste tabele.

141
Baze de date Capitolul 4

tblComenzi
ComandaID DataCom CumparatorID
10010 16.04.2005 6001
10011 16.04.2005 6083
10012 16.04.2005 6014
10013 16.04.2005 6025
10014 16.04.2005 6001
10015 20.04.2005 6083
10016 20.04.2005 6001
10017 20.04.2005 6014

tblDetaliiCom
DetComID ComandaID ArticolID PretArt Cantitate
20010 10010 1001 250.50 10
20011 10010 1002 115.00 12
20012 10011 1001 95.25 8
20013 10011 1052 65.00 50
20014 10012 1008 147.00 16

tblCumparatori
CumparatorID NumeCump Oras <<alte cimpuri>>
6001 ROMBAT SRL Tg. Mures ......
6002 AutoNET SRL Tg. Mures ......
6025 COMPACT SA Brasov ......
6083 ANCONA SA Sibiu ......
6014 SAVINA SRL Ludus ......

Fig. 4.7. Cele 3 tabele completate

Aceste 3 tabele fac parte dintr-o bază de date a unei firme de comerţ.
Cumpărătorii sunt firme, care comandă diferite articole produse de firma
noastră. În tabelul tblComenzi sunt ţinute comenzile, în tabelul
tblDetaliiCom sunt ţinute articolele tuturor comenzilor, iar în tabelul
tblCumparatori sunt stocaţi toţi cumpărătorii.

Ne propunem să aflăm toţi cumpărătorii care au comandat articolul 1001.


Cum procedăm? Iată paşii care trebuie urmaţi:
 Regăsiţi numele tuturor comenzilor ce conţin articolul 1001.
 Regăsiţi indicatorii tuturor cumpărătorilor care au comenzi cu
numerele returnate în pasul anterior.
142
Baze de date Capitolul 4
 Regăsiţi informaţiile despre cumpărători pentru toţi identificatorii
returnaţi în pasul anterior.

Fiecare dintre aceşti paşi poate fi executat de o interogare separată.


Procedând astfel, folosiţi datele returnate de o singură instrucţiune
SELECT pentru a popula clauza WHERE a următoarei instrucţiuni
SELECT.

Puteţi, de asemenea, să folosiţi subselecţii, care să combine cele 3


interogări într-o singură instrucţiune.

Pentru primul pas, instrucţiunea SELECT care afişează numărul


comenzilor care conţin articolul 1001, este evidentă, nu-i aşa?

Expresie SQL:
SELECT ComandaID
FROM tblDetaliiCom
WHERE ArticolID = „1001‟;

Rezultat:
ComandaID
..........
10010
10011

Urmăriţi instrucţiunea SQL şi verificaţi în tabelele din figura 4.7 dacă


rezultatele întoarse sunt corecte.

Următorul pas este să găsiţi identificatorii cumpărătorilor asociaţi cu


comenzile 10010 şi 10011. Iată cum trebuie să procedaţi:

Expresie SQL:
SELECT CumparatorID
FROM tblComenzi
WHERE ComandaID IN (10010, 10011);

Rezultat:
CumparatorID
..........
6001
6083

143
Baze de date Capitolul 4
Remarcaţi folosirea clauzei IN pe care aţi studiat-o puţin mai înainte.

Având indicatorii pentru cumpărătorii căutaţi, nu vă rămâne decât să


căutaţi cine sunt aceştia, în tabelul cu toţi cumpărătorii. Iată cum trebuie să
procedaţi:

Expresie SQL:
SELECT CumparatorID, NumeCump
FROM tblCumparatori
WHERE CumparatorID IN (6001, 6083);

Rezultat:
CumparatorID NumeCump
.......... .........
6001 ROMBAT SRL
6083 ANCONA SA

V-aţi descurcat foarte bine până aici, dar nu cred că sunteţi mulţumiţi cu
această metodă „băbească” de găsi informaţiile dorite. Aţi observat cum s-
au transferat rezultatele unei interogări în parametrii altei interogări.
Soluţia este să încercaţi să uniţi aceste 3 interogări într-una singură. Iată
această cale:

Expresie SQL:
SELECT CumparatorID, NumeCump
FROM tblCumparatori
WHERE CumparatorID IN (SELECT CumparatorID
FROM tblComenzi
WHERE ComandaID IN (SELECT ComandaID
FROM tblDetaliiCom
WHERE ArticolID =
„1001‟));

Rezultat:
CumparatorID NumeCump
.......... .........
6001 ROMBAT SRL
6083 ANCONA SA

Rezultatul obţinut este identic cu cel obţinut pas cu pas, dar aici aţi folosit
o singură expresie SQL. Observaţi că pentru a putea citi şi înţelege mai

144
Baze de date Capitolul 4
bine această expresie am grupat-o într-un anume fel. Este o idee bună, mai
ales atunci când expresiile pe care le folosiţi sunt complicate.

O altă modalitate de utilizare a subselecţiilor este crearea de câmpuri


calculate. Să presupunem că doriţi să afişaţi numărul total al comenzilor
emise de fiecare cumpărător din tabelul tblCumparatori. Ştim că aceste
comenzi sunt stocate în tabelul tblComenzi, împreună cu identificatorii
cumpărătorilor.

Pentru a efectua această operaţie, trebuie efectuaţi următorii paşi:


 Regăsiţi lista cumpărătorilor din tabelul tblCumparatori.
 Pentru fiecare cumpărător regăsit, număraţi comenzile asociate în
tabelul tblComenzi.

Iată cum trebuie procedat (tabelele sunt cele din figura 4.7):

Expresie SQL:
SELECT NumeCump, Oras, (SELECT COUNT(*) FROM tblComenzi AS C
WHERE C.CumparatorID=tblCumparatori.CumparatorID)
AS Comenzi
FROM tblCumparatori
ORDER BY NumeCump;

Remarcaţi utilizarea aliasului C pentru tabelul tblComenzi pentru a


simplifica scrierea expresiei clauzei WHERE.

Rezultat:
NumeCump Oras Comenzi
.......... ......... ........
ANCONA SA Tg. Mures 2
AutoNET SRL Tg. Mures 0
COMPACT SA Brasov 1
ROMBAT SRL Bistrita 3
SAVINA SRL Ludus 2

Deşi subselecţiile sunt foarte utile în construirea acestui tip de instrucţiune


SELECT, trebuie avut grijă în privinţa identificării corecte a coloanelor
implicate, ştiind că sunt coloane cu acelaşi nume care apar în tabele
diferite. Aceste coloane se identifică corect dacă înaintea numelui se pune

145
Baze de date Capitolul 4
numele tabelului din care face parte, ca de exemplu,
tblComenzi.CumparatorID sau tblCumparatori.CumpatatorID. Se vede
clar că câmpul CumparatorID face parte din două tabele.

Reţineţi această regulă pentru că o s-o folosiţi de multe ori!

146
Baze de date Capitolul 4
Unirea tabelelor

Una din caracteristicile extrem de puternice din limbajul SQL este


capacitatea de a uni tabele din mers, în interogările de regăsire a datelor.
Unirile constituie unele dintre cele mai importante operaţii pe care le puteţi
efectua folosind instrucţiunile SELECT, şi o bună înţelegere a lor şi a
sintaxei pentru unire reprezintă o parte esenţială din învăţarea limbajului
SQL.

Ceea ce aţi învăţat în capitolele anterioare despre chei, relaţii, diagrame


sunt acum hotărâtoare pentru construirea corectă a expresiilor SQL.

Ca definiţie simplă, unirea este un mecanism folosit pentru asocierea


tabelelor într-o instrucţiune SELECT. Utilizând o sintaxă specială, mai
multe tabele pot fi unite astfel încât să fie returnat un singur set de
rezultate, iar unirea asociază din mers liniile corectate din fiecare tabel.

Crearea unei uniri simple

Crearea unei uniri este foarte simplă. În exemplul următor, vom uni două
tabele tblProduse şi tblVinzatori, al cărui rezultat este produsul cartezian al
acestora, având un număr de înregistrări egal cu produsul numerelor
acestora (figura 4.8).

tblProduse
ProdusID VinzatorID DenumireProdus PretProdus
1001 V01 Piine 2.00
1002 V03 Banane 2.50
1003 V01 Biscuiti 1.25

tblVinzatori
VinzatorID NumeVinzator OrasVinzator <<alte cimpuri>>
V01 Ban Lucia Naoiu ......
V02 Pop Mariana Sarmasel ......

Fig. 4.8. Tabelele pentru unire

Unirea celor două tabele cu o expresie SQL va genera un nou tabel cu 6


înregistrări (3 x 2).

147
Baze de date Capitolul 4
Expresia SQL:
SELECT NumeVinzator, DenumireProdus, PretProdus
FROM tblVinzatori, tblProduse;

Rezultat:

NumeVinzator DenumireProdus PretProdus


Ban Lucia Piine 2.00
Ban Lucia Banane 2.50
Ban Lucia Biscuiti 1.25
Pop Mariana Piine 2.00
Pop Mariana Banane 2.50
Pop Mariana Biscuiti 1.25

Acest tip de unire nu se foloseşte niciodată sub această formă, deoarece nu


are nici un sens. Aici nu s-a pus nici un fel de condiţie, nici o legătură între
cele două tabele. Adevărata unire este cea când se fac legături între tabele,
aşa cum se vede mai departe.

Expresia SQL:
SELECT NumeVinzator, DenumireProdus, PretProdus
FROM tblVinzatori, tblProduse;
WHERE tblVinzatiri.VinzatorID=tblProduse.VinzatorID;

Rezultat:

NumeVinzator DenumireProdus PretProdus


Ban Lucia Piine 2.00
Ban Lucia Biscuiti 1.25

Ce s-a întâmplat de fapt? Clauza WHERE a filtrat înregistrările produsului


cartezian, rezultând numai 2 înregistrări.

Acest tip de uniri, bazate pe verificarea egalităţii dintre două tabele, se mai
numesc şi uniri interioare. Unele SGBGR-uri au sintaxe diferite,
specificând explicit tipul de unire. Studiaţi cu atenţie documentaţia
SGBDR-ului cu care lucraţi pentru a-i folosi corect sintaxa.

148
Baze de date Capitolul 4
O altă variantă de unire este cea făcută în clauza FROM prin folosirea
clauzei speciale INNER JOIN ... ON, după cum se vede mai jos:
SELECT NumeVinzator, DenumireProdus, PretProdus
FROM tblVinzatori INNER JOIN tblProduse
ON tblVinzatiri.VinzatorID=tblProduse.VinzatorID;

Această variantă este preferată de programatori, dar ea este şi cea indicată


de specificaţiile SQL.

149
Baze de date Capitolul 4

Uniri avansate

Limbajul SQL nu impune limite asupra numărului de tabele ce pot fi unite


într-o instrucţiune SELECT. Regulile de bază pentru crearea unei uniri
rămân aceleaşi. În primul rând, enumeraţi toate tabelele, apoi definiţi
relaţiile dintre ele. Iată un exemplu:
tblProduse
ProdusID VinzatorID DenumireProdus PretProdus DescriereProdus
1001 V01 Piine 2.00
1002 V03 Inghetata 1.25
1003 V01 Biscuiti 0.25
1004 V01 Ciocolata 2.65
1052 V02 Bricheta 0.35
1078 V03 Banane 2.50

tblDetaliiComenzi
DetComID ComandaID ProdusID Cantitate
20010 10010 1001 10
20011 10010 1002 12
20012 10010 1078 8
20013 10010 1052 50
20014 10012 1008 16

tblVinzatori
VinzatorID NumeVinzator Oras <<alte cimpuri>>
V01 Ban Lucia Naoiu ......
V02 Pop Mariana Sarmasel ......
V03 Baciu Mia Naoiu ......
V04 Ban Ionel Roma ......

Fig. 4.9. Tabele implicate în unire

Ne propunem să aplicăm unirea într-un caz concret de regăsire a unor


informaţii care se găsesc în trei tabele. Căutăm produsele care compun
comanda 10010, precum şi vânzătorul asociat. Studiaţi expresia SQL care
urmează şi verificaţi rezultatul obţinut.

Expresie SQL:
SELECT DenumireProdus, NumeVinzator, PretProdus, Cantitate
FROM tblProduse, tblDetaliiCom, tblVinzatori
WHERE tblDetaliiComenzi.ProdusID=tblProduse.ProdusID

150
Baze de date Capitolul 4
AND tblProduse.VinzatorID=tblVinzatori.VinzatorID
AND ComandaID= „10010‟;

Rezultat:
DenumireProdus NumeVinzator PretProdus Cantitate
Piine Ban Lucia 2.00 10
Inghetata Baciu Mia 1.25 12
Banane Ban Lucia 2.50 8
Bricheta Pop Mariana 0.35 50

Primele două rânduri ale clauzei WHERE fac legătura între perechile de
tabele tblDetaliiComenzi-tblProduse şi tblProduse-tblVinzatori, iar al
treilea filtrează doar produsele pentru comanda 10010.

Iată câteva aspecte esenţiale legate de uniri şi folosirea lor:


 Consultaţi-vă documentaţia sistemului de gestionare a bazei de
date, pentru a afla sintaxa exactă a unirii pe care o acceptă.
 Asiguraţi-vă că utilizaţi condiţia corectă de unire, indiferent de
sintaxa folosită, altfel vor fi returnate date incorecte.
 Asiguraţi-vă că prevedeţi întotdeauna o condiţie de unire, altfel
veţi sfârşi cu un produs cartezian.
 Într-o unire, puteţi include mai multe tabele, ba chiar să aveţi
tipuri diferite de unire pentru fiecare. Deşi metoda este corectă şi
adesea utilă, asiguraţi-vă că testaţi separat fiecare unire, înainte de
a le testa împreună. În felul acesta depanările vor fi mult
simplificate.
 O metodă bună este folosirea aliasurilor pentru tabele, pentru a
simplifica scrierea expresiilor SQL.

Compunerea interogărilor

Interogarea bazelor de date este chiar sensul existenţei lor. Nimeni n-a
creat vreo bază de date fără să o interogheze cândva, când se adună
suficiente date în ea. Până acum noi am făcut interogări folosind o singură
instrucţiune SELECT, care returna date din unul sau mai multe tabele.
Limbajul SQL vă permite să efectuaţi mai multe interogări (mai multe
151
Baze de date Capitolul 4
instrucţiuni SELECT) şi să returnaţi rezultatele sub forma unui singur set
de rezultate de interogare. De obicei, aceste interogări sunt cunoscute drept
reuniuni sau interogări compuse.

În esenţă, există două situaţii generale în care să folosiţi interogările


compuse:
 Pentru a returna date structurate similar din tabele diferite, într-o
singură interogare.
 Pentru a efectua mai multe interogări asupra unui singur tabel,
returnând datele ca o singură interogare.

Pentru a compune interogările SQL se foloseşte operatorul UNION. Cu


ajutorul lui pot fi specificate instrucţiuni SELECT multiple, iar rezultatele
acestora pot fi combinate într-un singur set de rezultate.

Folosirea operatorului UNION este destul de simplă, tot ce aveţi de făcut


este să specificaţi toate instrucţiunile SELECT şi să plasaţi între ele
cuvântul cheie UNION.

Să luăm un exemplu. Presupunem că trebuie să întocmiţi un raport despre


toţi cumpărătorii din judeţele Bistriţa-Năsăud, Braşov şi Cluj. În acelaşi
raport doriţi să includeţi toate locaţiile firmei ANCONA SA, indiferent în
ce judeţ s-ar afla ele. Desigur, se poate crea o clauza WHERE care să
realizeze acest lucru, dar acum veţi folosi operatorul UNION. Figura 4.10
conţine tabelul cu cumpărătorii, care o să fie folosit în acest exemplu.

CumparatorID NumeCumparator JudCump PersContact Email


6001 ROMBAT SA BN Pop Petru ppop@rmbat.ro
6002 AutoNET SRL MS Beldean Vian bvian@auto.ro
6004 SAVINA SRL MS Parauan Bicu pbicu@savina.ro
6025 COMPACT SRL BV Pietroi Sorina sorina@yahoo.ro
6083 ANCONA SA MS Palade Sorin sorin@ancona.ro
6084 ANCONA SA CJ Crisan Ovidiu covi@ancona.ro

Fig. 4.10. Tabelul tblCumparatori

După cum ştiţi deja, folosirea operatorului UNION implică scrierea mai
multor instrucţiuni SELECT, de aceea veţi crea mai întâi fiecare
instrucţiune SELECT, apoi le veţi compune.

152
Baze de date Capitolul 4
Prima instrucţiune SELECT va căuta cumpărătorii din cele 3 judeţe
amintite.

Expresie SQL:
SELECT NumeCumparator, JudCump, PersContact, Email
FROM tblCumparatori
WHERE JudetCumparator IN ('BN', 'BV','CJ');

Rezultat:
NumeCumparator JudCump PersContact Email
ROMBAT SA BN Pop Petru ppop@rmbat.ro
COMPACT SRL BV Pietroi Sorina sorina@yahoo.ro
ANCONA SA CJ Crisan Ovidiu covi@ancona.ro

A doua instrucţiune SELECT va căuta toate locaţiile firmei ANCONA SA.

Expresie SQL:
SELECT NumeCumparator, JudCump, PersContact, Email
FROM tblCumparatori
WHERE NumeCumparator= 'ANCONA SA';

Rezultat:
NumeCumparator JudCump PersContact Email
ANCONA SA MS Palade Sorin sorin@ancona.ro
ANCONA SA CJ Crisan Ovidiu covi@ancona.ro

După cum se vede, există două locaţii pentru firma ANCONA SA, una în
judeţul Mureş şi una în judeţul Cluj.

Pentru a compune cele 2 interogări veţi proceda astfel:

Expresie SQL:
SELECT NumeCumparator,JudCump, PersContact, Email
FROM tblCumparatori
WHERE JudetCumparator IN ('BN', 'BV','CJ')
UNION
SELECT NumeCumparator, JudCump, PersContact, Email
FROM tblCumparatori
WHERE NumeCumparator= 'ANCONA SA';

153
Baze de date Capitolul 4
Rezultat:
NumeCumparator JudCump PersContact Email
ROMBAT SA BN Pop Petru ppop@rmbat.ro
COMPACT SRL BV Pietroi Sorina sorina@yahoo.ro
ANCONA SA CJ Crisan Ovidiu covi@ancona.ro
ANCONA SA MS Palade Sorin sorin@ancona.ro

Deoarece ANCONA SA se găseşte în ambele interogări, SQL nu îl scrie de


două ori. Dacă totuşi, dorim să apară şi dublurile, atunci vom folosi clauza
UNION ALL. Fără extensia ALL, duplicatele se elimină automat.

Dacă dorim ca rezultatele să fie sortate, vom adăuga clauza ORDER BY


după ultima clauză WHERE. De remarcat, că operaţiile UNION acceptă o
singură clauză ORDER BY, după ultima instrucţiune SELECT. Iată cum
arată o expresie SQL cu afişarea tuturor înregistrărilor care sunt şi
ordonate:

Expresie SQL:
SELECT NumeCumparator, PersContact, Email
FROM tblCumparatori
WHERE JudetCumparator IN ('BN', 'BV','CJ')
UNION ALL
SELECT NumeCumparator, PersContact, Email
FROM tblCumparatori
WHERE NumeCumparator= 'ANCONA SA'
ORDER BY NumeCumparator;

Rezultat:
NumeCumparator JudCump PersContact Email
ANCONA SA CJ Crisan Ovidiu covi@ancona.ro
ANCONA SA CJ Crisan Ovidiu covi@ancona.ro
ANCONA SA MS Palade Sorin sorin@ancona.ro
COMPACT SRL BV Pietroi Sorina sorina@yahoo.ro
ROMBAT SA BN Pop Petru ppop@rmbat.ro

Observaţi înregistrarea dublă ANCONA SA, care apare din cauza


operatorului UNION ALL.

Iată câteva reguli pentru operaţii cu operatorul UNION:


 Toate interogările dintr-o operaţie UNION trebuie să conţină
aceleaşi coloane, expresii sau funcţii agregat.

154
Baze de date Capitolul 4
 Coloanele, expresiile şi funcţiile agregat trebuie să apară exact în
aceeaşi ordine în fiecare instrucţiune SELECT din operaţia
UNION.
 Tipurile de date din coloane trebuie să fie compatibile. Nu este
necesar ca datele să fie exact de acelaşi tip, dar trebuie să fie de
un tip pe care SGBDR-ul îl poate transforma implicit (de
exemplu tipuri de date numerice diferite sau tipuri de date
calendaristice diferite).

Inserarea, actualizarea şi ştergerea datelor

Datele unei baze de date trebuie periodic actualizate, pentru a reflecta


activităţile unei firme sau organizaţii. Întreţinerea datelor este o activitate
continuă, plină de responsabilitate, fără de care, utilitatea bazei de date este
îndoielnică. Limbajul SQL oferă instrucţiuni dedicate întreţinerii datelor
unei baze.

Întreţinerea unei baze de date constă, de fapt, în introducerea de noi date,


modificarea unor date existente sau ştergerea datelor din tabelele acesteia.
Toate aceste operaţii o să le învăţaţi în cele ce urmează.

Inserarea datelor se face cu instrucţiunea INSERT

Inserarea datelor

Toate expresiile SQL de până acum începeau cu instrucţiunea SELECT. Pe


lângă aceasta, mai sunt alte 4 instrucţiuni pe care le vom învăţa în
continuare. Acestea sunt INSERT, UPDATE, DELETE şi CREATE
TABLE.

Prima dintre ele este instrucţiunea INSERT, folosită pentru inserarea de


linii (înregistrări) într-un tabel de bază de date. Inserarea se poate face în
mai multe moduri:
 Inserarea unei singure linii complete;
 Inserarea unei singure linii parţiale;
 Inserarea rezultatelor unei interogări.

Le vom studia pe rând.

155
Baze de date Capitolul 4
Inserarea unei linii complete.

Cel mai simplu mod de a insera o linie într-un tabel este folosirea sintaxei
de bază a instrucţiunii INSERT, care cere numele tabelului şi valorile care
vor fi inserate în noua linie. Iată un exemplu:
INSERT INTO tblProduse ( ProdusID, CodProdus, Denumire, UM, Pret, Observatii )
VALUES ('32', '20033', 'Cafea_Jacobs', 'kg', '12.23', 'Conform normelor UE');

Această expresie SQL, inserează în tabelul tblProduse un rând cu valorile


prezentate în paranteza de după VALUES. Valorile corespund, în ordine, cu
denumirile câmpurilor din prima paranteză a expresiei SQL, indiferent de
ordinea în care apar în tabel. Dacă numărul coloanelor indicate nu este
acelaşi cu numărul valorilor, se va produce un mesaj de eroare care
precizează acest lucru.

Inserarea unei singure linii parţiale.

Există cazuri în care nu este nevoie să se completeze toate câmpurile unei


înregistrări, fie că nu se cunosc valorile în acel moment, fie că nu e
necesară valoarea acelui câmp pentru înregistrarea respectivă. În acest caz,
se completează numai acele câmpuri pentru care există valori. Este de la
sine înţeles că prin proiectarea bazei de date, este prevăzut că acele
câmpuri necompletate au voie să aibă valori nule.

Din exemplul anterior, se poate scoate câmpul Observatii care nu este


obligatoriu. Expresia SQL va arăta astfel:
INSERT INTO tblProduse ( ProdusID, CodProdus, Denumire, UM, Pret)
VALUES ('32', '20033', 'Cafea_Jacobs', 'kg', '12.23');

Deci, câmpul Observatii şi valoarea corespunzătoare nu apar în expresia


SQL.

Inserarea rezultatelor unei interogări.

Inserarea într-un tabel a unei singure înregistrări, complete sau parţiale,


este o acţiune obişnuită, de rutină, utilizată de obicei de administratorul
bazei de date pentru completări minore ale unui tabel. Cele mai
spectaculoase completări ale tabelelor sunt cele cu înregistrări provenite
din interogări ale altor tabele.

156
Baze de date Capitolul 4
Aceste inserări se pot face manual de către administratorul bazei de date,
dar cel mai probabil mod de a insera într-un tabel înregistrările provenite
dintr-o interogare, este folosirea limbajului VBA, în cadrul unor aplicaţii
integrate.

Această formă de instrucţiune INSERT, care poate fi utilizată pentru a


insera rezultatul unei instrucţiuni SELECT se numeşte INSERT SELECT,
fiind alcătuită dintr-o instrucţiune INSERT şi o instrucţiune SELECT. Să
presupunem că aveţi într-o bază de date un tabel numit tblClienti care
conţine clienţii unei firme. Pentru a adăuga noi clienţi, în practică se
procedează astfel: nu toţi clienţii se introduc direct în tabel, ci mai întâi se
introduc într-un tabel temporar, apoi se decide care sunt clienţii care merită
introduşi în baza de date şi numai atunci, se introduc în tabelul tblClienti.

Această expresie SQL este prezentată mai jos:


INSERT INTO tblClienti (ClientID, Denumire, CodFiscal, PersoanaContact, Adresa)
SELECT (ClientID, Denumire, CodFiscal, PersoanaContact, Adresa)
FROM tblClientiNoi;

După cum se vede, tabelul tblClienti este completat cu înregistrări din


tabelul tblClientiNoi, dar pot fi şi alte surse de interogare. Totul este ca
numărul de câmpuri şi tipul lor de dată să coincidă.

Actualizarea datelor

Datele unei baze de date suferă dese modificări. Cum datele se găsesc în
tabele, este nevoie ca aceste tabele să fie periodic actualizate. Ca să
modificaţi datele dintr-un tabel, trebuie să folosiţi instrucţiunea UPDATE.
Ea poate fi folosită în două moduri:
 Pentru actualizarea numai a anumitor linii dintr-un tabel;
 Pentru actualizarea tuturor liniilor unui tabel.

Instrucţiunea UPDATE folosită defectuos, poate să vă producă mari


neplăceri, ştiut fiind că aici nu există posibilitatea de revenire în sensul
„undo”. Prin urmare trebuie să fiţi foarte atenţi la folosirea ei. De altfel,
unele sisteme de gestiune a bazelor de date au restricţii de securitate pentru
a împiedica unele acţiuni greşite asupra bazei de date.

Instrucţiunea UPDATE este foarte simplu de utilizat. Sintaxa ei este


alcătuită din 3 părţi:

157
Baze de date Capitolul 4
 Tabelul care trebuie actualizat;
 Numele coloanelor şi noile lor valori;
 Condiţia filtru care determină liniile care trebuie actualizate.

Să examinăm un caz banal. Clientul cu codul 1000245, are acum adresă de


e-mail şi ar trebui să apară şi tabelul cu clienţii, numit tblClienti. Expresia
SQL care efectuează această actualizare este următoarea:
UPDATE tblClienti
SET E_mail = ‘alfaroom@yahoo.com’
WHERE ClientID = ’1000245’;

Este de la sine înţeles că cele 2 câmpuri (E_mail şi ClientID) sunt câmpuri


ale tabelului tblClienti.

Instrucţiunea UPDATE începe întotdeauna cu numele tabelului care este


actualizat (aici tblClienti). Urmează comanda SET, care atribuie noua
valoare unei coloane (aici coloana E_mail).

Instrucţiunea UPDATE se termină cu o clauză WHERE, care anunţă


sistemul de gestionare a bazei de date ce linie să actualizeze. Atenţie, fără
clauza WHERE sistemul ar actualiza toate liniile din tabelul tblClienti,
punând adresa de e-mail ‘alfaroom@yahoo.com’ la toţi clienţii, ceea ce ar fi un
lucru inadmisibil.

Actualizarea mai multor coloane necesită a sintaxă corespunzătoare cum se


poate vedea mai jos:
UPDATE tblClienti
SET E_mail = ‘alfaroom@yahoo.com’, PersoanaContact = ‘Mocian Ioan’
WHERE ClientID = ’1000245’;

Din această expresie SQL se pot deduce următoarele:


 Perechile de câmpuri şi valorile lor (între ele este semnul = ) se
despart prin virgulă;
 Avem atâtea egaluri câte câmpuri trebuie actualizate;
 Înregistrarea care trebuie actualizată este identificată cu câmpul
ClientID, care este cheie primară în tabelul tblClienti, vă mai
amintiţi desigur ea.

158
Baze de date Capitolul 4
Pentru a şterge valoarea unei coloane, tehnica este ca acea coloană să fie
setată pe valoarea NULL (condiţia este ca acel câmp să accepte valoarea
NULL). Iată expresia SQL care face acest lucru:
UPDATE tblClienti
SET E_mail = NULL
WHERE ClientID = ’1000245’;

Această expresie SQL, şterge adresa de e-mail a clientului 1000245.

Mai târziu, în capitolul 5 veţi putea face teste şi simulări cu actualizări de


date pe o bază de date de test.

Ştergerea datelor

Pentru a şterge linii dintr-un tabel, necesitate practică frecventă, se


foloseşte instrucţiunea DELETE. Ea poate fi utilizată în două modalităţi:
 Pentru ştergerea numai a anumitor linii dintr-un tabel;
 Pentru ştergerea tuturor liniilor unui tabel.

Deşi este o necesitate practică, folosirea instrucţiunii DELETE antrenează


mari riscuri, de aceea este bine să faceţi teste pe o copie a unei baze de
date. Oricum, ca începători nu vă va pune nimeni să „curăţaţi” tabelele
unei baze de date reale de înregistrările inutile.

Să presupunem că printre clienţi, există câţiva care şi-au închis firma, deci
nu mai e necesar să-i avem în tabelul tblClienti, aşa că trebuie să-i ştergem
din tabel. De exemplu, clientul cu codul 1000378 trebuie şters din tabel.
Expresia SQL care face acest lucru este următoarea:

DELETE FROM tblClienti


WHERE ClientID = ’1000378’;

Această expresie SQL ar trebui înţeleasă imediat, pentru că e foarte clară:


din tabelul tblClienti se şterge clientul care are câmpul ClientID la valoarea
1000378.

De remarcat faptul că instrucţiunea DELETE nu conţine nume de coloane,


ea şterge linii întregi, nu coloane. Pentru a şterge valorile din anumite
coloane veţi folosi instrucţiunea UPDATE, prezentată puţin mai înainte.

159
Baze de date Capitolul 4
De asemenea, instrucţiunea DELETE nu şterge tabele, ci numai înregistrări
din tabele. Chiar dacă şterge toate înregistrările unui tabel, aceste rămâne,
dar va fi gol.

Aţi văzut cum se poate şterge dintr-un tabel o înregistrare. Întrebarea


firească este cum se pot şterge dintr-un tabel toate înregistrările. Şi aici, ca
în orice acţiune de distrugere, este foarte simplu: trebuie eliminată clauza
WHERE. Iată ce simplu puteţi „scăpa” de înregistrările unui tabel:
DELETE FROM tblClienti ;

Luaţi-vă măsurile de precauţie când lucraţi cu această instrucţiune!

Principii privind actualizarea şi ştergerea datelor

După cum spuneam, instrucţiunile UPDATE şi DELETE sunt instrucţiuni,


pe cât de utile, pe atât de periculoase. Trebuie să reţineţi faptul că în SQL
nu există un buton Undo, de anulare a unei operaţiuni greşite, de aceea fiţi
foarte atenţi când folosiţi aceste 2 instrucţiuni.

În sinteză, iată câteva principii pe care trebuie să le respectaţi, ca utilizator


al limbajului SQL:
 Nu executaţi niciodată instrucţiunile UPDATE şi DELETE fără o
clauză WHERE, decât atunci când doriţi să realmente să
actualizaţi sau să ştergeţi toate liniile unui tabel;
 Asiguraţi-vă că toate tabelele au o cheie primară (dacă aţi uitat ce
este aceasta, consultaţi capitolul respectiv) pe care să o folosiţi
într-o clauză WHERE;
 Înainte de a folosi o clauză WHERE cu instrucţiunile UPDATE
sau DELETE, testaţi-o mai întâi cu o instrucţiune SELECT, ca să
vă asiguraţi că filtrează înregistrările corecte – din cauză că la
clauza WHERE puteţi greşi destul de uşor.
 Folosiţi integritatea referenţială (vezi paragraful Integritatea la
nivel de relaţie) impusă bazelor de date astfel ca sistemul de
gestiune al bazelor de date (SGBD) să nu permită ştergerea
liniilor care au date în alte tabele asociate lor.
 Unele SGBD-uri permit administratorilor de baze de date să
impună limitări ce împiedică executarea instrucţiunilor UPDATE
şi DELETE fără o clauză WHERE.

160
Baze de date Capitolul 4
 Nu vă apucaţi să executaţi operaţiuni de actualizare sau ştergere,
înainte să faceţi o copie de siguranţă a bazei de date. Veţi fi astfel
mai relaxaţi, iar în caz de o manevră greşită (oameni suntem,
nu?), puteţi reveni la ce a fost, fără nici o problemă.
 Nu executaţi operaţii de ştergere printre „alte activităţi” pentru că
aici aveţi nevoie de concentrare maximă (amintiţi-vă că aici nu
este Undo şi „ce aţi făcut, făcut rămâne”).

Respectaţi aceste câteva principii enumerate, care vă ajută mult, gândindu-


vă că oricâte lucruri bune aţi face în firma la care lucraţi ca administrator
de baze de date, o greşeală ca ştergerea completă a unor tabele sau câmpuri
vă descalifică definitiv în ochii celor care vă plătesc.

161
Baze de date Capitolul 4
Crearea şi manipularea tabelelor

Limbajul SQL nu este folosit numai pentru manipularea datelor. Cu


ajutorul limbajului SQL se pot crea, modifica şi şterge tabele, chiar dacă
toate SGBD-urile au propriile unelte pentru aceste acţiuni.

În general, există două modalităţi de creare a tabelelor de baze de date:


 Majoritatea SGBD-urilor deţine propriul instrument de
gestionare, folosit şi la crearea şi administrarea interactivă a
tabelelor bazei de date.
 Tabelele pot fi create, de asemenea, în mod direct, prin
intermediul instrucţiunilor SQL.

Instrucţiunea de creare a tabelelor cu limbajul SQL este CREATE TABLE.


Trebuie menţionat faptul că atunci când folosim instrumente interactive, de
fapt folosim instrucţiuni SQL care sunt generate şi executate de sistem,
fără să ne dăm seama pentru că totul se face „în spatele” interfeţei.

Pentru a crea un tabel folosind instrucţiunea CREATE TABLE, trebuie


specificate următoarele informaţii:
 Numele noului tabel, specificat după cuvântul cheie CREATE
TABLE;
 Numele şi definirea coloanelor din tabel, separate prin virgulă;

Iată cum arată o expresie SQL de creare a unui tabel (în Access):
CREATE TABLE tblProduse
(
ProdusID Integer NOT NULL,
CodProdus Text(50) NOT NULL,
Denumire Text(80) NOT NULL,
UM Text(10) NOT NULL,
PretUnitar Number NOT NULL,
Observatii Text(255)

);

După cum se vede, instrucţiunea de mai sus creează tabelul tblProduse


care are 6 câmpuri, despărţite prin virgule. Observaţi tipurile de date

162
Baze de date Capitolul 4
folosite, întreg, text şi număr real (Number). De asemenea, pentru a
specifica faptul că un câmp cere valoare obligatorie trebuie pusă expresia
NOT NULL, iar dacă lipseşte se consideră că s-a pus NULL, adică acel
câmp poate să rămână necompletat. Din cele 6 câmpuri, numai Observatii
nu este obligatoriu de completat.

Între numele coloanei, tipul de dată şi cuvântul cheie NOT NULL se pune
spaţiu. Modul de aranjare a expresiei SQL nu este important, deoarece
spaţiile suplimentare sunt ignorate, se poate folosi un singur rând pentru
definirea tuturor coloanelor sau se pot aranja pe mai multe rânduri ca în
exemplul prezentat mai înainte, pentru lizibilitate.

Numele tabelului care se creează nu trebuie să existe în baza de date, dacă


există se va produce un mesaj de eroare care indică acest lucru.

Adăugarea unei coloane. De multe ori în practică apare necesitatea


adăugării unei coloane la un tabel care a fost creat şi care are chiar date.
Limbajul SQL ne pune la dispoziţie o instrucţiune pentru a face acest lucru,
numită ALTER TABLE şi clauza ADD. Iată un exemplu de folosire a
acestei instrucţiuni:
ALTER TABLE tblProduse
ADD Furnizor Text(50);

Această expresie SQL adaugă tabelului tblProduse coloana Furnizor.

Ştergerea unei coloane. Dacă diagrama de relaţii permite, adică acel câmp
nu este implicat în vreo relaţie, coloana (câmpul) poate fi ştearsă dintr-un
tabel. Această manevră se face cu ajutorul instrucţiunii ALTER TABLE şi
clauza DROP COLUMN. Iată un exemplu de folosire a acestei
instrucţiuni:
ALTER TABLE tblProduse
DROP COLUMN Furnizor;

Această expresie SQL şterge din tabelul tblProduse coloana Furnizor.

Ştergerea unui tabel. Aşa cum se poate crea un tabel într-o bază de date
cu ajutorul limbajului SQL, tot aşa se poate şi înlătura un tabel din baza de
date. Operaţiunea este foarte simplă, chiar periculos de simplă.

Astfel, pentru a elimina din baza de date tabelul tblProduse folosim


expresia SQL următoare:
163
Baze de date Capitolul 4
DROP TABLE tblProduse;

Operaţiunea nu este însoţită de nici un mesaj, nu poate fi anulată, tabelul


rămânând şters definitiv, aşa că trebuie să fiţi extrem de precauţi când
faceţi o astfel de manevră.

Elemente performante ale limbajului SQL


Ceea ce am studiat până acum se încadrează în nivelul propus pentru acest
curs, însă limbajul SQL nu şi-a terminat posibilităţile, oferind
programatorilor profesionişti elemente cu adevărat performante. În acest
capitol vor fi prezentate, pe scurt, aceste elemente de performanţă fără a
intra în amănunte de ordin tehnic.

În continuare vor fi prezentate aceste posibilităţi avansate ale limbajului


SQL.

Proceduri stocate. Instrucţiunile SQL folosite până acum sunt simple,


deoarece folosesc o singură instrucţiune aplicată unuia sau mai multor
tabele. Însă, nu toate operaţiile sunt atât de simple, adesea sunt necesare
mai multe instrucţiuni.

Iată un caz de operaţie complexă:


 Pentru a onora o comandă trebuie mai întâi să vedem dacă avem
în stoc articolele respective;
 Dacă există, ele trebuie trecute pe o listă rezervată şi scăzute din
stoc pentru a nu fi vândute altor cumpărători;
 Articolele care nu există în stoc şi sunt cerute de comandă,
trebuie trecute pe o listă pentru a fi aprovizionate;
 Cumpărătorul trebuie anunţat asupra articolelor existente în stoc
(adică livrabile imediat) şi asupra celor care urmează să fie
aprovizionate.

Scenariul prezentat necesită mai multe instrucţiuni SQL adresate mai


multor tabele. În plus, instrucţiunile SQL trebuie efectuate într-o anumită
ordine, iar ordinea depinde de existenţa produselor în stoc (dacă există, nu
mai trebuie comandate).

164
Baze de date Capitolul 4
Cum trebuie scrise aceste instrucţiuni? Am putea să scriem individual
fiecare instrucţiune SQL, apoi pe baza rezultatului să executăm alte
instrucţiuni condiţionate. Acţiunea ar trebui repetată pentru fiecare
comandă, iar persoana care face acest lucru trebuie să aibă cunoştinţe şi
experienţă corespunzătoare.

Acelaşi lucru se poate face printr-o procedură stocată. Procedurile stocate


nu sunt altceva decât seturi de una sau mai multe instrucţiuni SQL salvate
pentru o viitoare folosire.

De ce trebuie folosite procedurile stocate? Iată câteva din motive:


 Pentru a simplifica operaţiile complexe (ca cea prezentată ma
înainte), prin înglobarea proceselor într-o singură unitate, uşor de
utilizat;
 Prin eliminarea paşilor individuali se elimină erorile umane şi se
asigură coerenţa datelor;
 Limitarea accesului la datele de bază, prin intermediul
procedurilor stocate, reduce şansa deteriorării datelor,
intenţionată sau nu.
 Procedurile stocate au formă compilată, deci se execută mult mai
repede;
 În limbajul SQL există elemente şi caracteristici disponibile
numai pentru cereri unice. Procedurile stocate le pot folosi pentru
a scrie cod mai puternic şi mai flexibil.

Prin urmare există 3 beneficii majore ale procedurilor stocate: simplitate,


securitate şi performanţă.

Pentru a practica efectiv în folosirea procedurilor stocate, va trebui să


folosiţi surse de informare care se găsesc din belşug în librării şi pe
Internet.

Tranzacţii. Tranzacţiile sunt facilităţi ale limbajului SQL care asigură că


loturile de operaţii SQL sunt executate complet sau deloc. Ştim că tabelele
unei baze de date relaţionale sunt legate între ele prin intermediul cheilor
primare şi cheilor externe. Prin urmare, unele modificări dintr-un tabel
produce modificări de date în alt tabel.

165
Baze de date Capitolul 4
De exemplu, dacă se adaugă o comandă în tabelul tblComenzi, în tabelul
tblDetaliiComenzi trebuie introduse articolele acelei comenzi. Mai întâi se
completează tabelul tblComenzi, apoi se completează tabelul
tblDetaliiComenzi. Se pune întrebarea, ce se întâmplă dacă în timpul
completării articolelor comenzii în tabelul tblDetaliiComenzi, se întrerupe
curentul sau nu există suficient spaţiu pe hard-disc?

Evident, va apare o comandă care nu are articole, sau o comandă care nu


are toate articolele, oricum o situaţie nereală. Cu siguranţă, au fost multe
astfel de situaţii, ceea ce i-a forţat pe creatorii limbajului SQL să găsească
soluţii de rezolvare. Astfel au fost inventate tranzacţiile.

Prelucrarea de tranzacţii este un mecanism folosit pentru gestionarea


seturilor de operaţii SQL ce trebuie executate în loturi, pentru ca baza de
date să nu conţină niciodată rezultatele unor operaţii parţiale.

Prin intermediul prelucrării de tranzacţii, vă puteţi asigura că seturile de


operaţii nu sunt întrerupte în mijlocul prelucrării – ele sunt fie complet
executate, fie deloc. Dacă nu intervine nici o eroare, întregul set de
instrucţiuni este executat, iar datele sunt trecute în tabelele bazei de date.
Dacă apare o eroare, atunci se poate derula în mod automat o revenire la
starea iniţială, stare cunoscută şi sigură.

Datorită importanţei şi complexităţii tranzacţiilor, acestea sunt folosite


numai de programatorii profesionişti, iar nivelul acestui curs este de a vă
iniţia în folosirea limbajului SQL. Dacă aţi înţeles până acum mecanismul
acestui limbaj, veţi putea trece fără probleme şi la părţile sale avansate,
pentru că oricum aveţi baza de plecare. Desigur, trebuie să mai studiaţi
bibliografie, care se găseşte azi din belşug, atât scrisă cât şi pe Internet.

Cursoarele. Uneori şi nu de puţine ori, în aplicaţiile performante este


nevoie de parcurgerea unui set de date provenite dintr-o interogare, aşa
cum se parcurg liniile unui tabel al bazei de date. Acest lucru este realizat
cu ajutorul cursoarelor.

Un cursor este o interogare în baza de date stocată în serverul SGBD – nu o


instrucţiune SELECT, ci rezultatul acesteia, adică date efective. Odată ce
cursorul este stocat, aplicaţia poate să deruleze sau să răsfoiască în sus şi în
jos prin date, după cum este nevoie.

166
Baze de date Capitolul 4
Concluzii

SQL este limbajul cel mai răspândit în lucrul cu bazele de date. Indiferent
dacă sunteţi programator de aplicaţii, administrator de baze de date (vezi
Anexa A), designer de aplicaţii Web sau utilizator al suitei Microsoft
Office, o bună cunoaştere a limbajului SQL, constituie o parte importantă a
interacţiunii cu bazele de date.

Sunt azi o mulţime de cărţi despre limbajul SQL şi unele sunt chiar foarte
bune, toate au însă un lucru comun: conţin prea multe informaţii pentru
majoritatea utilizatorilor. Lipsesc exemplele simple, sugestive care, de
multe ori, fac mai mult decât pagini întregi de explicaţii sterile.

Capitolul 4, pe care tocmai l-aţi parcurs, va pus la dispoziţie acele


cunoştinţe care vă pot ajuta să dezvoltaţi aplicaţii de baze de date la un
nivel cerut de multe firme mici sau medii în care aţi putea lucra. Exemplele
prezentate vă pot ajuta să înţelegeţi multe din aspectele practice ale
folosirii limbajului SQL.

Acei dintre dumneavoastră care vor ajunge administratori de baze de date,


găsesc aici informaţii preţioase pentru activitatea lor curentă. Pentru cei
care doresc mai mult, pot trece la studierea şi aplicarea elementelor
avansate ale limbajului SQL, cum sunt procedurile stocate, tranzacţiile,
cursoarele etc.

În capitolul următor, veţi avea ocazia să folosiţi limbajul SQL în cadrul


sistemului de gestiune a bazelor de date relaţionale ACCESS.

167