Sunteți pe pagina 1din 30

Curs 4

INTEROGAREA BAZELOR DE DATE


Interogarea (qu’ery) este operaþia prin care se obþin datele dorite dintr-o bazã de
date, selectate conform unui anumit criteriu (condiþie). Dat fiind cã operaþia de
interogare este cea mai importantã operaþie de manevrare a datelor, de multe ori limbajele
de manevrare a datelor sunt denumite limbaje de interogare.
Pentru formularea conceptualã a interogãrilor în bazele de date relaþionale s-au
dezvoltat douã limbaje abstracte de interogare: algebra relaþionalã ºi calculul relaþional.
Algebra relaþionalã (relational algebra) constã dintr-o mulþime de operaþii care au
ca operanzi relaþii, iar rezultatul este tot o relaþie.
Calculul relaþional (relational calculus) este bazat pe calculul predicatelor ºi
exprimã o interogare formulând o definiþie a rezultatului dorit (de regulã, o relaþie)
printr-o expresie de calcul relaþional. Variabilele unei expresii de calcul relaþional pot fi
variabile de tuplu (variabile ale cãror valori sunt definite pe mulþimea tuplurilor unei
anumite relaþii) sau variabile de domeniu (variabile ale cãror valori sunt definite pe
domenii de definiþie ale atributelor). Pe baza unor astfel de variabile se defineºte calculul
relaþional al tuplurilor, respectiv calculul relaþional al domeniilor.
Aceste limbaje de interogare abstracte, algebra relaþionalã, calculul relaþional al
tuplelor ºi calculul relaþional al domeniilor sunt echivalente din punct de vedere al
capacitãþii de exprimare a interogãrilor, diferenþele constând în modul de formulare a
acestora. S-a demonstrat cã, pentru orice expresie de algebrã relaþionalã, se poate gãsi o
expresie de calcul relaþional echivalentã ºi invers.
Limbajele de interogare reale implementate în sistemele de baze de date
relaþionale sunt limbaje definite pe baza unuia sau altuia din limbajele de interogare
abstracte, sau pe o combinaþie a acestora. De exemplu:
• Limbajul SQL2 este în cea mai mare parte bazat pe algebra relaþionalã,
dar mai conþine ºi construcþii derivate din calculul relaþional -Microsoft
Access, Sql Server (se numeºte T-SQL).
• Limbajul ISBL (Information System Base Language) al firmei IBM este bazat în
întregime pe algebra relaþionalã.
• Limbajul QUEL al SGBD Ingres este bazat pe calculul relaþional al tuplurilor.
• Limbajul QBE (Query by Example), dezvoltat la firma IBM este bazat pe
calculul relaþional al domeniilor-Microsoft Access, Visual Foxpro.
Un limbaj de interogare real este denumit relaþional complet dacã implementeazã
toate operaþiile prevãzute de unul din limbajele de interogare abstracte. În general, toate
limbajele relaþionale implementate în sistemele SGBD sunt limbaje relaþionale mai mult
decât complete, conþinând ºi operaþii care nu sunt prevãzute în limbajele relaþionale
abstracte, ca de exemplu, efectuarea unor calcule aritmetice asupra valorilor unor atribute
(sumã, medie, minim, maxim), funcþii de tipãrire a relaþiilor, etc.
Limbajul SQL2 este limbajul cel mai utilizat în sistemele relaþionale ºi de
aceea, în continuare majoritatea exemplificãrilor vor fi prezentate în SQL2.

4.1 ALGEBRA RELAÞIONALÃ


Algebra relaþionalã (relational algebra) exprimã interogãrile prin aplicarea unor
operatori specializaþi (operatorii algebrei relaþionale) asupra relaþiilor. E.F. Codd a
propus opt operaþii ale algebrei relaþionale, grupate în douã categorii:
• Operaþii pe mulþimi: reuniunea (union), intersecþia (intersection), diferenþa
(difference) ºi produsul cartezian (Cartesian product). Aceste operatii reprezintã
adaptarea operatiilor corespunzãtoare din teoria mulþimilor ºi acþioneazã asupra
relaþiilor vãzute ca mulþimi de elemente (tupluri), fãrã a lua în consideraþie
compoziþia fiecãrui element.
• Operaþii relaþionale speciale: restricþia (restriction), proiecþia (projection),
joncþiunea (join) ºi diviziunea (division). Aceste operaþii iau în consideraþie
compoziþia tuplurilor, formate din valori ale atributelor relaþiilor.
Toate aceste operaþii trebuie sã asigure proprietatea de închidere, adicã rezultatul
fiecãrei operaþii trebuie sã fie tot o relaþie. Aceastã proprietate permite efectuarea
operaþiilor imbricate: proiecþia unei joncþiuni dintre o relaþie ºi restricþia aplicatã altei
relaþii, etc.
Restricþia ºi proiecþia sunt operaþii unare (au un singur operand, o relaþie);
operatiile pe mulþimi, joncþiunea ºi diviziunea sunt operaþii binare (au doi operanzi, douã
relaþii).

4.1.1 OPERAÞII PE MULÞIMI


În operaþiile asupra relaþiilor considerate ca mulþimi se impun anumite condiþii
celor doi operanzi, astfel încât relaþia rezultat sã fie obþinutã ca o mulþime de tupluri
omogene. Aceste condiþii depind de tipul operaþiei: reuniunea, intersecþia ºi diferenþa
necesitã ca relaþiile sã fie compatibile, iar produsul cartezian necesitã ca numele atributelor
celor douã relaþii operand sã fie distincte. Pentru ca douã relaþii sã fie compatibile, trebuie
sã aibã acelaºi numãr de atribute ºi atributele corespondente sã fie definite pe domenii
compatibile.
Reuniunea a douã relaþii compatibile R ºi S este o relaþie QU = R u S care conþine
toate tuplurile ce aparþin fie relaþiei R, fie relaþiei S, fie ambelor relaþii. Tuplurile care
aparþin ambelor relaþii se introduc în relaþia rezultat o singurã datã, adicã nu se duplicã.
Operaþia de reuniune se exprimã în limbajul SQL ca o reuniune a douã tabele
obþinute ca rezultat a douã comenzi SELECT, cu sintaxa:
SELECT lista_coloane1 FROM tabel1 [WHERE condiþie1]
UNION
SELECT lista_coloane2 FROM tabel2 [WHERE condiþie2];
Cele douã liste de coloane din clauzele SELECT trebuie sã conþinã atribute
compatibile. Tabelele din clauzele FROM, ca ºi condiþiile din clauzele WHERE pot fi identice
sau diferite.
Fie relaþiile: ANGAJATI(IdAngajat,Nume,Prenume,DataNasterii,
Adresa,Functie, Salariu) ºi FURNIZORI (IdFurnizor, Nume, Prenume,
DataNaºterii,Adresa,Firma).
O operaþie de reuniune pe baza acestor relaþii poate arãta astfel:
SELECT Nume,Prenume FROM ANGAJATI WHERE Adresa = ‘Bucuresti’
UNION
SELECT Nume,Prenume FROM FURNIZORI WHERE Adresa =
‘Bucureºti’;
Rezultatul va fi o relaþie cu atributele (Nume,Prenume) care conþine numele ºi
prenumele tuturor angajaþilor ºi ale furnizorilor care locuiesc în oraºul Bucureºti. Dacã
existã tupluri duplicat (un angajat ºi un furnizor cu acelaºi nume ºi prenume, ceea ce este
posibil), relaþia rezultat conþine un singur tuplu cu valorile respective. Opþiunea SQL
UNION ALL permite ca rezultatul sã conþinã duplicate, deci acest rezultat nu mai poate fi
numit relaþie. Dupã cum se observã, limbajul SQL admite unele construcþii care nu
respectã cerinþele teoretice ale modelului relaþional.
Intersecþia a douã relaþii compatibile R ºi S este o relaþie QI = R n S care conþine
toate tuplurile care aparþin atât relaþiei R cât ºi relaþiei S. La fel ca ºi reuniunea, operaþia
de intersecþie se exprimã în SQL ca intersecþie a douã tabele obþinute ca rezultat a douã
comenzi SELECT, cu sintaxa:
SELECT lista_coloane1 FROM tabel1 [WHERE condiþie1]
INTERSECT
SELECT lista_coloane2 FROM tabel2 [WHERE condiþie2];
Diferenþa a douã relaþii compatibile R ºi S este o relaþie QM = R - S care conþine
toate tuplurile care aparþin relaþiei R, dar nu aparþin relaþiei S. Operaþia de diferenþã se
exprimã în SQL ca diferenþã a douã tabele obþinute ca rezultat a douã comenzi SELECT,
cu sintaxa:
SELECT lista_coloane1 FROM tabel1 [WHERE condiþie1]
MINUS
SELECT lista_coloane2 FROM tabel2 [WHERE condiþie2];
Reuniunea ºi intersecþia sunt comutative (RuS = SuR; R n S = S n R) ºi asociative
(R u (S u T) = (RuS)uT; Rn(SnT) = (RnS)nT). Diferenþa nu este nici
comutativã (R - S * S - R), nici asociativã (R -(S - T) * (R - S)- T).
Produsul cartezian. În teoria mulþimilor, produsul cartezian al mulþimilor R ºi S
este o mulþime compusã din toate perechile ordonate de elemente ale celor douã mulþimi:
R x S = {<a,b>|aeR,beS}.
În algebra relaþionalã, produsul cartezian al relaþiilor R(A1,A2,... An) ºi
S(B1,B2,...Bm) este o relaþie QC (A1,A2,....An,B1,B2,...Bm) = R x S care are ca
atribute toate atributele primei relaþii plus toate atributele celei de-a doua relaþii. Pentru a se
obþine tuplurile relaþiei rezultat se combinã (se concateneazã) valorile atributelor fiecãrui
tuplu din prima relaþie cu valorile atributelor tuturor tuplurilor din cea de-a doua relaþie.
Din aceastã definiþie se observã cã gradul relaþiei rezultat este egal cu suma
gradelor celor douã relaþii operanzi, iar cardinalitatea este egalã cu produsul
cardinalitãþilor celor douã relaþii operand.
Ca exemplu, se va calcula produsul cartezian al relaþiilor ANGAJATI ºi SECTII,
prezentate mai jos în figura. 3.1.
ANGAJATI
IdAngaja Nume Prenume Adresa Salari IdSectie
1t Ionescu DataNasterii
Ion 1945.01.05 Bucuresti u
4000 1
2 Popescu Petre 1972.06.21 Bucuresti 3500 1
3 Vasilescu Ana 1966.04.02 Bucuresti 3000 2
4 Ionescu Ion 1970.11.12 Bucureºti 2500 3
SECTII

IdSectie Nume Buget


1 Productie 4000000
2 Proiectare 3000000
3 Cercetare 2000000
ANGAJATI × SECTII

IdAngaja ANGAJA .... ANGAJATI. SECTII. SECTII Buget


