Documente Academic
Documente Profesional
Documente Cultură
Lucrarea 3
1
CUPRINS
Cuprins…………………………………………………………………………………….1
1. Introducere in SQL………………………….………………………………………….2
1.1. Crearea Bazei de date..…………………………………………………..……….4
2. Subinterogari si intrebuintarea lor. Construirea unei subinterogari………………...…..9
2.1. Subinterogari de tip single-row……………………………….......................10
2.1.1. Subinterogari de tip single-row intro clauza WHERE…......................…10
2.1.2. Folosirea functiilor agregate. Subinterogari de tip Single-Row intr-o clauza
SELECT …………..…………………………………..……………………………....…15
2.2. Subinterogari Nested ……………………………………………..………...18
3. Subinterogari Corelate ..………………………….…………………………………...20
4. Folosirea EXISTS, ANY, ALL. Subinterogari de tip Multi-Row…...………………..25
4.1.Operatorul IN……………………………………………...……….……..….25
4.2. Operatorii ALL si ANY………………………………………………..…....25
4.3. Operatorul EXISTS………………………………………………….........................29
4.4. Valori NULL………………………………………………………………...31
4.5. Actiuni DML care folosesc subinterogari…………………….......................32
5. Rezumat……………………………………………………………….........................34
6. Exercitiu complex…………………………………………………….……………….35
7. Bibliografie…………………………………………………………………………....37
2
Subinterogari. Incapsularea instructiunii SELECT
1. Introducere
O baza de date este o colectie de inregistrari, corelate din punct de vedere logic, care
reflecta un anumit aspect al lumii real si este destinata unui anumit grup de utilizatori. In aceste
sens, bazele de date pot fi create si mentinute manual (fisele de evidenta a cartilor dintro
biblioteca) sau computerizat, asa cum sunt majoritate bazelor de date din ziua de azi.
Utilizatorul unei baze de date are posibilitatea de a efectua diferite operatiuni asupra bazei
de date cum ar fi:
Limbajul de interactiune cu o baza de date este SQL. SQL (Structured Query Language -
Limbajul Structurat de Interogare) reprezinta un limbaj ce are ca scop intretinerea unui sistem de
baza de date relational (RDBMS). Acesta permite folosirea tuturor operatiunilor asupra unei baze
de date, mentionate mai sus, precum si control asupra accesului datelor.
Pentru a avea acces la baza de date, mai intai trebuie sa ne logam din Start> All
Programs> Oracle Database 10g Express Edition> Go To Database Homepage. Logarea o
facem pe userul alex cu parola oracle.
3
Dupa logare o sa intram in prima pagina, adica meniul principal:
4
Si o sa selectam SQL->SQL Commands->Enter Commands, de unde o sa dam comenzile
de SQL pentru baza noastra de date.
Pentru exemplificarea expresiilor din lucrare vom folosi tabela CLIENTI, care contine
coloanele ID (Numarul unic de identificare al clientului, care este si PRIMARY KEY pentru
tabela CLIENTI), NUME (Numele de familie al clientului), PRENUME (Prenumele clientului),
DATA_NASTERE (Data nasterii a clientului), SEX (Sexul clientului M/F), ADRESA (Adresa
clientului), TIP_ABONAMENT (Tipul abonamentului ales de client care poate fi: Pinguin,
Girafa, Elefant, Camila sau Balena) si PRET (Costul abonamentului ales de client care depinde
de tipul abonamentului dupa cum urmeaza: Pinguin = 5$, Girafa = 10$, Elefant = 15$, Camila =
20$, Balena = 100$) si TELEFON (Numarul de telefon al clientului).
Prima metoda este folosirea GUI-ului. Dupa ce se face logarea cu User si Password, se
intra la Home>Object Browser>Create>Table dupa care vom selecta numele si tipul coloanelor
precum si scala acestora, si daca dorm sa nu fie NULL. Aceasta optiune o sa o folosim doar in
cazul ID-ului, deoarece, el fiind PRIMARY KEY nu poate fi niciodata NULL.
5
Fig 2 – Selectarea PRIMARY KEY-ului.
A doua metoda de creare a tabelei CLIENTI este folosirea liniei de comanda SQL.
Aceasta este metoda indicata de creare a unei tabele, dar este mult mai putin user friendly decat
prima metoda, si necesita mai multe cunostine de SQL.
6
Dupa crearea tabelei avem nevoie sa o populam cu un numar de intrari, care ne vor ajuta
in exemplificarea expresiilor ce contin subinterogari. Si in acest caz, putem sa facem popularea in
doua feluri: fie folosind Oracle GUI, fie folosind linia de comanda SQL.
Pentru a folosi Oracle GUI ca sa populam tabela, trebuie mai intai sa selectam tabela
CLIENTI, dupa care sa selectam Data>Insert Row. Ne va aparea o fereastra care contine exact
campurile necesare popularii tuturor coloanelor din tabel.
De asemenea, aceeasi introducere de date o putem executa si din linia de comanda SQL,
folosind expresia INSERT:
7
Fig 6 – Crearea Intrarii si afisarea tabelei Clienti
Pentru a popula tabela vom folosi linia de comanda SQL din cadrul Oracle GUI. Tabela
CLIENTI in forma finala va arata in urmatorul fel:
8
Fig 7 – Tabela Clienti
9
2. Subinterogari si intrebuintarea lor. Construirea unei
subinterogari
Rezultatul unei subinterogari poate sa fie format dintro singura valoare (subinterogare
single-row), mai multe valori (subinterogare de tip multiple-row) sau chiar multiple coloane de
date (subinterogare de tip multiple-column). Mai sunt de asemenea si alte tipuri de subinterogari,
dupa cum se vede in tabelul 1.
10
Subinterogare Descriere
Single-row Intoarce, pentru interogarea externa, un singur
rand de rezultate corespunzatoare unei singure
coloane
Multiple-row Intoarce, pentru interogarea externa, mai multe
randuri de rezultate
Multiple-column Intoarce, pentru interogarea externa, mai multe
coloane de rezultate
Subinterogare corelata Creaza o referinta la coloana interogarii externe
si executa subinterogarea o data pentru fiecare
rand al interogarii externe
Subinterogare necorelata Intai, executa subinterogarea dupa care trimite
valorile la interogarea externa
Subinterogare DML Foloseste o subinterogare pentru a determina
randurile afectate de actiunea DML
Prima metoda este cea clasica, fara folosirea subinterogarilor. Sa presupunem ca vrem sa
aflam toate persoanele care au acelasi tip de abonament ca si Cimpoiu Tudor. In mod normal ar
trebui sa facem aceasta interogare din doi pasi. Mai intai facem o interogare ca sa vedem ce tip de
abonament are Cimpoiu Tudor.
11
Si, ni se va intoarce rezultatul:
Dupa ce am aflat ca abonatul are abonamentul Elefant, putem trece la etapa a doua si
anume, construirea interogarii care ne va arata ceea ce vrem sa stim de fapt.
Acelasi rezultat putem sa-l obtinem si daca folosim o singura expresie SQL de tipul unei
subinterogari Single-Row. O astfel de subinterogare este potrivita pentru acest exemplu deoarece
vrem sa obtinem un rezultat, pentru care avem nevoie sa aflam o valoare necunoscuta din baza de
date si din cauza ca dorim ca interogarea interna sa intoarca doar un singur rezultat.
12
Si vom obtine acelasi rezultat:
Se poate observa ca mai intai se executa interogarea interna, iar rezultatul acesteia este o
singura valoare care este trimisa catre interogarea externa. Apoi, interogarea externa este
executata si ni se intorc toate persoanele care au acelasi tip de abonament ca Cimpoiu Tudor.
Folosind o singura expresie SQL, putem elimina interactiunea cu utilizatorul in rezolvarea acestei
sarcini. In plus, subinterogarea permite interogarii externe sa arate intotdeauna ce persoane au
acelasi tip de abonament, chiar daca abonamentul se schimba.
In cazul subinterogarilor, pentru Oracle 10g, operatorii sunt cei care indica daca cream o
subintergodare de tip single-row sau multiple-row. Operatorii pentru Single-row sunt =,
>,<,<=,=> sau <>. Desi alti operatori, cum ar fi IN, sunt permisi, operatorii de tip single-row sunt
cei care instiinteaza Oracle 10g ca rezultatul subinterogarii este o singura valoare. Daca rezultatul
intors este reprezentat prin mai multe valori, si nu una singura, expresia SELECT nu va functiona
si va da eroare.
13
Si o sa intampinam urmatoarea eroare:
Aceasta eroare se intampina in cazul folosirii functiilor agregate, din cauza urmatoarei
reguli: Daca un camp neagregat este folosit in combinatie cu o functie de grup in cadrul unei
expresii SELCT, campul trebuie folosit si cu o clauza de tip GROUP BY. Dar, in acest exemplu
folosirea clauzei GROUP BY nu are niciun sens. Daca este adaugata o clauza GROUP BY care
sa contina coloana Tip_Abonament, fiecare abonament ar fi in propriul sau grup deoarece fiecare
abonament eset diferit. Cu alte cuvinte, rezultatul ar fi acelasi ca si cand am folosi expresia
SELECT Tip_Abonament, Pret in cadrul interogarii.
Astfel, pentru a afla cel mai scump abonament, trebuie sa folosim o subinterogare pentru
a determina cel mai mare Pret al unui abonament. Pretul obtinut poate fi apoi folosit de o
interogare externa, si rezultatul dorit sa fie afisat.
In acest caz, se obtin doua raspunsuri, deoarece abonamentul Balena apare de doua ori in
cadrul tabelei CLIENTI.
In cazul folosirii subinterogarilor, putem introduce mai multe subinterogari in cadrul unei
singure expresii SELECT. De exemplu, sa spunem ca pe langa cel mai mare pret de abonament,
14
dorim sa aflam si cine sunt cei care il detin, si daca avem vreun abonat care are este mai batran
decat abonatul Hamac Laurentiu (pentru promotii).
Se poate observa ca ambele interogari sunt complete deoarece contin minimul necesar
pentru o interogare si anume: o clauza SELECT si o clauza FROM. Deoarece ambele sunt
subinterogari ele sunt introduse intre paranteze. Prima subinterogare determina care este
abonamentul cel mai mare si intoarce o valoare pentru prima conditie a interogarii externe, iar a
doua subinterogare determina daca avem un abonat mai batran decat Hamac Laurentiu. Deoarece
cele doua conditii ale clauzei WHERE externe se combina, si se aplica operatorul logic AND,
ambele valori ale subinterogarilor trebuiesc sa fie indeplinite pentru ca interogarea externa sa
intoarca un rezultat. In acest exemplu interogarea gaseste un rezultat, pentru care afiseaza numele
si prenumele lui, precum si tipul abonamentului si costul acestuia.
Aceasta actiune se poate indeplini folosind subinterogari in cadrul unei clauze SELECT,
care calculeaza pretul mediu al abonamentelor. Cand o subinterogare de tip Single-Row este
introdusa intro clauza SELECT, rezultatele subinterogarii sunt afisate la iesirea interogarii
15
externe. Pentru a include o subinterogare intro expresie SELECT, se foloseste virgula pentru a
separa subinterogarea de coloanele tabelului, ca si cum am afisa o coloana normala. Se poate,
chiar si adauga rezultatului subinterogarii un alias de coloana.
Expresia va fi urmatoarea:
TO_CHAR este folosit pentru a rotunji valoarea pretului mediu, iar 99.99 este formatul
specificat. Am dat un alias coloanei, de forma “Pret Mediu”. Tabela rezultata este urmatoarea:
Se poate vedea valoarea medie a costului unui abonament, si compara cu costul unui tip
de abonament. Pentru calcularea pretului mediu al unui abonament, interogarea externa SELECT
include atat Tipul Abonamentului, cat si Pretul, precum si subinterogarea creuta. Costul mediu
este afisat pentru fiecare rand in parte, putand compara valoarea unui tip de abonament cu costul
16
mediu. Daca nu folosim un alias, rezultatul subinterogarii este afisat in heading-ul coloanei noi,
iar acest lucru este destul de neplacut.
Si o sa obtinem tabela:
17
2.2. Subinterogari Nested
Cel mai des intalnit motiv pentru folosirea subinterogarilor nested este crearea unui lant
de date. De exemplu, vrem sa aflam ce client are cel mai mare abonament, mai batran de 40 de
ani:
O sa ni se intoarca rezultatul:
18
- Pentru a afla care este cel mai scump abonament o sa aflam mai intai cine este cel mai batran
abonat care are abonamentul cu cel mai mare pret. Dupa ce aceasta subinterogare intoarce un
raspuns, acesta este trimis la nivelul superior si tot asa, pana aflam numele abonatului, si anume:
Gigi Becali.
19
3. Subinterogari Corelate
Pentru a putea exemplifica acest tip de subinterogari trebuie sa mai cream o a doua baza
de date, care va contine ce extraoptiuni au abonatii. Tabelul se va numi EXTRA si va contine
urmatoarele coloane: ID (care este si PRIMARY KEY), NUME (Numele abonatului),
PRENUME (Prenumele abonatului), EXTRAOPTIUNI (o descriere a extraoptiunilor fiecarui
client) si TOTAL (costul total al extraoptiunilor).
Crearea tabelei o vom face din Oracle GUI. Vom crea astfel urmatoarele coloane pentru
tabela EXTRA:
Dupa ce am creat tabela EXTRA, o vom popula cu extraoptiuni pentru fiecare abonat,
daca este cazul. Dupa populare tabela va avea urmatoarea forma:
20
Cum am mentionat mai sus subinterogarile corelate ne permit sa folosim o referinta
externa cu unele rezultate surprinzatoare. Luam ca exemplu urmatoarea interogare:
21
Se poate observa ca tabela obtinuta seamana foarte mult cu tabela obtinuta din urmatorul
JOIN:
22
Se poate observa ca rezultatele obtinute in urma celor doua subinterogari sunt identice.
Subinterogarile corelate se comporta foarte mult ca un join. Corelarea se obtine prin folosirea
unui element din interogare in subinterogare. In acest exemplu corelarea a fost obtinuta de:
In aceasta comanda se face comparatia intre C.Id, din tabela din interiorul subinterogarii,
si E.Id care apartine tabelei exterioare interogarii noastre. Deoarece E.Id poate avea o valoare
diferita pentru fiecare rand, subinterogarea corelata se executa pentru fiecare rand in parte.
In acest exemplu, fiecare rand din tabelul Extra este procesat in raport cu criteriul din
subinterogare. Aceasta operatie intoarce fiecare valoare a coloanei ID pentru fiecare rand din
tabelul Clienti pentru care E.Id=C.Id. Acest exemplu functioneaza, deoarece am intors o singura
valoare pentru fiecare rand.
In urmatorul exemplu, intoarcerea pretului abonamentului si compararea lui cu numele
clientului o sa intoarca urmatorul rezultat:
23
In acest caz apare o eroare de conversie, ceea ce duce la afisarea unui mesaj de eroare, si
implicit a nereturnarii niciunui rezultat.
Expresia SELECT de mai sus a cauzat in sistemul meu de operare Windows o eroare de
tip General Protection Fault. Sistemul SQL, pur si simplu nu poate corela toate coloanele din
tabela Clienti cu un operator =.
24
4. Folosirea EXISTS, ANY, ALL. Subinterogari de tip Multi-Row
Subinterogarile de tip Multi-Row sunt interogari introduse in alte interogari care pot sa
intoarca ca rezultat mai multe randuri, care sa fie folosite de interogarea parinte. Acest tip de
subinterogari sunt utilizate cel mai des in cadrul clauzelor de tip WHERE sau HAVING.
Principala regula de care trebuie sa tinem cont atunci cand lucram cu subinterogari Multi-Row
este aceea ca trebuie sa folosim operatori multi-rand. Daca este utilizat un operator de tipul
single-row, iar subinterogarea intoarce mai mult de un singur rand, Oracle 10g va intoarce un
mesaj de eroare, iar expresia SELECT va esua. Operatorii de tip multi-rand sunt IN, ALL si
ANY, de care o sa vorbim in cele ce urmeaza.
4.1.Operatorul IN
Dintre cei trei operatori multi-rand, operatorul IN este folosit cel mai des. Sa presupun ca
vreau sa arat ce barbat si ce femeie au cel mai scump abonament din categoria lor. Voi folosi
comanda:
Se poate observa ca cel mai mare abonament detinut de un barbat este cel de 100 de euro,
iar cel mai scump abonament detinut de o femeie este cel de 15 euro.
Acesti doi operatori trebuiesc combinati cu alti operatori de comparatie pentru a trata
rezultatul unei subinterogari ca un set de mai multe valori, in loc de o singura valoare. Prin
combinarea lor, obtinem urmatorul efect:
25
Operator Descriere
>ALL Mai mult decat valoarea cea mai mare
returnata de subinterogare
<ALL Mai putin decat valoarea cea mai mica
returnata de subinterogare
<ANY Mai putin decat valoarea cea mai mare
returnata de subinterogare
>ANY Mai mult decat valoarea cea mai mica
returnata de subinterogare
=ANY Egal cu orice valoare returnata de
subinterogare(similar cu IN)
- Daca operatorul ALL este folosit in combinatie cu simbolul “mai mare decat”( >), interogarea
externa cauta toate inregistrarile care au o valoare mai mare decat cea mai mare valoarea intoarsa
de subinterogare (cu alte cuvinte, mai mare decat toate valorile returnate)
- Daca operatorul ALL este folosit in combinatie cu simbolul “mai mic decat”( <), interogarea
externa cauta toate inregistrarile care au o valoare mai mica decat cea mai mica valoarea intoarsa
de subinterogare (cu alte cuvinte, mai mica decat toate valorile returnate)
Pentru a vedea ce intrebuintare are operatorul ALL, vom da exemplu urmatoarea comanda
care mai tarziu o vom folosi ca o subinterogare. Aceasta intoace valorile abonamentelor Elefant si
Balena, adica cele mai scumpe abonamente.
26
Acum, sa presupnem ca vrem sa aflam daca exista alte abonamente care sunt mai ieftine
decat cele doua. O abordare ar fi sa folosim functia MIN intro subinterogare pentru a afla ceea ce
dorim. O alta abordare insa, este folosirea operatorului <ALL, dupa cum se vede in urmatoarea
figura.
Si o sa ne intoarca tabela:
In tabela ne sunt prezentate abonamentele utilizatorilor, mai ieftine decat cele pe care le-
am dat in subinterogare.
Similar, se poate folosi >ALL pentru a intoarce toate abonamentele cu o valoare mai mare
decat cele returnate de subinterogare, dar avand in vedere ca nu avem alt abonament mai scump
decat abonamentul Balena, aceasta interogare nu va intoarce nicio data, deci nu are sens sa o
folosim.
27
Operatorul =ANY functioneaza in acelasi fel ca operatorul de comparatie IN. De exemplu
in urmatoarea interogare, dorim sa cunoastem ce alti utilizatori mai au acelasi tip de abonament
ca Geanta Aurelian. Deoarece acest tip de abonament poate aparea la mai multi utilizatori, o sa
folosim operatorul =ANY.
Trebuie mentionat ca acelasi rezultat il puteam obtine daca foloseam cuvantul cheie IN in
loc de operatorul =ANY.
Operatorul EXISTS este folosit pentru a intoarce valoarea de adevar a unei subinterogari.
Acesta va intoarce TRUE daca subinterogarea intoarce vreo valoare, si FALSE daca nu intoarce
nimic.
Vom exemplifica acest operator. In linia de comanda SQL vom da urmatoarea comanda:
28
Aceasta comanda ne va intoarce urmatoarea tabela:
29
O sa obtinem urmatorul rezultat:
Obtinem acest rezultat, deoarce subinterogarea a intors valoarea FALSE, ceea ce face ca
interogarea externa sa nu intoarca nicio data. Putem folosi EXISTS in aceasta maniera pentru a
verifica existenta anumitor randuri si pentru a controla rezultatul obtinut la iesirea interogarii pe
baza faptului daca exista sau nu acele randuri.
30
Pentru a genera valoarea NULL in cadrul subinterogarii am incercat sa aflam un nume al
unui client pentru un tip de abonament care nu exista. Astfel catre interogarea externa s-a trimis
valoarea NULL. Rezultatul acestei interogari este:
Dupa cum se poate vedea, Oracle 10g nu a intors nicio eroare, a intors doar “no data
found”. Dupa cum se vede, nu putem sa ne dam seama daca nu s-au gasit date din cauza ca nu
exista date, sau nu am scris un operator, sau daca chiar nu exista un client care sa aibe acest tip de
abonament. Daca analizam subinterogarea, o sa vedem ca interogarea va avea drept conditie
WHERE Nume = NULL. Operatorul IS NULL este necesar pentru a identifica daca exista o
valoare NULL in cadrul clauzei de conditie.
Acest operator poate fi folosit pentru a vedea daca subinterogarea genereaza o valoare
NULL. Acest operator este de tip boolean, adica intoarce valoarea TRUE daca este gasita
valoarea NULL sau intoarce FALSE daca nu este gasita valoarea respectiva.
Stim deja ca SQL permite inserarea de date din tabele existente intr-alte tabele, folosind
subinterogari in comanda INSERT. Folosind subintrebari, putem deasemeni sa facem modificari
si stergeri in tabele. Cel mai indicat exemplu ar fi comanda SET. Sa presupunem ca vrem sa
schimbam tipul abonamentului al clientului Cristoiu Dana in acelasi tip de abonament ca al
clientului Iancu Ion.
31
Iar dupa ce aplicam comanda:
O sa avem in tabela:
5. Rezumat
32
- O subinterogare este o interogare completa, dar trebuie folosita intr-una din comenzile
SELCET, FROM, HAVING sau WHERE. O subinterogare trebuie scrisa intre paranteze si
are cel putin o instructiune SELECT si o instructiune FROM
- Subinterogarile sunt completate intai. Rezultatul unei subinterogari este folosit pe post
de intrare intr-o alta interogare.
- Sbuinterogari scrise pe mai mult de un rand, intorc cel putin un rand de rezultate.
- Operatori care pot fi folositi cand scriem o subinterogare cu mai multe randuri contin
comenzile IN, ALL, ANY si EXISTS.
- Subinterogari de mai multe randuri intorc mai mult de o coloana celeilalte interogari.
Coloanele de date sunt trimise celeilalte interogari in aceasi ordine in care sunt scrise in
subinterogarea din comanda SELECT.
33
6. Exercitiu complex
1. Vreau sa afisez Id-ul, Numele, Prenumele celor care au tipul de abonament in valoare
de 100 de dolari, mai intai abonatii de acelasi sex ca abonatul Geanta, apoi cei de acelasi sex cu
abonatul Lupu.
Mai intai o sa afisez ceea ce doresc pentru persoanele cu acelasi sex ca Geanta:
Si o sa am doua rezultate:
Si nu o sa am niciun rezultat:
34
2. Vreau sa modific utilizatorul Geanta Aurelian, astfel incat abonamentul sau sa nu mai
coste 5 euro, ci sa aibe acelasi pret ca abonamentul lui Gigi Becali.
Initial o sa am in tabel:
35