Sunteți pe pagina 1din 35

Baze de Date pentru Telecomunicaţii

Lucrarea 3

Subinterogari. Incapsularea instructiunii SELECT

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

In ziua de azi, sistemele de baze de date au devenit o componenta esentiala a activitatii de


zi cu zi. In cursul unei zile normale, o persoana desfasoara tot felul de actiuni care implica
interactiunea cu o baza de date, fie ca rezerva bilete de avion sau pentru un film, fie ca realizeaza
diferite operatiuni de extragere sau depunere de bani la banca.

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:

- Insert – Introducerea unei noi inregistrari sau date in tabela


- Delete – Stergerea unei inregistrari sau date memorata anterior in tabela
- Update – Actualizarea unei inregistrari sau date
- Read (Select) – Citirea inregistrarilor sau datelor introduse anterior in tabela. Aceasta
operatie mai poarta si numele de interogare (query)

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.

1.1. Crearea Bazei 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).

Tabela CLIENTI poate fi creata in doua moduri, folosind ORACLE 10g.

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.

Fig 1 – Creare DB din GUI

Dupa crearea tabelei trebuie selectata cheia primara.

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.

Dupa logare, incepem sa construim tabelul CLIENTI, introducand urmatoarele comenzi:

Fig 3– Crearea tabelei din SQL Command Line

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.

Fig 4 – Crearea unei intrari din GUI

Tabela va avea urmatoarea forma:

Fig 5 – Tabela CLIENTI dupa introducerea primei intrari

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

Sa presupunem ca avem o baza de date pentru o librarie, si ca dormi sa intocmim o lista


cu toate cartile despre computere care au un pret mai mare decat cartea „Teach yourself SQL in
21 days”. In mod normal am avea nevoie de doua interogari separate:
1) Intai interogam baza de date ca sa aflam pretul cartii „Teach yourself SQL in 21 days”
2) Facem o a doua interogare in care, pentru afisarea tuturor cartilor cu pret mai mare,
punem conditia in cadrul SELECT-ului

O alta abordare la aceasta problema este folosirea subinterogarilor. O subinterogare este o


interogare aflata in interiorul altei interogari sau o interogare plasata in interiorul unei comenzi
de tipul SELECT, INSERT, UPDATE sau DELETE. O subinterogare poate fi folosita oricand in
cadrul unei expresii.
O subinterogare se mai numeste si o interogare interioara sau select interior, pe cand
expresia ce conine subinterogarea mai este numita si interogare externa sau select exterior.
Subinterogarea aflata in interiorul unei expresii select externe are urmatoarele
componente:
- o interogare de tip SELECT care include lista componentelor obisnuite (*, nume de coloane)
- o clauza de tip FROM care include unu sau mai multe nume de tabele sau view-uri
- o clauza WHERE optionala
- o clauza GROUP BY optionala
- o clauza HAVING optionala

Subinterogarea SELECT este intotdeauna introdusa intre paranteze, fata de SELECT-ul


extern. Aceasta poate fi introdusa in cadrul clauzei WHERE sau HAVING al unei expresii
externe de tip SELECT, INSERT, UPDATE sau DELETE, sau in interiorul unei alte
subinterogari (sunt posibile pana la 32 de astfel de subinterogare in cadrul unei alte
subinterogari, dar limita variaza in functie de memoria disponibila si complexitatea celorlalte
expresii din interogare). O subinterogare poate fi folosita oricand, cu conditia sa intoarca o
singura valoare.

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

Tabel 1. Tipuri de subinterogari

2.1. Subinterogari de tip single-row

O subinterogare de tip single-row este utilizata cand rezultatele necesare interogarii


externe se bazeaza pe o valoare necunoscuta, singulara. Desi acest tip de interogare se numeste
single-row (rand unic), iar numele implica afisarea mai multor coloane, dar doar al unui singur
rand, subinterogarea poate intoarce doar rezultatul corespunzator unei singure coloane a unui
singur rand. De aceea, aceasta subinterogare se mai sumeste si single value (valoare singulara).

2.1.1. Subinterogari de tip single-row intr-o clauza WHERE

Pentru a exemplifica acest tip de subinterogare, o sa reluam exemplul precedent, in care o


sa afisam ce dorim sa aflam, in functie de o valoare care initial este necunoscuta, prin doua
metode.

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.

Si vom afla rezultatul dorit:

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.

Astfel, o sa cream urmatoarea interogare, ce contine o subinterogare:

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.

Sa presupunem ca ni se cere sa intoarcem valoarea maxima a unui abonament. Functia


MAX este cea care se ocupa cu aceasta sarcina. O sa folosim comanda:

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.

Vom folosi urmatoarea interogare ce contine o subinterogare:

Si vom obtine rezultatul:

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).

Vom crea urmatoarea interogare:

Si vom obtine urmatorul rezultat:

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.

2.1.2. Folosirea functiilor agregate. Subinterogari de tip Single-Row intro clauza


SELECT

O subinterogare de tip Single-Row poate fi introdusa in cadrul clauzei SELECT a


interogarii externe. In acest caz valoarea returnata de subinterogare este disponibila pentru fiecare
rand generat la executarea interogarii externe. De obicei aceasta tehnica este folosita pentru a face
calcule cu o valoare produsa de o subinterogare. De exemplu, sa presupunem ca vrem sa
calculam costul mediu al abonamentelor fata de pretul fiecarui abonament in parte.

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.

Aceasta subinterogare poate fi folosita si in afisarea diferentei dintre valoarea medie si


valoarea abonamentului. Astfel, o sa avem comanda:

Si o sa obtinem tabela:

17
2.2. Subinterogari Nested

Subinterogarile pot fi introduse(nested) in cadrul clauzelor de tip FROM, WHERE sau


HAVING al altor subinterogari. In Oracle 10g, subinterogarle din cadrul unei clauze WHERE pot
fi introduse in alte subinterogari pana la o adancime de 32 (nivelul de subinterogare in cadrul
altei subinterogari), si nu exista nicio limita cand subinterogarile sunt introduse in alte
subinterogari in cadrul unei clauza FROM. Cand facem aceasta operatie e bine sa folosim
urmatoarea startegie:

- Sa determinam exact ceea ce vrem sa aflam, in alte cuvinte, scopul interogarii


- Sa scriem subinterogarea aflata pe cel mai jos nivel
- Apoi, sa ne uitam la valoarea trimisa catre subinterogarea externa. Daca nu e o valoare de care
are nevoie interogarea externa (de exemplu, daca este o referinta la o coloana gresita), trebuie sa
analizam cum putem sa convertim data astfel incat sa obtin tipul corect de rand. Daca e necesar,
se foloseste alta subinterogare intre interogarea externa si subinterogarea nested. In unele cazuri,
e poasibil sa avem nevoie sa cream cateva straturi de subinterogari pentru a lega valoare
subinterogarii aflate pe nibelul cel mai de jos la tipul de valoare de care are nevoie subinterogarea
externa.

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:

Pasi de rezolvare ai interogarii sunt urmatorii:


- Scopul interogarii este sa aflam numele si prenumele unei persoane
- Prima conditie este aceea ca tipul abonamentului sa fie egal cu tipul returnat de prima
subinterogare

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

Pana acum am vorbit despre subinterogari necorelate. Adica, subinterogarea este


executata prima data, rezultatul generat de ea este transmis catre interogarea externa, si apoi
interogarea externa este executata. Pentru subinterogarile corelate, Oracle 10g foloseste un alt tip
de procedura pentru a executa interogarea. O subinterogare corelata face referinta la una sau mai
multe coloane din interogarea externa, iar operatorul EXISTS este folosit pentru a testa daca
legatura sau relatia dintre cele doua exista.

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:

E si C sunt aliasurile tabelelor Extra si Clienti. Si se vor obtine rezultatele:

21
Se poate observa ca tabela obtinuta seamana foarte mult cu tabela obtinuta din urmatorul
JOIN:

Tabela obtinuta este:

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.

Un alt exemplu a ceva ce nu trebuie sa facem este urmatorul:

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:

Aceasta comanda imi va intoarce rezultatul:

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.

4.2. Operatorii ALL si ANY

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)

Operatorul ALL este destul de simplu de dedus ce face:

- 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.

Si vom afla pretul celor doua 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.

Oracle 10g proceseaza aceasta expresie SELECT in felul urmator:


- Subinterogarea intoarce preturile celor mai scumpe abonamente, iar rezultatul este trimis
interogarii externe
- Deoarece este folosit operatorul <ALL in cadrul interogarii externe, Oracle 10g este instiintat
ca trebuie sa intoarca toate intrarile din tabela care au un pret mai mic decat cel returnat de
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.

Tabela intoarsa va fi urmatoarea:

Trebuie mentionat ca acelasi rezultat il puteam obtine daca foloseam cuvantul cheie IN in
loc de operatorul =ANY.

4.3. Operatorul EXISTS

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:

Nu este exact ce ne-am astepta, dar sa explicam folosirea comenzii. Subinterogarea


folosita pentru EXISTS este evaluata o singura data in acest exemplu si intoarce valoarea TRUE.
Astfel vor fi afisate toata randurile. Daca insa, schimbam interogarea in felul urmator:

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.

4.4. Valori NULL

Ca si in celelate cazuri, valoarea NULL prezinta o provocare in cazul folosirii


subinterogarilor. Deoarece NULL este similar cu absenta datelor, valoarea NULL nu poate fi
intoarsa catre interogarea externa, pentru a se executa o comparatie. Aceasta valoare nu este egala
cu nimic, nici macar cu un alt NULL. Astfel, daca o valoare NULL este trimisa de o
subinterogare, rezultatul interogarii externe va fi “no rows selected”, adica nu s-a selectat niciun
rand. Desi expresia nu genereaza o eroare, nici nu se obtine niciun rezultat.
Vom crea o interogare in care vom incerca sa generam o valoare NULL in cadrul
subinterogarii.

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.

4.5. Actiuni DML care folosesc subinterogari

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.

Initial, pentru Cristoiu Dana, o sa avem:

31
Iar dupa ce aplicam comanda:

O sa avem in tabela:

Putem folosi subinterogarile in dreptul instructiunii WHERE din comanda DELETE


pentru a determina ce randuri sunt sterse, lucru bazat pe valoarea intoarsa a subinterogarii.

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.

- O subinterogare de un singur rand poate sa intoarca maximum o valoare.

- Operatorii de un singur rand contin =, >, <, >=, <= si <>.

- 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.

- Valorile NULL nu reprezinta o problema daca sunt intoarse de o subinterogare pe mai


multe randuri sau o subinterogare pe mai multe coloane, in cazul in care a fost foloasit unul
dintre operatorii IN sau =ANY. Functia NVL poate fi folosita sa substituie valoarea NULL cu
o valoare, atunci cand se lucreaza cu subinterogari.

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:

Apoi o sa afisez pentru persoanele care au acelasi sex ca Lupu:

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:

Fac acest lucru folosind un UPDATE care contine o subinterogare.

O sa obtin in tabela un nou rezultat:

35

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