t Nume
TI. IdSectie IdSectie Nume
.
1 Ionescu … 1 1 Producti 4000000
1 Ionescu … 1 2 Proiecta
e 3000000
1 Ionescu … 1 3 Cercetar
re 2000000
2 Popescu … 1 1 Producti
e 4000000
2 Popescu … 1 2 Proiecta
e 3000000
2 Popescu … 1 3 Cercetar
re 2000000
3 Vasilescu … 2 1 Producti
e 4000000
3 Vasilescu … 2 2 Proiecta
e 3000000
3 Vasilescu … 2 3 Cercetar
re 2000000
4 Ionescu … 3 1 Producti
e 4000000
4 Ionescu … 3 2 Proiecta
e 3000000
4 Ionescu … 3 3 Cercetar
re 2000000
e
Fig. 3.1. Produsul cartezian a douã relaþii.
Pentru ca rezultatul produsului cartezian sã fie corect din punct de vedere relaþional,
este necesar ca atributele celor douã relaþii operand sã aibã nume diferite, deoarece în
relaþia rezultat nu pot exista douã atribute cu acelaºi nume. Aceastã cerinþã se rezolvã uºor,
prin calificarea numelor unor atribute cu numele relaþiei cãreia îi aparþin sau prin
redenumirea atributelor.
Calificarea numelui unui atribut cu numele relaþiei se realizeazã prin scrierea
numelui atributului precedat de numelui relaþiei, cele douã nume fiind separate prin
operatorul punct (.), la fel ca în reprezentarea datelor sau funcþiilor membre ale unui obiect
(instanþã a unei clase) în programarea obiect-orientatã. De exemplu, atributul IdSectie
din relaþiile ANGAJATI ºi SECTII se poate diferenþia prin calificare astfel:
SECTII.IdSectie ºi ANGAJATI.IdSectie.
Pentru redenumirea atributelor în algebra relaþionalã se poate folosi o operaþie
specialã, care se adaugã celor opt operaþiii de bazã. Sintaxa conceptualã a operaþiei de
redenumire este:
RENAME nume_relatie.nume_atribut AS noul_nume_atribut
Operaþia produs cartezian este conceptual comutativã, adicã R×S = S×R, dacã se
considerã cã atributele unei relaþii nu sunt ordonate. Dacã se considerã schema relaþiei
rezultat ca listã a atributelor sale, atunci, prin convenþie, atributele primei relaþii operand
sunt primele în lista de atribute a relaþiei rezultat, iar atributele celei de-a doua relaþii
urmeazã în lista atributelor relaþiei rezultat.
Operaþia produs cartezian este asociativã, dacã se considerã cã ordinea atributelor
într-o schemã de relaþie ºi ordinea tuplurilor într-o relaþie nu este relevantã: R ×(S × T) = (R
× S)× T.
În limbajul SQL, produsul cartezian a douã tabele R ºi S se obþine ca o variantã a
instrucþiunii SELECT, într-una din formele:
SELECT * FROM R,S;
SELECT lista_coloane FROM R,S;
În prima formã, limbajul SQL admite operaþia produs cartezian ºi în situaþia în care
în cele douã relaþii operand existã douã atribute cu acelaºi nume, subînþelegându-se cã
atributele rezultatului sunt ordonate, mai întâi fiind atributele primei relatii, urmate de
atributele celei de-a doua relatii.
Pentru cea de-a douã formã, atributele cu acelaºi nume trebuie sã fie calificate cu
numele relaþiei respective. De exemplu, produsul cartezian al relaþiilor
SECTII(IdSectie,Nume,Buget) ºi ANGAJATI(IdAngajat,Nume,Prenume,
DataNasterii,Adresa,Salariu,IdSectie) se poate scrie în SQL într-una din
formele:
SELECT * FROM SECTII,ANGAJATI;
SELECT SECTII.IdSectie,SECTII.Nume,Buget,IdAngajat,
ANGAJAÞI.Nume,Prenume,DataNasterii,Adresa,Salariu,
ANGAJAÞI.IdSectie FROM SECTII,ANGAJATI;
În plus, în limbajul SQL se pot redenumi atributele folosind cuvântul cheie AS între
numele unui atribut ºi redenumirea acestuia. În aceastã formã, interogarea precedentã poate
fi scrisã astfel:
SELECT SECTII.IdSectie,SEC T II.Nume
AS SNume,
Buget,IdAngajat,ANGAJAÞI.Nume
AS ANume,
Prenume,DataNasterii,Adresa,Sa
lariu, ANGAJATI.IdSectie FROM
SECTII,ANGAJATI;
În unele implementãri ale limbajului SQL nu este necesar cuvântul cheie AS pentru
redenumirea atributelor.

4.1.2 OPERAÞII RELAÞIONALE SPECIALE


În operaþiile speciale asupra relaþiilor se ia în consideraþie compoziþia tuplurilor
(combinaþii de valori ale atributelor) ºi se impun anumite condiþii atributelor acestora.
Restricþia (restriction) este o operaþie relaþionalã unarã care selecteazã dintre
tuplurile relaþiei operand acele tupluri care îndeplinesc o condiþie datã.
Operaþia de restricþie se mai numeºte ºi selecþie (ºi, într-adevãr, restricþia face o
selecþie a tuplurilor), dar este mai bine sã fie evitatã aceastã denumire deoarece se poate
confunda cu instrucþiunea SELECT, care are rolul de instrucþiune generalã de interogare.

Operaþia de restricþie se noteazã:   (R ) , unde  este o expresie logicã


specificatã asupra atributelor relaþiei R. În relaþia rezultat sunt selectate acele tupluri ale
relaþiei R pentru care expresia  are valoarea 1 (TRUE). Relaþia rezultat are aceleaºi
atribute ca ºi relaþia operand.
Expresia logicã  este formatã din una sau mai multe variabile logice v conectate
prin operatorii logici AND, OR, NOT, ca de exemplu:

 = v1 AND (v2 OR v3)...


Fiecare variabilã logicã v este rezultatul returnat de un operator de comparaþie. Se
pot compara valorile a douã atribute sau se poate compara valoarea unui atribut cu o
constantã.
De exemplu, pentru a selecta din relaþia ANGAJATI toþi angajaþii care lucreazã în
secþia 1 ºi au salarii mai mari sau egale cu 4000 ºi pe cei care lucreazã în secþia 2 ºi au
salarii mai mari sau egale cu 3000, se foloseºte restricþia prezentatã în figura 3.2.
Rezultatul prezentat corespunde stãrii relaþiei ANGAJATI din figura 3.1.
Precedenþa operatorilor logici este cea cunoscutã din logica matematicã: NOT,
AND, OR; aceastã precedenþã se poate modifica folosind paranteze. În expresia din figura
3.2 nu sunt neapãrat necesare parantezele, dar au fost introduse pentru a evidenþia mai clar
condiþiile impuse valorilor atributelor.
 (IdSectie=1 AND Salariu>4000)OR IdSectie=2 AND Salariu>3000)ANGAJATI)
IdAngajat Nume Prenume DataNasterii Adresa Salariu IdSectie
1 Ionescu Ion 1945.01.05 Bucuresti 4000 1
3 _______ Vasilescu Ana ____ 1966.04.02 __ Bucuresti 3000 2
Fig. 3.2. Operaþia de restricþie.

O secvenþã de restricþii poate fi aplicatã în orice ordine, adicã:

 cond1(  cond2(R)) =  cond2(  cond1(R))


Mai mult, se poate observa ºi demonstra cu uºurinþã cã orice secvenþã de restricþii
poate fi înlocuitã printr-o singurã restricþie în care expresia logicã de condiþie se obþine
prin conjuncþia (AND) tuturor condiþiilor:
 cond1(  cond2(..  condn(R)..))=  cond1 AND cond2...AND
 ondn(R)
Identitatea de mai sus poate fi interpretatã ºi invers, ºi anume cã operaþia de
restricþie poate fi divizatã (splitatã) în operaþii de restricþii succesive cu condiþii care sunt
componentele conjunctive (conectate prin operatorul AND) ale condiþiei de restricþie.
Cardinalitatea (numãrul de tupluri) relaþiei rezultat al operaþiei de restricþie este
mai micã sau cel mult egalã cu cardinalitatea relaþiei operand. Situaþia de egalitate apare
dacã expresia logicã de condiþie este evaluatã la valoarea TRUE pentru oricare tuplu al
relaþiei operand. De regulã, însã, prin operaþia de restricþie se obþine un numãr de tupluri
mai mic decât numãrul de tupluri al relaþiei date.
În limbajul SQL restricþia se exprimã printr-o formã particularã a
instrucþiunii SELECT, în care lista de atribute este formatã din toate atributele unei
singure relaþii, iar clauza WHERE este obligatorie ºi introduce condiþia de restricþie:
SELECT * FROM tabel WHERE conditie [clauze_secundare];
De exemplu, pentru a obþine restricþia din figura 3.2 se introduce comanda:
SELECT * FROM ANGAJATI WHERE IdSectie = 1
AND Salariu >= 4000 OR IdSectie = 2 AND Salariu >=3000;
În termenii folosiþi în limbajul SQL, restricþia selecteazã o parte din liniile
tabelului operand.
Proiecþia (projection) este o operaþie relaþionalã unarã prin care se selecteazã o
submulþime de atribute ale relaþiei operand.
Notaþia pentru proiecþie este:  lista_atribute(nume_relatie). Relaþia
rezultat a operaþiei de proiecþie conþine numai atributele din lista de atribute datã ca
parametru, care este o submulþime nevidã a mulþimii atributelor relaþiei operand.
Douã exemple de operaþii de proiecþie asupra relaþiei ANGAJATI cu starea din
figura 3.1 sunt prezentate în figura 3.3.
Dacã lista atributelor de proiecþie este o cheie (sau conþine o cheie) a relaþiei
operand, atunci relaþia rezultat are toate tuplurile distincte (fig. 3.3, a). În aceastã situaþie
numãrul de tupluri ale relaþiei rezultat este egal cu numãrul de tupluri ale relaþiei operand.
Dacã lista de atribute nu este o cheie (sau nu conþine o cheie) a relaþiei operand,
atunci este posibil ca prin proiecþie sã se obþinã douã sau mai multe tupluri identice, dar în
relaþia rezultat sunt eliminate tuplurile duplicat. De exemplu, în proiecþia pe atributele
(Nume,Prenume) a relaþiei ANGAJATI din figura 3.3, b tuplul (Ionescu,Ion) este
introdus o singurã datã în relaþia rezultat, deºi el este obþinut de douã ori prin operaþia de
proiecþie. În acestã situaþie, numãrul de tupluri ale relaþiei rezultat este mai mic decât
numãrul de tupluri ale relaþiei operand.
Gradul relaþiei rezultat al unei proiecþii (numãrul de atribute) este mai mic sau egal
cu gradul relaþiei operand. Numãrul de atribute al relaþiei rezultat este egal cu numãrul de
atribute al relaþiei operand dacã lista de proiecþie este identicã cu lista atributelor relaþiei
date.
 IdAngajat,Nume,Prenume(ANGAJATI)  Nume,Prenume(ANGAJATI)

IdAngajat Nume Nume


Prenume
1 Ionescu Ion Prenume
Ionescu Ion
2 Popescu Popescu Petre
3Petre Vasilescu Ana Vasilescu Ana
4 Ionescu Ion
a
b
Fig. 3.3. Operaþii de proiecþie:
a - lista atributelor de proiecþie conþine o cheie a relaþiei operand;
b - lista atributelor de proiecþie nu conþine o cheie a relaþiei operand.
Fie o succesiune de operaþii de proiecþie:
 lista1(  lista2 ...(  listak(R))...)
O astfel de succesiune de proiecþii este corectã numai dacã lista1 lista2...listak;
bineînþeles, se considerã listele de atribute ca mulþimi. În aceastã situaþie, întreaga
succesiune de proiecþii se poate înlocui cu proiecþia pe lista de atribute cea mai din stânga:
 lista1(R) .
Egalitatea de mai sus se poate interpreta ºi reciproc: o proiecþie pe o mulþime de
atribute (lista1) poate fi înlocuitã cu o succesiune de proiecþii pe mulþimi de atribute
care includ lista de atribute datã.
În limbajul SQL, operaþia de proiecþie se obþine tot prin instrucþiunea de
interogare SELECT; lista de coloane introdusã în instrucþiunea SELECT este lista
atributelor de proiecþie. Sub forma:
SELECT DISTINCT lista_coloane FROM nume_tabel;
instrucþiunea SELECT reprezintã o operaþie de proiecþie asupra relaþiei numetabel pe
atributele date în lista coloane. De exemplu, proiecþia din figura 3.3, b se scrie poate
în SQL astfel:
SELECT DISTINCT Nume,Prenume FROM ANGAJATI;
Dacã lipseºte clauza DISTINCT ºi lista de atribute nu este o supercheie a relaþiei,
rezultatul operaþiei poate conþine tupluri duplicat (deci nu este o relaþie în sensul
definiþiei din modelul relaþional).
În termenii folosiþi în limbajul SQL, proiecþia realizeazã o selecþie a coloanelor
unui tabel.
Joncþiunea (cuplarea) - (join) este o operaþie binarã a algebrei relaþionale prin
care se combinã tuplurile a douã relaþii într-o singurã relaþie.
Joncþiunea se noteazã cu semnul >< ºi este o operaþie foarte importantã în bazele
de date relaþionale, deoarece ea permite realizarea asocierilor între relaþii. În continuare vor
fi prezentate douã forme ale operaþiei de joncþiune: 8-joncþiunea ºi joncþiunea naturalã.
 -joncþiunea a douã relaþii R(A1,A2,...An) ºi S(B1,B2,...Bm) este o relaþie
 J(A1,A2,... An,B1,B2,...Bm) = R ><  S, în care fiecare tuplu este o combinaþie
