Documente Academic
Documente Profesional
Documente Cultură
De
aceea, e lesne de observat faptul că există o mulțime de combinații care pot fi realizate. Spre exemplu, se
examinează o altă instrucțiune:
Se selectează toate câmpurile tabelului discipline, pentru care (WHERE) numărul de ore planificate
pentru o disciplina (Nr_ore_plan_disciplina) este egală cu 80 și (AND) identificatorul disciplinei
(Id_disciplina) este mai mare de 110. Astfel, este formulată interogarea care îndeplinește condiția din
clauza WHERE.
Uneori nu se cunosc valorile exacte pe care le căutăm. Utilizând operatorul LIKE este posibil să
selectam rândurile care se potrivesc cu un model specificat de caractere.
În următorul exemplu, este formulată o interogare care cere ca înregistrările să fie reprezentate sub
formă de grid, cu câmpurile Id_Disciplina, Disciplina, unde câmpul Disciplina începe cu litera (simbolul)
'S' și rezultatul să fie ordonat pe câmpul Id_Disciplina în ordine descendentă.
După cum se poate observa, clauza LIKE testează dacă valoarea parțială a unui șir de caractere
coincide cu un șablon definit de utilizator. Această clauza face uz de caracterul procent (%) în calitate de
șablon, care denotă o secvență de lungime arbitrară de caractere ce pornește din această poziție.
Clauza ORDER BY introduce numele câmpului, după care se face ordonarea liniilor rezultate.
Ordonarea este, implicit, în ordine crescătoare. Dacă numele câmpului este urmat de cuvântul DESC,
ordonarea liniilor se face în ordine descrescătoare a valorilor acelui câmp.
81
Acestea folosesc următoarea sintaxă:
În exemplul de mai jos, sortarea este executată, de asemenea, în mod crescător, după câmpul
Nr_ore_plan_disciplina. În setul de rezultate sunt 9 linii și nu 3. Cu ajutorul opțiunii WITH TIES mai
multe discipline care au același numărul de ore ca și cele TOP(3) au fost incluse în rezultat [56].
82
4.4. Interogări cu joncțiuni și funcții
Cea mai folosită instrucțiune SQL pentru obținerea informațiilor din mai multe tabele relaționate
este JOIN, sau joncțiunea. Instrucțiunile JOIN pot fi interne sau externe.
Deseori, pentru a obține un rezultat complet, este necesară selectarea datelor din două sau mai multe
tabele. De obicei, tabelele din baza de date sunt legate între ele prin chei. Este important, îndeosebi, rolul
cheii primare care face ca coloanele ce o constituie să posede o valoare unică pentru fiecare rând.
De exemplu, este necesar să se afișeze lista profesorilor și identificatorii disciplinelor care se predau
la grupa Id_Grupa = 1. Câmpul Nume_Profesor se află în tabelul profesori. Identificatorii disciplinelor și
grupelor asociate profesorilor se află în tabelul studenti_reusita.
83
Instrucțiunea SELECT cu INNER JOIN are următoarea formă generală:
84
tupluri în tabelul studenti_reusita, care nu coincid pe câmpurile de joncțiune din tabelul profesori, acestea
sunt, de asemenea, afișate. Coloanele tabelului din stânga se completează cu valori nule.
Restricțiile în clauza WHERE sunt adăugate doar pentru a reduce setul de date rezultant, că el să fie
mai citibil din imagine. Instrucțiunea de mai sus este echivalentă cu instrucțiunea:
SELECT d.Disciplina,
p.Nume_Profesor,
p.Prenume_Profesor
FROM discipline d, profesori p
WHERE d.Disciplina LIKE 'Practica%'
AND p.Prenume_Profesor LIKE 'M%' ORDER BY p.Nume_Profesor;
Produsul Cartezian a două tabele asociază fiecare rând din primul tabel cu toate rândurile din tabelul
al doilea. Rezultatul păstrează toate rândurile tuturor tabelelor joncțiunea, obținând toate combinațiile
posibile ale acestora. Desigur, dacă nu există duplicate în tabelele originale, toate rândurile din rezultat vor
fi, de asemenea, unice.
Un produs Cartezian are tendința de a genera un număr mare de rânduri, iar rezultatul, de regulă, rar
este util. Acesta poate parveni accidental în cazul nespecificării criteriilor de joncțiunea, în particular,
atunci când se utilizează sintaxa SQL89. Prin urmare, deseori, trebuie să fie prezentă o condiție de
valabilitate a joncțiunii, fapt ce transformă produsul Cartezian într-un alt tip de joncțiune.
Excepție fac doar cazurile în care este nevoie de combinarea tuturor rândurilor din toate tabelele.
Produsul Cartezian poate fi folosit, de asemenea, pentru executarea unor teste în cazul în care este
necesară generarea unui număr mare de rânduri pentru simularea unui număr rezonabil de date.
86
O funcție este constituită dintr-o serie de argumente, care sunt utilizate în procesare. Sintaxa de bază
este următoarea:
87
Să se observe că, în acest exemplu, este o singură noutate: înainte de câmpul Disciplina, s-a scris
funcția UPPER, care transformă caracterele minuscule în caractere majuscule. În afară de aceasta, în
gridul interogării, câmpul care prezintă disciplinele nu are un nume.
În clauza SELECT, se pot redenumi câmpuri sau se pot specifica nume pentru expresii, folosind
următoarea sintaxă:
Crearea unui nou câmp calculat pe baza câmpurilor din tabelele implicate în interogare se
realizează, în exemplul precedent, prin numele Tip_majuscule.
88
SQL permite sintetizarea datelor din baza de date prin utilizarea unor funcții de grup asupra
coloanelor. O funcție de grup primește ca argument o întreagă coloană (sau coloane) și furnizează ca
rezultat o singură valoare, care sintetizează datele din coloana respectivă. Evident că instrucțiunile
SELECT cu funcții bloc sunt mai complexe.
Se examinează un exemplu care utilizează 3 funcții: pentru a obține valoarea medie a unei coloane
numerice, pentru a obține valoarea maximă dintr-o coloană și pentru a obține valoarea minimă dintr-o
coloană.
În acest exemplu, SGBD-ului i se solicită să calculeze numărul de ore mediu alocat pentru
disciplinele predate la facultate, dar și valoarea maximă a orelor pentru o disciplina, și valoarea minimă a
orelor înregistrată, făcând uz de coloanele logice Nr_ore_medie, Nr_ore_maxim, Nr_ore_minim,
respectiv.
Funcția COUNT este ușor diferită de celelalte și are 3 formate.
COUNT(*) întoarce numărul de rânduri dintr-un tabel care satisfac criteriul de selecție, incluzând
rândurile duplicat și rândurile ce conțin valori nule. În exemplul de mai jos, structura instrucțiunii este
mult mai simplă: este solicitat, în calitate de rezultat, numărul de rânduri ale tabelului discipline.
89
Atunci când se apelează la funcții agregate în clauza SELECT se utilizează, de obicei, și clauza
GROUP BY pentru a separa informația în grupuri distincte.
Clauza GROUP BY se folosește pentru a grupa rezultatele funcțiilor de grup după valoarea uneia
sau mai multor coloane. Dacă se dorește calculul unei valori pe grupe de linii, atunci se introduce clauza
GROUP BY, urmată de numele uneia sau mai multor coloane. În acest caz, funcția se aplică separat acelor
linii care au aceeași valoare a coloanelor listate de clauza GROUP BY.
Astfel, în exemplul de mai jos, sunt prezentate valorile câmpului Nume_Profesor, în același timp,
este calculat numărul mediu, maxim și minim de ore la o disciplină, grupate după profesor
(Nume_Profesor).
Clauza HAVING operează la nivel de grupuri ce au fost create, în prealabil, cu clauza GROUP BY.
Clauza HAVING este asemănătoare clauzei WHERE. WHERE acționează asupra tuturor câmpurilor ce
îndeplinesc condiția specificată, în timp ce HAVING acționează asupra grupurilor.
90
Cu ajutorul clauzei HAVING, se pot pune condiții pe grupurile de linii asociate cu fiecare valoare a
coloanelor de grupare. Doar grupurile care satisfac condiția sunt afișate în rezultatul interogării.
Exemplul de mai jos este similar cu cel precedent, având o singură deosebire: se afișează numai
acele valori ale coloanei Suma_balurilor_acumulate, care depășesc suma 2000.
Trebuie menționat că clauza HAVING trebuie să preceadă întotdeauna clauza ORDER BY.
91
Al doilea tip de subinterogare este evaluat invers, adică interogarea externă furnizează valori cererii
interne, iar rezultatele subinterogării sunt transferate cererii externe. Subinterogările corelate care apar în
clauza WHERE a unei interogări au următoarea formă generală:
92
…{expresie|(expresie1 [, expresie2 …])}
{>|<|=|>=|<=|<>} (<subinterogare>)
Să se observe că interogarea conține, în afară de cei doi operanzi, un operator. Operatorul ce
intervine în specificarea condiției reprezintă un operator de comparație (=, >, >=, <, <=, <>) care se aplică
numai în cazul în care subinterogarea returnează o singură valoare sau o singură linie de valori (definită pe
una sau mai multe coloane).
Predicatul este evaluat cu valoarea TRUE, în cazul în care comparația (indicată de unul din
operatorii de comparație) rezultatului expresiei (expresiilor) cu cel returnat de subinterogare, este TRUE.
În caz contrar, se evaluează la FALSE. Dacă interogarea subordonată nu produce nicio valoare, predicatul
se evaluează la valoarea NULL. Dacă subinterogarea returnează mai mult de o valoare (mai multe linii
definite pe o coloană, sau cel puțin o linie definită pe mai multe coloane) se produce o eroare de executare.
Următorul exemplu de cod reprezintă o subinterogare scalară, care determină lista de discipline care
are numărul maxim de ore din tot tabelul discipline.
Această interogare este destul de corectă, deoarece valoarea scalară a numărului de ore se compară
cu subinterogare care returnează o singură valoare. Ca rezultat, se obțin 2 înregistrări.
Cu toate acestea, în cazul în care se scrie următoarea interogare referitoare la întrebarea cu privire la
anumite valori din subinterogare:
Sistemul a afișat un mesaj de eroare, indicând faptul că pot fi obținute la subinterogare mai multe valori.
93
…{expresie|(expresie1 [, expresie2 …])}
[NOT] IN (<subinterogare>)…
Din sintaxa generală, se observă că există două forme ale predicatului cu includerea operatorului IN.
Predicatul, în forma sa mai simplă, presupune că, în partea stângă a operatorului IN, se poate găsi o
expresie, iar a două variantă presupune că partea stângă este constituită dintr-o linie de expresii.
Operatorul NOT IN verifică neapartenența la o mulțime.
Predicatul este evaluat la TRUE, dacă, în subinterogare, se găsește vreo linie egală cu cel din stânga
operatorului IN. În caz contrar, este evaluat la FALSE (chiar dacă subinterogarea nu întoarce nicio linie).
Dacă subinterogarea întoarce unele linii nule, iar restul liniilor sunt distincte de linia din stânga
operatorului IN, predicatul este evaluat la NULL.
O interogare imbricată poate fi o alternativă sintactică a unei expresii cu joncțiuni. Interogarea de
mai jos, afișează lista profesorilor (identificator, nume, prenume) care nu predau la grupa 'CIB171.'
94
Se consideră rezultatul subinterogării. Predicatul
Id_Profesor = ANY
(SELECT DISTINCT Id_Profesor
FROM studenti_reusita p JOIN grupe g ON p.Id_Grupa=g.Id_Grupa
WHERE Cod_Grupa = 'CIB171');
întoarce valoarea TRUE, dacă identificatorul specificat de coloana Id_Profesor, din interogarea principală,
va figura în lista de valori a tabelului studenti_reusita (returnată de subinterogare). Datorită utilizării
predicatului NOT, valoarea TRUE va fi obținută cu excepția cazului în care profesorul este în listă. Acest
predicat este verificat pentru fiecare linie din interogarea principală, care returnează toate Id-urile
profesorilor în tabelul profesori.
95
Fie se scrie următoarea interogare, care afișeze numele și prenumele profesorului cu identificatorul
mai mare decât al profesorilor care predau la grupa 'CIB171'.
96