a douã tupluri, unul din relaþia R (cu atributele A1,A2,... .An), iar celãlalt din relaþia S
(cu atributele B1,B2,...Bm), combinaþie care satisface condiþia de joncþiune  . Forma
generalã a condiþiei de joncþiune  este:
 = cond1 AND cond2 ...AND condi ...AND condn
unde fiecare condiþie parþialã (condi) este o variabilã logicã, rezultat al unei operaþii de
comparaþie # (unde # poate fi unul din operatorii: =, *, <, <, >, > ) asupra valorilor a douã
atribute Ai (care aparþine relaþiei R) ºi Bi (care aparþine relaþiei S), deci:
condi = Ai # Bi
Atributele Ai ºi Bi ale cãror valori se comparã trebuie sã fie definite pe domenii
compatibile. Tuplurile în care atributele din condiþiile de joncþiune au valori NULL nu
sunt luate în consideraþie pentru calculul relaþiei rezultat.
Se observã asemãnarea operaþiei de 8-joncþiune cu produsul cartezian, dat fiind cã
tuplurile relaþiei rezultat sunt combinaþii ale tuplurilor relaþiilor operand, cu numãr de
atribute (gradul relaþiei) egal cu suma numãrului de atribute (gradul) ale celor doi operanzi.
Diferenþa esenþialã dintre joncþiune ºi produsul cartezian este aceea cã în operaþia de
joncþiune se combinã numai tuplurile care îndeplinesc condiþia de joncþiune  , pe câtã
vreme în operaþia produs cartezian în relaþia rezultat se includ toate combinaþiile de
tupluri din relaþiile operand. Ca urmare, operaþia de  -joncþiune poate fi scrisã ca
restricþie cu condiþia  a produsului cartezian al celor douã relaþii: R ><  S =   (R
x S). Ca exemplificare, se va calcula joncþiunea:
ANGAJATI ><e SECTII =   (ANGAJATI x SECTII) cu condiþia:
 =(ANGAJATI.IdSectie = SECTII.IdSectie),
asupra relaþiilor ANGAJATI(IdAngajat,Nume,Prenume,DataNasterii,
Adresa, Salariu,IdSectie) ºi SECTII (IdSectie,Nume,Buget) cu
valorile date în figura 3.1. Rezultatul acestei operaþii este dat în figura 3.4.
ANGAJATI >< (ANGAJATI.IdSectie = SECTII.IdSectie ) SECTII
IdAngajat ANGAJATI. .... ANGAJATI. SECTII. SECTII. Buget
Nume IdSectie IdSectie Nume
1 Ionescu … 1 1 Productie 4
4000000
2 Popescu … 1 1 Productie
3 Vasilescu … 2 2 Proiectare
4000000
4 Ionescu … 3 3 Cercetare
3000000
2000000
Fig. 3.4. Operaþie de 9-joncþiune între relaþiile ANGAJATI ºi SECTII.
Cea mai utilizatã formã de  -joncþiune este echijoncþiunea, în care se foloseºte
numai operatorul de comparaþie de egalitate (=). De altfel, exemplul prezentat mai sus este
o echijoncþiune. Într-o echijoncþiune vor exista întotdeauna una sau mai multe perechi de
atribute care au valori identice în fiecare din tuplurile relaþiei rezultat, ºi anume perechile
de atribute care sunt comparate pentru egalitate. În figura de mai sus, atributele
ANGAJATI.IdSectie ºi SECTII.IdSectie au valori identice în toate tuplurile, dat
fiind cã acestea au fost comparate pentru egalitate în condiþia de joncþiune.
Este de remarcat faptul cã operatorul de comparaþie de egalitate (=) folosit în
modelul relaþional este corespunzãtor operatorului (= =) din limbajul C (C++) ºi este
identic cu operatorul de asignare; diferenþierea dintre cei doi operatori cu acelaºi semn de
reprezentare rezultã din context (expresia în care apar).
Joncþiunea naturalã. Dat fiind cã într-o relaþie nu sunt necesare douã atribute cu
valori identice, s-a definit o nouã operaþie de joncþiune, numitã joncþiunea naturalã
(natural join) sau, chiar mai simplu, joncþiune. Joncþiunea naturalã este o echijoncþiune în
care fiecare pereche de atribute comparate pentru egalitate (în condiþia de joncþiune) se
înlocuieºte cu unul singur. Se poate spune cã joncþiunea naturalã este o echijoncþiune
urmatã de o proiecþie pe reuniunea atributelor celor douã relaþii.
Dat fiind cã  -joncþiunea este o restricþie a produsului cartezian al celor douã
relaþii operand, rezultã joncþiunea naturalã ca o proiecþie a unei restricþii a produsului
cartezian al celor douã relaþii.
Dacã se noteazã relaþiile operand cu R(A1,A2,...An,B1,B2,...Bm) ºi
S(B1,B2,...Bm, C1,C2,...Ck), cu atributele comune (B1,B2,...Bm), rezultatul
operaþiei de joncþiune naturalã este relaþia QJ cu expresia:

Q = R >< S = Π σ (R × S)
J A1,….An,B1,.…Bm,C1,.…Ck (R.B1=S.B1… AND R.Bm=S.Bm)

Atributele (B1,B2,...Bm) din cele douã relaþii comparate pentru egalitate în


joncþiunea naturalã se numesc atribute comune (sau atribute de joncþiune) ºi trebuie sã fie
definite pe domenii compatibile. Ele se considerã identice (chiar dacã au denumiri diferite)
ºi în reuniunea atributelor se introduc o singurã datã.
Joncþiunea naturalã se reprezintã numai cu semnul ><, fãrã sã mai fie însoþit de
condiþia de joncþiune, înþelegând prin aceasta cã joncþiunea are loc pe atributul (sau
atributele) comune ale celor douã relaþii.
În figura 3.5 este prezentat rezultatul joncþiunii dintre relaþiile ANGAJATI ºi
SECTII cu starea din figura 3.1 pe atributul comun IdSectie. Atributul comun
(IdSectie) apare o singurã datã în relaþia rezultat.
ANGAJATI >< SECTII
____________________________________________________________
IdAngajat Nume ANGAJATI. Salariu IdSectie SECTII. Buget
1 Ionescu 4000 1 Productie 4000000
2. Popescu… 3500 1 Productie 4000000
3 Vasilescu 3000 2 Proiectare 3000000
4 Ionescu 2500 3 Cercetare 2000000

Fig. 3.5. Joncþiunea naturalã a relaþiilor ANGAJATI, SECTII.


Gradul relaþiei rezultat al joncþiunii naturale a celor douã relaþii este: q = n + m +
k ºi este mai mic decât suma gradelor celor douã relaþii (sumã egalã cu n + 2*m + k).
Dacã nu existã nici o combinaþie de tupluri care sã îndeplineascã condiþia de
joncþiune, rezultatul operaþiei este o relaþie cu zero tupluri. Dacã nu se impune nici-o
condiþie de joncþiune, joncþiunea devine un produs cartezian al celor douã relaþii, cu un
numãr de tupluri egal cu produsul (NR x NS) al numãrului de tupluri NR ºi respectiv NS, ale
celor douã relaþii. În cazul general, numãrul de tupluri ale relaþiei rezultat al operaþiei de
joncþiune este cuprins între 0 ºi (NR x NS).
Operaþia de joncþiune naturalã este conceptual comutativã (adicã R >< S = S >< R), dacã
se considerã cã atributele unei relaþii nu sunt ordonate. Dacã se considerã schema relaþiei
rezultat ca listã a atributelor sale, atunci, prin convenþie, atributele primei relaþii operand
sunt primele în lista de atribute a relaþiei rezultat, iar atributele celei de-a doua relaþii, mai
puþin atributul (sau atributele) de joncþiune, urmeazã în lista atributelor relaþiei rezultat.
Operaþia de joncþiune naturalã nu este, în general, asociativã. Fie mulþimile de
atribute disjuncte A, B, C, D ºi relaþiile cu schemele: R(A,B), S(B,C) ºi T(A, D). În
expresia (R >< S) >< T se efectueazã mai întâi joncþiunea R >< S pe atributul comun B ale
celor douã relaþii, rezultând o relaþie cu schema Q(A,B,C), dupã care se efectueazã
joncþiunea Q >< T pe atributul comun A

Asocierea de la dreapta la stânga a relaþiilor date (expresia R >< (S >< T)) nu este
posibilã, deoarece joncþiunea (S >< T) nu se poate evalua, dat fiind cã relaþiile S(B,C) ºi T
(A,D) nu au nici-un atribut comun.
Se poate remarca uºor cã existã ºi situaþii în care joncþiunea naturalã este asociativã,
ºi anume când fiecare pereche de relaþii din expresia datã au atribute comune.
Operaþia de joncþiune naturalã este utilizatã pentru a combina date din douã relaþii,
astfel încât informaþia rezultatã sã fie cuprinsã într-o singurã relaþie. În cazul cel mai
frecvent, joncþiunea naturalã se calculeazã între o relaþie care referã ºi relaþia referitã,
atributul de joncþiune fiind cheia strãinã (în relaþia care referã), respectiv cheia primarã
(sau candidatã) în relaþia referitã. Rezultatul obþinut reflectã asocierea dintre cele douã
relaþii. De exemplu, joncþiunea naturalã din figura 3.5 între relaþiile ANGAJATI ºi
SECTII reflectã asocierea N: 1 între acestea. Din acest exemplu se poate remarca faptul cã
prin operaþia de joncþiune se obþin informaþii combinate din cele douã relaþii operand.
Pentru fiecare tuplu din relaþia care referã (în exemplul de mai sus, relaþia ANGAJATI) se
obþin toate informaþiile din tuplul referit (în exemplul de mai sus, relaþia SECTII),
adicã acel tuplu care are valoarea cheii primare egalã cu valoarea cheii strãine care o referã.
În exemplul de mai sus, prima linie a tabelului rezultat conþine toate informaþiile (nume
secþie, buget) despre secþia în care lucreazã angajatul respectiv (secþia 1), etc.
Forþa modelului relaþional constã în posibilitatea de a combina informaþiile din
douã sau mai multe relaþii pentru a obþine rezultatul unei interogãri, combinare care se
poate face printr-una sau mai multe operaþii de joncþiune. Aceastã posibilitate de
combinare a informaþiilor este denumitã de unii autori ca o „navigare” prin baza de date.
În limbajul SQL,  -joncþiunea se poate exprima direct cu o instrucþiune SELECT
pe douã sau mai multe tabele, condiþia de joncþiune  fiind introdusã prin clauza WHERE.
De exemplu,  -joncþiunea din figura 3.4 se poate obþine prin instrucþiunea:
SELECT * FROM ANGAJATI,SECTII WHERE ANGAJATI.IdSectie =
SECTII.IdAngajat;
O joncþiune naturalã se poate exprima în limbajul SQL numai în mod explicit,
adicã trebuie ca lista de atribute a instrucþiunii SELECT sã conþinã numai atributele
diferite din cele douã relaþii (fiecare atribut de joncþiune se introduce o singurã datã), iar în
clauza WHERE trebuie introdusã condiþia de egalitate a atributelor corespondente. De
exemplu, joncþiunea naturalã ANGAJATI >< SECTII din figura 3.5 se obþine prin
instrucþiunea SQL:
SELECT IdAngajat,ANGAJATI.Nume,Prenume,DataNasterii,
Adresa,Salariu,SECTII.IdSectie,SECTII.Nume,
Buget,IdAngajat FROM ANGAJATI,SECTII WHERE
ANGAJATI.IdSectie = SECTII.IdSectie;
Diviziunea (division) este o operaþie binarã a algebrei relaþionale prin care se
obþine o relaþie care conþine atributele diferenþei mulþimilor de atribute ale relaþiilor
operand.
Fie douã mulþimi de atribute: A = {A1,A2,..An} ºi B = {B1,B2,..Bm} ºi douã
relaþii R(A,B) ºi S(B) astfel încât mulþimea atributelor relaþiei S sã fie o submulþime a
mulþimii atributelor relaþiei R. Relaþia QD obþinutã prin operaþia de diviziune are ca
atribute toate atributele diferenþei celor douã mulþimi de atribute (adicã acele atribute care
aparþin relaþiei R ºi nu aparþin relaþiei S) ºi conþine acele tupluri t[A] care au
proprietatea cã pentru orice tuplu s din S existã un tuplu t în R care are atributul B egal cu
tuplul s. Se poate scrie:
QD(A) = R - S =nA aR.B = S.B(R)
În limbajul SQL, diviziunea se exprimã printr-o instrucþiune SELECT,
introducând explicit lista atributelor de proiecþie ºi condiþia de egalitate a atributelor
corespondente din cele douã relaþii prin clauza WHERE.
Algebra relaþionalã este o colecþie de operaþii asupra relaþiilor. Cele opt operaþii
propuse de E.F.Codd (reuniunea, intersecþia, diferenþa, produsul cartezian, restricþia,
proiecþia, joncþiunea, diviziunea), la care se adaugã operaþia de redenumire a atributelor,
nu constituie o mulþime minimã de operaþii ale algebrei relaþionale, deoarece o parte din
operaþii se pot exprima prin intermediul altora. Aºa cum s-a prezentat mai sus, joncþiunea
este o proiecþie a unei restricþii a produsului cartezian al celor douã relaþii, iar diviziunea
este o proiecþie a unei restricþii asupra relaþiei deîmpãrþit. La fel, intersecþia se poate
exprima printr-o expresie construitã pe baza operaþiei de diferenþã: R n S = R - (R -
S).
Cinci operaþii (reuniunea, diferenþa, produsul cartezian, restricþia, proiecþia) sunt
operaþii primitive ºi constituie mulþimea minimã de operaþii ale algebrei relaþionale. Pe
baza lor se poate construi orice expresie a algebrei relaþionale. Dar ºi celelalte trei operaþii
(ºi în special joncþiunea) sunt operaþii deosebit de utile în formularea interogãrilor, astfel
încât algebra relaþionalã a pãstrat toate cele opt operaþii propuse de E.F.Codd, la care s-a
adãugat operaþia de redenumire a atributelor.

4.1.3 FORMULAREA INTEROGÃRILOR


Interogãrile exprimate în limbaj natural se pot formula într-unul din limbajele
abstracte de interogare, algebra relaþionalã sau calculul relaþional, dupã care se poate gãsi
comanda corespunzãtoare în limbajul de interogare implementat de sistemul SGBD în care
va fi realizatã baza de date (cum este limbajul SQL).
Pentru utilizator, o interogare este o metodã de a regãsi anumite informaþii dintr-o
bazã de date, prin intermediul unei aplicaþii de baze de date. Din punctul de vedere al
programatorului aplicaþiei de baze de date, interogarea se exprimã printr-o comandã
echivalentã expresiei de interogare, comandã care se transmite sistemului SGBD.
Din punct de vedere al sistemului de gestiune, o interogare este un program (de
exemplu, în limbajul SQL) pe care îl compileazã ºi apoi îl executã. Ca orice program, o
interogare este prelucratã de cãtre SGBD în mai multe faze: analiza lexicalã, analiza
sintacticã ºi analiza semanticã, pentru validarea interogãrii, urmate de generarea codului.
De asemenea, dacã existã mai multe soluþii pentru aceeaºi interogare, sistemul de gestiune
selecteazã soluþia optimã. Conceptual, subsistemul SGBD de prelucrare a interogãrilor
constã din urmãtoarele componente:
• Compilatorul de interogãri, care efectueazã analiza lexicalã ºi sintacticã a
interogãrii; acesta valideazã din punct de vedere sintactic interogarea, adicã
verificã existenþa relaþiilor, a vederilor, a indexurilor ºi a atributelor implicate
în interogare ºi utilizarea corectã a acestora.
• Optimizatorul de interogãri, care efectueazã analiza semanticã a interogãrii ºi
selecteazã alternativa optimã dintre mai multe soluþii posibile de execuþie a
interogãrii.
• Generatorul de cod, care genereazã programul de execuþie al interogãrii,
conform optimizãrilor efectuate.
• Componenta de execuþie (runtime), care executã programul interogãrii.
Compilarea interogãrii se realizeazã la fel ca orice compilare a programelor, fãrã
aspecte specifice sistemelor de baze de date. Optimizarea interogãrilor este o operaþie
specificã sistemelor de gestiune ºi utilizeazã proprietãþile operaþiilor relaþionale pentru a
obþine performanþe de execuþie a interogãrilor cât mai bune. Optimizarea este efectuatã de
cãtre SGBD, transparent, fãrã intervenþia programatorului.
În algebra relaþionalã o interogare se formuleazã printr-o expresie constând dintr-o
secvenþã de identificatori (nume de relaþii, nume de atribute), constante ºi operatori. Pentru
exprimarea unei interogãri printr-o expresie de algebrã relaþionalã, trebuie sã fie precizate
urmãtoarele elemente:
• Lista atributelor relaþiei rezultat, care se numesc atribute de proiecþie.
• Lista relaþiilor din care se extrag informaþiile.
• Condiþia pe care trebuie sã o îndeplineascã tuplurile relaþiei rezultat.
În funcþie de aceste elemente, se pot studia douã situaþii de rezolvare a
interogarilor: interogãri care se rezolvã în cadrul unei singure relaþii ºi interogãri care se
rezolvã folosind douã sau mai multe relaþii ale bazei de date.
Interogãri într-o singurã relaþie. Dacã toate atributele care intervin în interogare
(atributele de proiecþie ºi atributele din condiþie) sunt atribute ale unei singure relaþii R,
atunci interogarea se poate rezolva la nivelul acelei relaþii, ca o proiecþie (pe atributele
relaþiei rezultat) a restricþiei cu condiþia impusã asupra relaþiei date, prin expresia:
Q = Π σ (R)
lista_atribute conditie

Exemplul 3.1. Fie relaþia ANGAJATI definitã în figura 3.1 ºi interogarea: „Care
sunt numele ºi prenumele angajaþilor care au un salariu mai mare sau egal cu 3000?”.
Se observã cã aceastã interogare poate fi rezolvatã la nivelul unei singure relaþii,
relaþia ANGAJATI. Expresia de algebrã relaþionalã care exprimã interogarea datã este:
Q1 =  Nume,Prenume σSalariu >3000 (ANGAJATI)
Instrucþiunea SQL care realizeazã aceastã interogare este:
SELECT Nume,Prenume FROM ANGAJATI WHERE
Salariu >= 3000; Rezultatul interogãrii este urmãtorul:

Nume Prenume
Ionescu Ion
Popescu Petre
Vasilescu Ana
Exemplul 3.2. Fie relaþia ANGAJATI definitã în figura 3.1 ºi interogarea: „Care
sunt numele, prenumele ºi salariul angajaþilor care lucreazã în secþia cu numãrul 1?”
Analizând aceastã interogare se constatã cã toate atributele de proiectie (nume,
prenume, data nasterii ºi salariul unui angajat) ºi atributul din condiþia de interogare
(numãrul sectiei) sunt atribute ale relaþiei ANGAJATI, deci interogarea poate fi rezolvatã
la nivelul acestei relaþii.
Expresia de algebrã relaþionalã care exprimã interogarea datã este:
Q = Π σ (ANGAJATI)
2 Nume,Prenume,Salariu IdSectie = 1

Comanda SQL care realizeazã aceastã interogare este:


SELECT Nume,Prenume,Salariu FROM ANGAJATI WHERE IdSectie=1;
Rezultatul interogãrii este:
Nume Prenume Salariu
Ionescu Ion 4000
Popescu Petre 350
Interogãri în douã sau mai multe relaþii. În situaþia în care atributele de
proiecþie ºi atributele din condiþia de interogare nu aparþin unei singure relaþii, pentru
rezolvarea interogãrii trebuie sã fie folosite toate acele relaþiile care, împreunã, conþin
aceste atribute.
Conceptual, o astfel de interogare se rezolvã construind mai întâi o relaþie care sã
conþinã toate atributele necesare prin combinarea a douã sau mai multe relaþii folosind
operaþii de produs cartezian sau joncþiuni, iar rezultatul interogãrii se obþine prin restricþia
(cu condiþia de interogare) ºi proiecþia (pe atributele de proiecþie) a acestei relaþii.
Cazul cel mai frecvent de interogare necesitã joncþiunea naturalã a douã sau mai
multe relaþii asociate, folosind perechea de atribute cheia strãinã - cheia primarã referitã
pentru fiecare operaþie de joncþiune:
Q = Π σ (R >< S >< T...)
lista_atribute conditie
Exemplul 3.3. Fie relaþiile ANGAJATI, SECTII definite în figura 3.1 ºi
interogarea „Care sunt numele, prenumele ºi salariul angajaþilor care lucreazã în secþia cu
numele Producþie ?”.
Atributele de proiecþie (Nume,Prenume,Salariu) sunt atribute ale relaþiei
ANGAJATI; atributul Nume al unei secþii (care apare în condiþia de interogare) nu
aceea, se aflã în aceeaºi relaþie, ci în relaþia SECTII de pentru a rezolva aceastã
interogare, este necesarã combinarea celor douã relaþii (fig. 3.6).

Combinarea celor douã relaþii se efectueazã prin joncþiunea naturalã (pe atributul
comun IdSectie) a celor douã relaþii. Relaþia rezultat al joncþiunii conþine toate
informaþiile necesare interogãrii: numele, prenumele ºi salariul angajaþilor ºi numele
secþiei corespunzãtor numãrului secþiei (IdSectie) în care lucreazã fiecare angajat.
Dupã aceasta se face restricþia (cu condiþia SECTII.Nume= ‘Productie’), urmatã de
proiecþia pe atributele de proiecþie. Expresia finalã de algebrã relaþionalã care exprimã
interogarea datã este:
Q =Π
3 ANGAJATI.Nume,Prenume,Salariu
σ (ANGAJATI >< SECTII)
SECTII.Nume='Productie'

Comanda SQL care realizeazã aceastã interogare este:


SELECT ANGAJATI.Nume,Prenume,Salariu FROM
ANGAJATI,SECTII WHERE SECÞII.IdSectie =
ANGAJATI.IdSectie AND SECTII.Nume =
‘Productie’;
Aºa cum s-a mai precizat, în limbajul SQL trebuie sã fie introdusã explicit condiþia
de joncþiune naturalã (SECTII.IdSectie = ANGAJATI.IdSectie), împreunã cu
celelalte condiþii de interogare (SECTII.Nume =‘Productie’).
Rezultatul acestei interogãri asupra relaþiilor cu starea din figura 3.1 este:
Nume Prenume Salariu
Ionescu Ion 4000
Popescu Petre 3500
Exemplul 3.4. Fie relaţiile FURNIZORI, ACHIZIŢII, COMPONENTE (fig. 3.7), uşor
modificate faţă de cele prezentate în capitolul precedent.
FURNIZORI
IdFurnizor Nume Prenume Adresa
1 Marculescu Mihai Bucuresti
2 Mircescu Vasile Bucuresti
3 Amzulescu Ion Craiova

ACHIZITII
IdComponenta IdFurnizor Cantitate PretUnitar
1 1 100 110
1 2 200 100
2 2 300 200
3 3 300 150

COMPONENTE
IdComponenta Denumire Culoare Greutate
1 Rezistenta Rosu 1
2 Condensator Alb 2
3 Ferita Negru 4

Fig. 3.7. Relaþiile FURNIZORI, ACHIZITII,COMPONENTE.


Interogarea "Care sunt numele ºi prenumele furnizorilor care au livrat componente în
cantitãþi mai mari sau egale cu 200 ?" necesitã joncþiunea relaþiilor FURNIZORI ºi
ACHIZITII care, împreunã, conþin atributele ce intervin în interogare. Expresia de
algebrã relaþionalã care realizeazã aceastã interogare este:
Q4 =nNume,Prenume Cantitate > 200 (FURNIZORI X ACHIZITII)
În SQL, aceastã interogare se exprimã astfel:
SELECT Nume,Prenume FROM FURNIZORI,ACHIZITII
WHERE FURNIZORI.IdFurnizor = ACHIZITII.IdFurnizor AND Cantitate
>= 200;

Nume Prenume
Mircescu Vasile
Amzulescu Ion
Eemplul 3.5. Pentru aceleaºi relaþii din figura 3.7, se considerã interogarea: "Care
sunt numele, prenumele ºi adresa furnizorilor care au livrat componenta cu denumirea
Rezistenta? ".
Atributele de proiecþie (Nume, Prenume, Adresa) aparþin relaþiei FURNIZORI,
iar atributul Denumire aparþine relaþiei COMPONENTE. Asocierea dintre aceste relaþii
este realizatã prin relaþia ACHIZITII, astfel încât aceastã interogare necesitã joncþiunea
tuturor celor trei relaþii. (fig. 3. 8).

Fig. 3.8. Interogare pe mai multe relaþii asociate.

Pentru realizarea interogãrii date se vor executa urmãtoarele operaþii:


R1 = ACHIZITII >< COMPONENTE
R = FURNIZORI >< R = FURNIZORI>< (ACHIZITII >< COMPONENTE)
2 1
R = σ (R )
3 Denumire ='Rezistenta' 2
Q = Π (R )=
5 Nume,Prenume,Adresa 3
Π σ
Nume,Prenume,Adresa Denumire ='Rezistenta'
(FURNIZORI >< (ACHIZITII >< COMPONENTE))

În limbajul SQL, interogarea de mai sus se exprimã prin instrucþiunea:


SELECT Nume, Prenume, Adresa
FROM FURNIZORI,ACHIZITII,COMPONENTE
WHERE FURNIZORI.IdFurnizor =
ACHIZITII.IdFurnizor AND
COMPONENTE.IdComponenta =
ACHIZITII.IdComponenta AND Denumire =
‘Rezistenta’;
Rezultatul acestei interogãri pentru starea relaþiilor din figura 3.7 este:

Nume Prenume Adresa


Marculescu Mihai Bucuresti
Mircescu _______ Vasile ________Bucuresti

Se observã cã în comanda SQL nu se evidenþiazã care sunt operaþiile de joncþiune


ºi ordinea lor de execuþie, iar condiþiile de restricþie ºi joncþiune sunt cuprinse într-o singurã
expresie (în clauza WHERE). Sistemul SGBD este acela care determinã modul optim de
realizare a operaþiilor conþinute în blocul de interogare.
4.2 Limbajul SQL
Limbajul SQL (Structured Query Language) este limbajul utilizat de majoritatea
sistemelor de baze de date relationale pentru definirea ºi manipularea datelor.
Limbajul SQL a fost dezvoltat într-un prototip de sistem de gestiune a bazelor de
date relaþionale -System R - la IBM, la mijlocul anilor 1970. In 1979 Corporatia Oracle a
introdus prima implementare a limbajului SQL în varianta comercialã. În anul 1987
Institutul National American de Standarde - ANSI (American National Standardization
Institute) a elaborat standardul limbajului SQL. Ulterior au avut loc mai multe revizii ale
acestui standard. În 1992 Organizaþia International de Standarde - ISO (International
Standardization Office) a adoptat limbajul SQL ca limbaj standard pentru sistemele de
gestiune a bazelor de date relaþionale sub denumirea de SQL-92 (sau, mai simplu, SQL2)
[ANSI92]. Un standard ulterior, SQL-99 (numit ºi SQL3) adaugã limbajului trãsãturi ale
modelului obiect-relaþional.
Majoritatea sistemelor SGBD relaþionale actuale suportã standardul SQL2, dar
fiecare implementeazã, de fapt, un dialect specific al limbajului SQL. În diferitele
implementãri ale limbajului SQL pot sã lipseascã unele comenzi prevãzute în standardul
SQL2, dar pot exista extensii specifice, neprevãzute în standard, care micºoreazã oarecum
gradul de portabilitate a aplicaþiilor. Unele sisteme de gestiune (ca Oracle9i,
PostgreSQL-7.2) suportã ºi o mare parte din specificaþiile obiect-relaþionale prevãzute în
standardul SQL99 (SQL3). Deoarece aceastã lucrare este axatã pe modelul relaþional se
vor descrie în principal instrucþiunile standardului SQL2.
Limbajul SQL foloseºte termenii de tabel (table), linie (row), coloanã (column)
pentru a desemna o relaþie, un tuplu sau un atribut, deci este orientat spre reprezentarea prin
tabele a relaþiilor, care este mai simplã ºi mai intuitivã pentru proiectanþi ºi pentru
programatori.
Limbajul SQL cuprinde atât componenta de descriere a datelor relaþionale (Limbaj
de Descriere a Datelor - LDD) cât ºi componenta de manipulare a datelor (Limbaj de
Manipulare a Datelor - LMD), ambele fiind absolut necesare în gestiunea bazelor de date.
Pe lângã aceste componente principale, standardul SQL2 mai prevede ºi alte componente ale
limbajului:

• Controlul tranzacþiilor - conþine comenzi pentru specificarea tranzacþiilor.


Unele implementãri adaugã comenzilor prevãzute în standard ºi alte comenzi
suplimentare de control al concurenþei ºi refacerea datelor.
• Controlul securitãþii ºi al protecþiei datelor - conþine comenzi de administrare
a bazelor de date, pentru definirea utilizatorilor ºi a drepturilor acestora de acces
la tabele. Aceastã componentã este puternic dependentã de sistemul de gestiune
al bazei de date, iar pentru sistemele performante, administrarea bazei de date
este un capitol foarte extins, care face obiectul activitãþii unei categorii speciale
de utilizatori ai bazei de date (administratori ai bazei de date).
Limbajul SQL este un limbaj neprocedural: o instrucþiune SQL specificã ce
informaþii trebuie sã fie setate sau obþinute, nu modul (procedura) în care se opereazã.
Limbajul SQL conþine numai instrucþiuni de definire ºi manipulare a datelor ºi nu conþine
instrucþiuni de control al fluxului execuþiei (instrucþiuni ca for, while, if, etc). De aceea,
pentru realizarea aplicaþiilor de baze de date, s-a dezvoltat o multitudine de tehnologii,
limbaje, biblioteci ºi interfeþe de programare care integreazã, printr-o tehnicã oarecare,
instrucþiunile SQL de acces la date.
În continuare se vor prezenta cele mai importante instrucþiuni de descriere ºi
manipulare a datelor definite în standardul SQL2.
Pentru a învãþa ºi testa diferite instrucþiuni SQL trebuie sã fie instalat un sistem de
gestiune a bazelor de date ºi un program utilitar care primeºte instrucþiuni de la consolã ºi le
transmite sistemului SGBD pentru a fi executate. Majoritatea sistemelor SGBD oferã astfel
de instrumente soft (cu sau fãrã interfaþã graficã). De exemplu, pentru sistemul Microsoft
SQL Server existã utilitarele isql ºi osql care permit executarea instrucþiunilor
Transact-SQL (care sunt extensii ale limbajului SQL); pentru sistemele Oracle existã
utilitarul SQL*Plus care permite execuþia de la consolã atât a instrucþiunilor SQL, ca ºi a
blocurilor PL/SQL; pentru sistemul mySQL existã utilitarul mySQL care executã
instrucþiuni SQL. Aceste programe utilitare sunt descrise în primul capitol din îndrumarul
de aplicaþii. Bineînþeles, atunci când se testeazã o anumitã instrucþiune SQL trebuie sã fie
folositã exact varianta implementatã în sistemul folosit, care poate diferi într-o oarecare
mãsurã de forma generalã din standard.

4.2.1 Structura lexicalã a limbajului SQL


O instrucþiune SQL (statement) este o secvenþã de elemente componente (tokens)
terminatã cu semnul punct ºi virgulã (;). Fiecare instrucþiune SQL conþine o comandã SQL
(command), care specificã ce acþiune se efectueazã, urmatã de alte elemente componente,
care specificã operaþii, clauze, parametri, etc. De exemplu, instrucþiunea:
SELECT * FROM ANGAJATI;
conþine comanda SQL SELECT, urmatã de alte elemente componente ale instrucþiunii.
Un element al unei instrucþiuni SQL poate fi: cuvânt cheie (key word), identificator
(identifier), constantã (literal) sau un caracter special. Elementele componente sunt, în
general, separate printr-unul sau mai multe spaþii albe (whitespaces): caracter spaþiu,
caracter linie nouã sau caracter tab. Separatorii pot lipsi dacã nu existã ambiguitãþi în
secvenþa de elemente ale unei comenzi. O comandã se poate scrie pe una sau mai multe
linii, iar într-o linie se pot introduce una sau mai multe comenzi.
Cuvinte cheie ºi identificatori. Cuvintele cheie sunt elemente componente cu
semnificaþie fixã în limbajul SQL. Acestea pot fi comenzi (SELECT, UPDATE, INSERT,
etc.), operatori (AND, OR, NOT, LIKE), clauze (WHERE, SET, VALUES, etc.). De
exemplu, în instrucþiunile urmãtoare, toate cuvintele scrise îngroºat (bold) sunt cuvinte
cheie:
SELECT * FROM SECTII WHERE IdSectie = 1;
INSERT INTO SECTII VALUES (2,‘Productie’,500);
Identificatorii sunt elemente componente care denumesc tabele, coloane sau alte
obiecte ale bazei de date. În exemplul de mai sus, SECTII, IdSectie sunt identificatori.
În SQL cuvintele cheie ºi identificatorii trebuie sã înceapã cu o literã sau cu
caracterul subliniere ( _ ), iar caracterele urmãtoare pot fi litere, cifre sau caracterul
subliniere. Cuvintele cheie ºi identificatorii au aceeaºi structurã lexicalã ºi nu pot fi
diferenþiaþi fãrã a cunoaºte limbajul. În cuvintele cheie ºi identificatori nu se diferenþiazã
caracterele mici de cele mari (sunt case-insensitive),deci comenzile INSERT, insert, sau
Insert, etc. sunt identice. Totuºi, pentru evidenþierea comenzilor SQL, în continuare
majoritatea cuvintelor cheie vor fi scrise cu majuscule. La fel vor fi scrise ºi numele
relaþiilor.
Pe lângã acest tip de identificatori simpli (formaþi dintr-o secvenþã de litere, cifre ºi
caracterul subliniere), mai existã ºi un alt tip de identificatori, identificatorii delimitaþi
(quoted identifiers), constând dintr-o secvenþã de caractere încadratã (la început ºi la
sfârºit) de caracterul ghilimele ( “ ). Un identificator delimitat este întotdeauna identificator
(niciodatã cuvânt cheie), iar literele mari sunt diferite de literele mici (este case-sensitive).
De exemplu, elementul “SELECT” este un identificator delimitat ºi poate denumi o tabelã
sau o coloanã (atribut), în timp ce elementul SELECT este un cuvânt cheie ºi utilizarea lui
ca nume de tabel sau de atribut va produce o eroare de interpretare a comenzii.
Un identificator delimitat poate conþine orice caracter cu excepþia caracterulul
ghilimele, permiþând crearea unor nume (de tabele, coloane, etc.) mai complexe, care sã
conþinã spaþii sau caractere speciale ( &, %, etc.), ceea ce cu identificatori simpli
(ne-delimitaþi) nu este posibil.
Constante. Constantele (literale) pot fi ºiruri de caractere, numere întregi, numere
reale sau constanta NULL. Ele se reprezintã aproximativ la fel ca în alte limbaje de
programare (de exemplu C/C++).
Caractere speciale. Unele caractere care nu sunt litere sau cifre pot avea rol de
operatori SQL sau pot avea o semnificaþie specialã în cadrul comenzilor SQL. De exemplu,
caracterul punct ºi virgulã (;) este folosit pentru terminarea comenzilor; caracterul punct (.)
este folosit ca punct zecimal sau pentru calificarea numelor; caracterul asterisc (*) este
folosit ca operator de înmulþire sau în comanda SELECT, etc.
4.2.2 Expresii, operatori ºi funcþii SQL2
O expresie SQL constã dintr-unul sau mai mulþi operanzi, operatori ºi paranteze.
Un operand poate fi numele unei coloane (a unui tabel), o constantã (literal), sau valoarea
returnatã de o functie; parantezele sunt folosite pentru a preciza o anumitã ordine a
operaþiilor, dacã aceasta este diferitã de cea implicitã, datã de precedenþa operatorilor.
Un operator SQL este compus dintr-unul sau mai mai multe caractere speciale (care
nu sunt litere sau cifre), ca de exemplu: +,-,*,/,%,<,>,=,~,!,@ #,&,|,^,?,‘,$, sau este un
cuvânt cheie, ca de exemplu: AND, OR, NOT, LIKE, etc. Din punct de vedere al numãrului
de operanzi, operatorii SQL sunt de douã categorii, binari ºi unari, cei unari putând fi
operatori prefix sau operatori postfix. Din punct de vedere al tipului de operaþie, operatorii
SQL (din orice categorie) pot fi aritmetici, logici, de comparaþie SQL, sau relationali.
Operatorii aritmetici ai limbajului SQL2 sunt compuºi din unul sau mai multe
caractere speciale ºi au notaþie ºi semnificaþie asemãnãtoare cu a celor definiþi în diferite
limbaje de programare, cu mici diferenþe care se pot remarca din lista de mai jos.
Operatorii aritmetici binari sunt: + (adunarea), - (scaderea), * (înmulþirea), /
(împãrþirea), % (modulo), ^ (ridicarea la putere), & (AND orientat pe biti), | (OR orientat pe
biti), # (XOR orientat pe biti) , << (deplasarea la stânga), >> (deplasarea la dreapta). Tot
operatori aritmetici sunt ºi operatorii binari de comparatie: < (mai mic), > (mai mare), <=
(mai mic sau egal), >= (mai mare sau egal), = (egal), <> (sau !=) (diferit). Operatorii
aritmetici unari sunt: @ (valoarea absoluta), ! (factorial), !! (factorial, operator postfix),
~ (NOT orientat pe biti).
Operatorii de comparaþie SQL sunt descriºi în tabelul urmãtor.

Operator Operaþia efectuatã


A BETWEEN min AND max comparã A cu douã valori, min ºi max
max
A IN (v1,v2, ...vn) comparã A cu o lista de valori (v1, v2,…vn )
A IS NULL comparã A cu NULL
A IS NOT NULL comparã A cu NOT NULL
A LIKE model_sir comparã A cu un model de ºir de caractere
Pentru operatorii de comparaþie, valoarea de comparat (A) este, de regulã, valoarea
unui atribut al unei relaþii, dat prin numele coloanei corespunzãtoare a tabelului care
reprezintã relaþia respectivã, o
constantã sau valoarea unei expresii. Operatorii de comparaþie (atât cei aritmetici, cât ºi
operatorii de comparaþie specifici SQL), returneazã (evalueazã) valoarea logicã TRUE (1),
dacã condiþia de comparaþie este îndeplinitã ºi FALSE (0) dacã condiþia de comparaþie nu
este îndeplinitã. Valoarea NULL este returnatã dacã ambii operanzi comparaþi au valoarea
NULL.
Operatorii logici ai limbajului SQL sunt notaþi prin cuvinte cheie: AND, OR, NOT.
Toþi aceºti operatori se aplicã unor variabile logice cu 3 valori (trivalente): TRUE (1),
FALSE (0) ºi NULL; valoarea NULL semnificã lipsa de informaþie. Operatorii logici SQL
returneazã o valoare logicã trivalentã (TRUE, FALSE sau NULL), aºa cum se poate vedea
din tabelele de adevãr de mai jos.

A B A AND B A OR B
TRUE TRUE TRUE TRUE
TRUE FALSE FALSE TRUE
TRUE NULL NULL TRUE
FALS FALSE FALSE FALSE
FALS
E NULL FALSE NULL
NULL
E NULL NULL NULL

A NOT A
TRUE FALSE
FALSE TRUE
NULL NULL
Operatorii relaþionali sunt notaþi prin cuvinte cheie: UNION (reuniune),
INTERSECT (intersecþie), MINUS (diferenþa).
Funcþiile definite în SQL sunt de douã categorii: funcþii agregat ºi funcþii scalare.
Funcþiile agregat calculeazã un rezultat din mai multe linii ale unui tabel. Aceste funcþii
vor fi detaliate într-o secþiune urmãtoare, la descrierea instrucþiunii SELECT.
Funcþiile scalare primesc unul sau mai multe argumente ºi returneazã valoarea
calculatã sau NULL în caz de eroare. Argumentele funcþiilor pot fi constante (literale) sau
valori ale atributelor specificate prin numele coloanelor corespunzatoare. Existã mai multe
tipuri de funcþii scalare SQL:
• Funcþii numerice: Majoritatea versiunilor de SQL furnizeazã funcþii de calcul
trigonometric (sin, cos, etc.), funcþii de calcul al logaritmului (ln, log), al puterii
(pow), funcþii de rotunjire (floor, ceil), etc.
• Funcþii pentru manipularea ºirurilor de caractere.
• Funcþii pentru data calendaristicã ºi timp.
• Funcþii de conversie.
Funcþiile scalare se folosesc în expresii, care pot sã aparã în diferite clauze ale
instrucþiunilor SQL.

4.2.3 Tipuri de date ºi domenii SQL2


În limbajul SQL (standardul SQL2) sunt definite mai multe tipuri de date: numeric,
ºir de caractere, ºir de biþi, data (calendaristicã), timp. Denumirile tipurilor de date, ca ºi
limitele acestora (valoare minimã, valoare maximã) prezintã diferite variaþii în funcþie de
implementare (versiunea de SGBD), dar în general sunt destul de asemãnãtoare.
Tipul numeric include numere întregi de diferite dimensiuni (integer sau int
reprezentat pe 4 octeþi, smallint reprezentat pe 2 octeþi), numere reale reprezentate în
virgulã flotantã, cu diferite precizii (float, reprezentat pe 4 octeþi, real ºi double [precision],
reprezentate pe 8 octeþi) ºi numere zecimale reprezentate cu precizia doritã (tipul numeric
sau decimal).
Formatul de reprezentare a numerelor zecimale cu precizia doritã este:
numeric[(p,s)] (sau decimal [(p,s)]), unde p (precizia) este numãrul total de cifre afiºate, iar s
(scara) este numãrul de cifre dupã punctul zecimal. În reprezentarea acestui tip de date poate
sã lipseascã parametrul s ºi atunci se considerã s = 0 (nici o cifrã dupã punctul zecimal), sau
pot lipsi ambii parametri ºi, în acest caz, se pot reprezenta numere cu orice precizie ºi scarã
(pânã la limita admisã de implementarea sistemului). Pentru a pãstra precizia doritã,
numerele de tip DECIMAL sau NUMERIC sunt memorate ca ºir de caractere, fiecare
caracter reprezentând o cifrã zecimalã, punctul zecimal sau semnul.
Tipul ºir de caractere permite definirea ºirurilor de caractere de lungime fixã
(character(n) sau, prescurtat, char(n)), precum ºi a ºirurilor de caractere de lungime
variabilã (character varying, prescurtat varchar(n)). Ambele tipuri pot reprezenta ºiruri de
maximum n caractere, cu diferenþa cã, pentru
ºiruri de lungime mai micã decât n, la tipul char(n) se completeazã ºirul cu spaþii albe pânã
la n caractere, în timp ce la tipul varchar(n) se memoreazã numai atâtea caractere câte are
ºirul dat.
Tipul ºiruri de biþi defineºte secvenþe de cifre binare (care pot lua valoarea 0 sau 1)
de lungime fixã n (bit(n)) sau de lungime variabilã, cu limita maximã n (bit varying(n)).
Tipurile pentru data calendaristicã ºi timp sunt: date, time, timestamp, interval.
Tipul date permite memorarea datelor calendaristice prin utilizarea a trei câmpuri
(year, month, day), în formatul yyyy-mm-dd. Sunt admise numai date valide (valori
pozitive diferite de zero ºi mai mici decât 12 pentru lunã, etc.).
Tipul time este utilizat pentru memorarea timpului, folosind trei câmpuri (hour,
minute, second) în formatul HH:MM:SS ºi, de asemenea, se admit numai valori valide. Un
parametru opþional p (time(P)) permite stabilirea numãrului de zecimale cu care se
reprezintã câmpul second. Valoarea implicitã a lui p este 0.
Tipul timestamp(p) este folosit pentru memorarea combinatã a datei calendaristice ºi
a timpului, cu precizia p pentru câmpul second. Valoarea implicitã a lui p este 6.
Tipul interval este utilizat pentru memorarea intervalelor de timp.
În denumirile tipurilor de date nu se diferenþiazã caracterele mici de cele mari (sunt
case-insensitive), deci se poate scrie: INT, VARCHAR, NUMERIC, etc.
Pe lângã aceste tipuri definite în standardul SQL2, implementãrile limbajului SQL
în diferite sisteme SGBD prezintã variante de tipuri de date specifice implementãrii
respective. De exemplu, SQL implementat de SQL Server adaugã tipul tinyint, ca numãr
întreg reprezentat pe 1 octet; în SGBD Oracle, tipul ºir de caractere de lungime variabilã
este numit varchar2, etc.
Standardul SQL2 nu suportã tipuri de date ºi operaþii definite de utilizator, dar
aceste trãsãturi au fost introduse în standardul SQL3 care defineºte, de fapt, modelul
obiect-relaþional de date. În momentul de faþã se poate observa cã majoritatea
producãtorilor de sisteme de baze de date relaþionale introduc treptat, de la o versiune la
alta, diferite caracteristici ale modelului obiect-relaþional cuprinse în standardul SQL3.
Domeniile atributelor în SQL2 se specificã pe baza tipurilor de date predefinite ale
limbajului SQL, deci sunt destul de depãrtate de noþiunea de domeniu relaþional, aºa cum a
fost descrisã în secþiunea precedentã, dat fiind cã nu se face nici o precizare a semnificaþiei
domeniului.
Standardul SQL2 prevede comanda CREATE DOMAIN, care atribuie un nume de
domeniu ºi unele constrângeri unui tip predefinit SQL2, dar aceastã comandã nu prea mai
este implementatã în sistemele de gestiune actuale, care preferã alte soluþii de definire a
domeniilor.
De exemplu, în SQL Server, se pot crea aºa-numitele “tipuri definite de utilizator”
(user-defined types), care sunt, de fapt, echivalente cu domeniile create cu comanda SQL
CREATE DOMAIN. Pentru aceasta se foloseºte o procedurã stocatã, scrisã în limbajul
Transact-SQL care este specific sistemului SQL Server ºi care extinde limbajul SQL. În
sistemele de baze de date Oracle 8i ºi Oracle 9i, se pot crea cu adevãrat tipuri de date noi,
folosind comanda CREATE TYPE, care permite gruparea sub un anumit nume a mai
multor atribute, de diferite tipuri (predefinite sau definite de utilizator), într-un mod
asemãnãtor cu definirea claselor din limbajele obiect-orientate. Aceste tipuri definite de
utilizator sunt folosite ca domenii ale atributelor (coloanelor) tabelelor. Pentru fiecare tip de
date nou definit, se pot prevedea metode, scrise într-unul din limbajele C, Java sau PL/SQL.
Aceste caracteristici reprezintã trãsãturile obiect-relaþionale ale sistemelor de baze de date
Oracle 8i ºi Oracle 9i. În sistemul PostgreSQL se pot crea, de asemenea, tipuri de date noi,
folosind comanda CREATE TYPE, iar tipurile nou create pot fi folosite ca domenii ale
atributelor.
Convenþiile sintactice care se vor folosi în acest capitol ºi în urmãtoarele pentru
prezentarea limbajului SQL ºi a limbajelor de programare dezvoltate pe baza acestuia sunt
prezentate în tabelul 2.3.
Convenþie sintacticã Utilizare
Litere mari Cuvinte cheie ale limbajului sau denumiri de tabele.
[ ] (paranteze drepte) Element opþional al instrucþiunii.
{ } (acolade) Element obligatoriu al instrucþiunii.
| (barã verticalã) Separã elementele din parantezele drepte sau acolade. Numai unul
din elementele separate
cu barã verticalã se pot introduce în instrucþiunea respectivã.
[,...n] Indicã faptul cã elementul precedent poate fi repetat de n ori.
Elementele repetate sunt
separate prin virgulã.
element1, Listã de n elemente de acelaºi tip.
............. Elementele repetate sunt separate prin virgulã.
elementn
lista_elemente Listã de elemente de acelaºi tip (separate prin virgulã)

Caracterele folosite pentru a specifica o anumitã convenþie sintacticã (paranteze,


bara verticalã, virgula, etc.) nu apar în instrucþiunile propriu-zise. Listele de elemente
(compuse din mai multe elemente separate prin virgulã) vor fi exprimate fie folosind una
cele trei din construcþiile de mai sus, care se potriveºte cel mai bine instrucþiunii respective.
Pe lângã aceste convenþii, pentru o prezentare cât mai concisã ºi mai uºor de înþeles a
instrucþiunilor, s-au mai adoptat ºi alte notaþii: denumiri sugestive ale elementelor sintactice,
renunþarea la detalii minore pentru a se putea urmãri caracteristicile de ansamblu, etc.

4.2.4 Instrucþiuni SQL de definire a datelor


Componenta de definire a datelor a limbajului SQL (numitã Limbajul de Definire a
Datelor - LDD) permite crearea (CREATE), modificarea (ALTER) ºi distrugerea (DROP)
obiectelor bazei de date: tabele de bazã (TABLE), tabele vedere (VIEW), indexuri
(INDEX), proceduri (PROCEDURE), etc. Majoritatea dialectelor limbajului SQL conþin
comenzile:
CREATE TABLE, CREATE VIEW, CREATE INDEX, CREATE
USER CREATE FUNCTION, CREATE PROCEDURE, CREATE
TRIGGER ALTER TABLE, ALTER VIEW, ALTER FUNCTION,
ALTER PROCEDURE DROP TABLE, DROP VIEW, DROP INDEX,
DROP USER DROP FUNCTION, DROP PROCEDURE, DROP
TRIGGER
În continuare vor fi descrise cele mai importante instrucþiuni SQL de definire a
datelor.
4.2.4.1 CREAREA TABELELOR SI A VEDERILOR
În limbajul SQL2 un tabel se creeazã folosind instrucþiunea CREATE TABLE, care
are urmãtoarea
sintaxã:
CREATE TABLE nume_tabel (
col1 dom1 [constrangeri_coloana],
col2 dom2 [constrangeri_coloana],
coln domn [constrangeri_coloana],
[constrangeri_tabel] );
Constrângerile impuse fiecãrei coloane (atribut), ca ºi constrângerile de tabel, sunt
opþionale ºi vor fi discutate în capitolul urmãtor.
De exemplu, tabelul ANGAJATI corespunzãtor relaþiei ANGAJATI (descrisã în
secþiunea precedentã) se poate defini astfel:
CREATE TABLE ANGAJATI (
Nume varchar(20),
Prenume varchar(20),
DataNasterii date,
Adresa varchar(50),
Functie varchar(20),
Salariu numeric);
Instrucþiunea CREATE TABLE defineºte atât un tip de relaþie (cu atributele
specificate) cât ºi o variabilã relaþie care iniþial este vidã (nu conþine nici un tuplu).
Tabelele create cu instrucþiunea CREATE TABLE sunt numite ºi tabele de bazã
(base tables); ele sunt memorate în fiºierele bazei de date ºi pot fi accesate pentru
introducerea, modificarea ºi regãsirea (interogarea) datelor.
Vederi (views). Un tabel vedere este un tabel virtual, care nu este memorat fizic în
fiºiere, ci reprezintã o selecþie (dupã un anumit criteriu) a datelor memorate în unul sau
mai multe tabele de bazã.
Datele (valorile atributelor) sunt memorate o singurã datã, în tabelele de bazã, dar
pot fi accesate atât prin tabelele de bazã cât ºi prin tabelele vederi. Instrucþiunea SQL de
creare a unui tabel vedere este:
CREATE VIEW nume_vedere AS (SELECT...);
Formatul comenzii SELECT va fi descris în capitolul urmãtor.
Un tabel vedere este întotdeauna actualizat ("la zi"), adicã orice modificare
efectuatã în tabelele de bazã se regãseºte imediat în orice tabel vedere creat pe baza
acestora.
4.2.4.2 MODIFICAREA SI STERGEREA TABELELOR
Comanda de modificare a tabelelor (ALTER TABLE) permite adãugarea sau
ºtergerea unor atribute, modificarea domeniilor unor atribute, precum ºi adãugarea,
modificarea sau ºtergerea unor constrângeri ale tabelului.
De exemplu, instrucþiunea de adãugare a atributului DataAngajarii în tabelul
ANGAJATI se scrie în felul urmãtor:
ALTER TABLE ANGAJATI ADD DataAngajarii Date;
Pentru ºtergerea unei coloane dintr-un tabel se foloseºte cuvântul cheie DROP în
comanda ALTER TABLE. De exemplu, pentru ºtergerea coloanei DataAngajarii din tabelul
ANGAJATI se introduce instrucþiunea:
ALTER TABLE ANGAJATI DROP DataAngajarii;
Instrucþiunile de ºtergere a tabelelor de bazã ºi a vederilor sunt:
DROP TABLE
nume_tabel;
DROP VIEW
nume_vedere;
4.2.5 INSTRUCÞIUNI SQL de manipulare a datelor
Instrucþiunile SQL de manipulare a datelor conþin una din comenzile: SELECT,
INSERT, UPDATE sau DELETE ºi vor fi studiate în continuare.
4.2.5.1 INSTRUCÞIUNEA SELECT
Instrucþiunea SELECT este instrucþiunea de interogare în limbajul SQL, prin care
se regãsesc informaþiile dorite din unul sau mai multe tabele ale bazei de date. Instrucþiunea
SELECT este foarte puternicã ºi are urmãtoarea sintaxã generalã:
SELECT [DISTINCT]
lista_coloane [FROM
lista_tabele] [WHERE
conditie]
[clauze_secundare];
Ca rezultat al instrucþiunii SELECT se obþine un tabel care conþine atributele
(coloanele) din lista_coloane ale acelor linii (tupluri) ale produsului cartezian al tabelelor
din lista_tabele pentru care expresia logicã conditie este adevãratã (are valoarea TRUE).
Se remarcã trei secþiuni (clauze) importante ale instrucþiunii de interogare:
SELECT, FROM ºi WHERE. Clauza SELECT defineºte coloanele tabelului rezultat.
Clauza FROM indicã unul sau mai multe tabele (o listã de tabele) din care se selecteazã
liniile tabelului rezultat. Clauza WHERE defineºte condiþia pe care trebuie sã o
îndeplineascã fiecare linie a tabelului rezultat. În afara acestor clauze, comanda SELECT
mai poate conþine ºi clauze secundare (ORDER BY, GROUP BY, HAVING), care permit
ordonãri sau grupãri ale tuplurilor (liniilor) rezultate, etc. Singura clauzã obligatorie este
SELECT; restul clauzelor sunt opþionale.
Clauza SELECT introduce lista coloanelor unor tabele sau expresii care vor fi
selectate ºi afiºate. Coloanele din listã trebuie sã aparþinã unuia din tabelele specificate în
clauza FROM. De exemplu, comanda urmãtoare va selecta numele ºi prenumele tuturor
angajaþilor din tabelul ANGAJATI:
SELECT Nume, Prenume FROM ANGAJATI;
Ca rezultat al instrucþiunii de mai sus se pot obtine douã sau mai multe linii identice,
dacã exista angajaþi cu acelaºi nume ºi prenume, deci rezultatul operaþiei nu este o
“relaþie” în sensul definiþiei din modelul relaþional. Pentru eliminarea liniilor duplicat se
introduce parametrul DISTINCT ºi atunci se eliminã liniile duplicat iar rezultatul este o
relaþie în sensul definiþiei din modelul relaþional. Deci instrucþiunea de mai sus se poate
scrie:
SELECT DISTINCT Nume,Prenume FROM ANGAJATI;
Dacã lista de atribute este un asterisc (*), atunci se selecteazã toate atributele
produsului cartezian al tabelelor indicate prin clauza FROM, care îndeplinesc condiþia din
clauza WHERE. De exemplu, instrucþiunea:
SELECT * FROM ANGAJATI;
permite selectarea tuturor coloanele ºi a liniilor din tabelul ANGAJATI.
În clauza SELECT se pot introduce ºi funcþii de totalizare (funcþii agregat).
Funcþiile agregat definite în limbajul SQL2 sunt date în tabelul urmãtor.

Funcþia Valoarea returnata


COUNT numãrul de linii ale
SUM rezultatului;
suma tuturor valorilor dintr-o
MAX coloanã cea mai mare dintr-o
valoarea
MIN coloanã cea mai micã dintr-o
valoarea
AVG coloanãvalorilor dintr-o
media
coloanã
De exemplu, comenzile urmãtoare vor afiºa numãrul de linii ale tabelului
ANGAJATI ºi salariul maxim, minim ºi mediu al angajaþilor:
SELECT COUNT(*) FROM ANGAJATI;
SELECT MAX(Salariu) FROM ANGAJATI;
SELECT MIN(Salariu) FROM ANGAJATI;
SELECT AVG(Salariu) FROM ANGAJATI;
Instrucþiunea SELECT poate sã conþinã chiar ºi numai clauza SELECT, deci fãrã sã
se refere la un tabel (printr-o clauzã FROM). În acest caz, comanda SELECT conþine o listã
de expresii pe care le evalueazã ºi rezultatele calculate sunt returnate ca o linie a unui tabel
ale cãrui coloane sunt chiar expresiile date.
În clauza SELECT se pot redenumi atributele (coloane ale tabelelor) sau se pot
specifica nume pentru expresii, folosind urmãtoarea sintaxã:
SELECT nume1 [AS] noul_nume1 [,...n] FROM lista_tabele [alte_clauze];
Se observã cã noul nume atribuit unei coloane (sau expresii) urmeazã vechiului
nume (sau expresiei), precedat (optional, depinzând de implementare) de cuvântul-cheie AS.
De exemplu, comanda urmãtoare va afisa numele angajatului denumit NumeAngajat ºi 80%
din salariul acestuia, denumit SalariuNet:
SELECT Nume NumeAngajat,Salariu*0.8 SalariuNet FROM ANGAJATI;
Clauza FROM este obligatorie dacã într-una din clauzele SELECT, WHERE sau
HAVING apar nume de coloane ale unor tabele. În acest caz, lista de tabele care însoþeºte
clauza FROM trebuie sã conþinã numele tuturor tabelelor (separate prin virgulã) ale cãror
coloane se folosesc. Dacã lista conþine mai mult de un tabel, atunci numele coloanelor din
clauza SELECT trebuie sã fie diferite ºi, dacã nu sunt diferite, se calificã cu numele
tabelului caruia îi aparþine, precedând numele atributului cu numele tabelului urmat de
operatorul “punct” (.). De exemplu:
SELECT ANGAJATI.Nume,SECTII.Nume FROM ANGAJATI,SECTII;
De retinut cã, deºi limbajul SQL este case-insensitive, totuºi este necesar ca numele
tabelului cu care se calificã numele unui atribut sã fie identic (inclusiv tipul de caracter,
majusculã sau nu) cu cel declarat în clauza FROM.
Clauza WHERE restrictioneazã tuplurile returnate ca rezultat la acele tupluri care
îndeplinesc condiþia introdusã de aceastã clauzã sub forma unei expresii logice.
O expresie logicã se construieste din valori logice, operatori logici (AND, OR,
NOT) ºi paranteze. O valoare logicã se obtine, în mod obiºnuit, ca rezultat al comparaþiei
între doi operanzi folosind un operator de comparaþie. Un operand poate fi un atribut
(nume de coloanã dintr-unul din tabelele introduse prin clauza FROM), o constantã,
valoarea unei expresii aritmetice sau o valoare returnatã de o funcþie. Operatorii de
comparaþie utilizaþi în clauza WHERE pot fi atât operatori aritmetici de comparaþie cât ºi
operatori SQL de comparaþie, aºa cum se poate vedea în instrucþiunile urmãtoare:
SELECT Nume,Prenume FROM ANGAJATI WHERE DataNasterii >
1968-01-01;
SELECT Nume,Prenume FROM ANGAJATI
WHERE Salariu BETWEEN 3000 AND 4000 AND Functie = ‘Inginer’;
Prima instrucþiune va afiºa toþi angajaþii care s-au nãscut dupã data de 1 Ianuarie
1968; cea de-a doua comandã va afiºa toþi angajaþii cu funcþia Inginer ºi salariul cuprins
între 3000 ºi 4000.

Clauza ORDER BY introduce numele atributului dupã care se face ordonarea liniilor
tabelului rezultat. Ordonarea se face în ordine crescãtoare în mod implicit sau dacã numele
atributului este urmat de cuvântul cheie ASC; dacã numele atributului este urmat de
cuvântul DESC, ordonarea liniilor se face în ordine descrescãtoare a valorilor acelui atribut.
Ordonarea liniilor astfel obþinutã este ordonare logicã, foarte utilã în prezentarea (afiºarea)
rezultatului ºi nu înseamnã ordonarea înregistrãrilor în fiºierele relaþiilor. De exemplu,
pentru afiºarea listei angajatilor ordonatã dupã numele acestora, se introduce comanda:
SELECT * FROM ANGAJATI ORDER BY Nume;
Clauza GROUP BY se foloseºte pentru gruparea rezultatelor funcþiilor agregat
(totalizatoare) în funcþie de valoarea uneia sau mai multor coloane.
Pentru aceasta, în instrucþiunea SELECT se introduce clauza GROUP BY, urmatã
de numele coloanei (sau al coloanelor) dupã valoarea cãrora se doreºte gruparea rezultatelor
funcþiei agregat. În acest caz, funcþia agregat se aplicã separat acelor linii care au aceeaºi
valoare a atributelor specificate de clauza GROUP BY.
De exemplu, salariul mediu calculat separat pe grupuri de angajati, fiecare grup
fiind compus din liniile care au aceeaºi valoare a atributului Functie, se obþine cu
urmãtoarea instrucþiune SQL:
SELECT AVG (Salariu) FROM ANGAJATI GROUP BY Functie;
Clauza HAVING. Funcþiile agregat (totalizatoare) nu pot fi utilizate în clauza
WHERE; de exemplu instrucþiunea urmãtoare (prin care se cere lista angajaþilor cu salariu
mai mare decât salariul mediu) este eronatã:
SELECT Nume,Prenume FROM ANGAJATI WHERE Salariu >= AVG(Salariu);
Pentru folosirea unei funcþii agregat într-o condiþie de selecþie se foloseºte clauza
HAVING. Clauza HAVING este asemãnãtoare clauzei WHERE, adicã introduce o
condiþie pe care trebuie sã o îndeplineasca tuplurile rezultat, ºi, în plus, permite utilizarea
funcþiilor agregat în expresia conditionalã. Exemplul de mai sus se scrie corect astfel:
SELECT Nume,Prenume
FROM ANGAJATI HAVING Salariu >= AVG (Salariu);
Instrucþiuni SELECT imbricate. Subinterogãri. Instrucþiunile SELECT se pot
imbrica pe mai multe niveluri, o instrucþiune având ca argument rezultatul unei altei
instrucþiuni, numitã subinterogare. Existã mai multe moduri de construire a
subinterogãrilor, una din formele cele mai frecvent folosite fiind urmãtoarea:
SELECT lista_atribute FROM tabel1
WHERE colx IN (SELECT colx FROM tabel2 WHERE conditie);
Într-o astfel de construcþie valoarea de comparaþie (pentru operatorul de
comparaþie IN) din clauza WHERE a primei instrucþiuni SELECT se defineºte printr-o
subinterogare care constã dintr-o altã instrucþiune SELECT. Alte forme de construire a
subinterogãrilor vor fi prezentate în capitolele urmãtoare.

Crearea uniunilor cu SQL.


Se utilizează pentru situaţiile în care datel se selectează din mai multe tabele. Se
utilizează structura JOIN ON care specifică tabelul care trebuie unit şi relaţia dintre
câmpuri.
Sintaxa:
SELECT [ALL|DIS TINCT|DISTINCTROW]
From nume_tabel {INNER|LEFT|R IGHT} JOIN tabel_legatura
ON criteriu_legatura
[ nume_tabel {INNER|LEFT|RIGHT} JOIN tabel_legatura
ON criteriu_legatura ]
[WHERE conditie]
[ORDER BY criteriu]
unde: nume_tabel {INNER|LEFT|RIGHT} JOIN tabel_legatura specifică
denumirea tabelului cuplat cu celelalte tabele. Fiecare tabel care participă într-o uniune
trebuie introdus înaintea clauzei JOIN. INNER defineşte o uniune internă, LEFT, RIGHT
definesc uniuni externe.
ON criteriu_legatura defineşte cele două câmpuri care trebuie unite şi relaţia
dintre ele.

Exemplu: Testaţi efectul instrucţiunii:

SELECT nume, studenti.marca, nota_fin, cod_disc


FROM studenti INNER JOIN [note] ON studenti.marca=note.marca
WHERE (studenti.cod_spec="CE") and (note.cod_disc=1407)
ORDER BY studenti.nume;
Tipurile de unire 1. (Join): Constă în includerea unui rând pentru fiecare posibila pereche de randuri
din cele doua tabele.

Varianta 1.

SELECT * FROM Table1, Table2

Example:
select * from Table1, Table2
Table1 Table2 c1 c2 c3 c4
c1 c2 c3 c4 a 1 c 3
a 1 c 3 a 1 d 4
b 2 d 4 b 2 c 3
b 2 d 4
2) Inner join: Se adauga o conditie de potrivire intre cele doua tabele:se selecteazã doar acele
inregistrari care au in comun aceeasi valoare intr+o anumite coloana. De obicei se verifica o conditie
dintre coloane comune celor doua tabele.

Syntax:

SELECT * FROM Table1 INNER JOIN Table2 on condition

SELECT * FROM Table1 INNER JOIN Table2 on Table1.c2=Table2.c4

Select Grupe.Denumire, Studenti.Nume, Studenti.prenume From Grupe INNER Join Studenti

On Grupe.codg=Studenti.codg

Example:

select * from Table1 inner


Table1 Table2 join Table2 on c2=c4
c1 c2 c3 c4 c1 c2 c3 c4
a 1 c 1 a 1 c 1
b 2 d 2 b 2 d 2

3) Outer Join

a) Left Outer Join: Include toate înregistrările din tabelul specificat în partea stanga a
clauzei LEFT OUTER, chiar daca nu se potrivesc.

Syntax:

SELECT * FROM Table1 LEFT JOIN Table2 on condition

Example:

select * from Table1 left join


Table1 Table2 Table2 on c2=c4
c1 c2 c3 c4 c1 c2 c3 c4
a 1 c 1 a 1 c 1
b 2 d 2 b 2 d 2
e 3 f 4 e 3 null null
b) Right Outer Join: A right outer join is the reverse of a left outer join. All rows from the
right table are returned. Null values are returned for the left table any time a right table row
has no matching row in the left table

select * from Table1 left join


Table1 Table2 Table2 on c2=c4
c1 c2 c3 c4 c1 c2 c3 c4
a 1 c 1 a 1 c 1
b 2 d 2 b 2 d 2
e 3 f 4 null null f 4
Example: Retrieve all the titles

SELECT Titles.TitleID, Titles.Name AS Title, Genres.Name AS Genre, Titles.Path


FROM
Genres
INNER JOIN Titles
ON Genres.GenreID=Titles.GenreID

Example: Select all titles and the play list they appear in (if a title does not appear in a play list, select null in
the PlaylistID column

SELECT Titles.TitleID, Titles.Name, PlaylistItems.PlayListID


FROM
Titles
INNER JOIN PlaylistItems
ON Titles.TitleID = PlaylistItems.TitleID

Using Where

Allows to specify conditions to use in order to filter the data.

Example: Retrieve all the titles of an author

SELECT Titles.TitleID, Titles.Name, Titles.Path


FROM
Titles
INNER JOIN TitleAuthors
ON Titles.TitleID=TitleAuthors.TitleID
INNER JOIN Authors
ON Authors.AuthorID=TitleAuthors.AuthorID
WHERE (((Authors.Name)=Author));

Using Group By

Combines records with identical values in the specified field list into a single record. A summary value is
created for each record if you include an SQL aggregate function, such as Sum or Count

Syntax

SELECT select_list
FROM table_list
WHERE condition
GROUP BY column_list

4.2.5.2 INSTRUCÞIUNEA INSERT


Instrucþiunea INSERT se foloseºte pentru introducerea datelor în tabele ºi are
urmãtoarea sintaxã: INSERT INTO
nume_tabel(col1,col2,...coln)VALUES(val1,val2,...valn);
Între valori ºi numele de coloane trebuie sã existe o corespondenþã unu la unu.
Valorile din listã pot fi constante (literale) sau expresii. De exemplu, introducerea unei linii
în tabelul SECTII se poate face cu instrucþiunea:
INSERT INTO SECTII (IdSectie,Nume,Buget)
VALUES (1,‘Productie’,4000000);
INSERT INTO GRUPE (Denumire, NrStud) VALUES („760 Informatica”, 23);
Lista de coloane poate sã lipseascã dacã se introduc valori în toate coloanele
tabelului, dar în aceastã situatie ordinea valorilor introduse trebuie sã respecte ordinea
atributelor. Aceasta ordine provine din ordinea de definire a atributelor prin instrucþiunea
CREATE TABLE, precum ºi din operaþiile ulterioare de alterare a tabelului respectiv, ºi se
poate afla printr-o instrucþiune DESCRIBE nume_tabel. De exemplu, introducerea unei
linii în tabelul ANGAJATI(IdAngajat,Nume,Prenume,DataNasterii,Adresa,Salariu), se
poate face cu instrucþiunea:
INSERT INTO ANGAJATI
VALUES(100,‘Mihailescu’,
‘Mihai’,‘1950-04-05’,‘Craiova’,3000);2.2.5.3
INSTRUCTIUNEA UPDATE
Instrucþiunea UPDATE permite actualizarea valorilor coloanelor (atributelor) din
una sau mai multe linii ale unui tabel. Aceasta are sintaxa:
UPDATE nume_tabel SET col1 = expr1 [,...n] [WHERE conditie];
Clauza WHERE impune ca actualizarea valorilor coloanelor sã se efectueze numai
asupra acelor linii care îndeplinesc condiþia datã. Dacã este omisã clauza WHERE, vor fi
modificate valorile coloanelor din toate liniile tabelului.De exemplu, pentru a modifica linia
introdusã mai sus în tabelul ANGAJATI, se poate introduce instrucþiunea:
UPDATE ANGAJATI
SET Adresa = ‘Bucuresti,Str. Victoriei’ WHERE IdAngajat = 100;
Update Rezultate SET Notafin = IIF()

UPDATE REZULTATE SET NotaEx = NotaEx +1 WHERE CodCurs=2;


UPDATE REZULTATE SET NotaFin = (2*NotaEx + NotaLab)/2 WHERE
NotaEx>=5 And NotaLab>=5 ;

UPDATE REZULTATE SET NotaFin = 4 WHERE NotaEx <5 Or NotaLab<5 ;

UPDATE REZULTATE SET NOTAEX = NOTAEX +1 WHERE CodCurs=1 And


NotaEx=4

UPDATE STUDENTI SET ANSTUD = ANSTUD +1 WHERE NUME LIKE


„M*”

UPDATE REZULTATE SET NOTAEX = NOTAEX +1 WHERE CodCurs =1 Or


CodCurs=4 Or CodCurs =8 Or CodCurs =9;
UPDATE REZULTATE SET NOTAEX = NOTAEX +1 WHERE CodCurs IN
(1,4,8,9);
4.2.5.4 INSTRUCTIUNEA DELETE
Instrucþiunea DELETE permite ºtergerea uneia sau mai multor linii dintr-un
tabel ºi are forma: DELETE FROM nume_tabel [WHERE conditie];
Din tabel se ºterg acele linii care îndeplinesc condiþia datã în clauza WHERE. Dacã
este omisã clauza WHERE, vor fi sterse toate liniile din tabel.
De exemplu, pentru a sterge din tabelul ANGAJATI toþi angajatii care au numele
Ionescu, se introduce instrucþiunea:
DELETE FROM ANGAJATI WHERE Nume =‘Ionescu’;
DELETE FROM STUDENTI WHERE Month(DataN)=8;
DELETE FORM STUDENTI WHERE YEAR(DATE()) – YEAR(DATAN) >=25
SELECT NUME, PRENUME FROM STUDENTI WHERE DATAN IS NULL

În aceastã secþiune au fost prezentate consideraþii generale asupra comenzilor de


definire ºi manipulare a datelor prevãzute în standardul SQL2. Alte comenzi SQL
vor fi prezentate pe parcursul secþiunilor ºi a capitolelor urmãtoare, o datã cu
introducerea noþiunilor la care se referã.

In plus, existã numeroase extensii, opþiuni ºi detalii ale comenzilor, unele


depinzând de implementarea limbajului în fiecare ti ºi versiune de SGBD. Pentru aceste
aspecte este necesar sã fie consultatã documentaþia sistemului respect

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