Sunteți pe pagina 1din 27

Cereri multi relaie

Comanda SELECT ofer posibilitatea de a consulta informaii care provin din mai multe tabele. Operatorii care intervin n astfel de cereri pot fi: operatori pe mulimi (UNION, UNION ALL, INTERSECT, MINUS); operatori compunere care implementeaz diferite tipuri de JOIN. Exist dou moduri de realizare a cererilor multi-relaie: forma relaional, n care drumul de acces la informaie este n sarcina sistemului. forma procedural, n care trebuie indicat drumul de acces la informaie prin imbricarea de comenzi SELECT; Exemplu: S se obin, utiliznd aceste dou forme, codurile i titlurile crilor mprumutate. a) Forma relaional: SELECT carte.codel, titlu FROM carte, imprumuta WHERE carte.codel = imprumuta.codel; b) Forma procedural (imbricare de comenzi SELECT-Subcereri): SELECT codel, titlu FROM carte WHERE codel IN (SELECT DISTINCT codel FROM imprumuta);

Operatori pe mulimi sau Operatori pentru interogri


compuse (UNION, UNION ALL, INTERSECT, MINUS)
Uneori este util s se ruleze interogri multiple i s se combine rezultatele ntr-un singur set de rezultate. Operatorii pe mulimi combin rezultatele obinute din dou sau mai multe interogri. Cererile care conin operatori pe mulimi se numesc cereri compuse. Exist patru operatori pe mulimi: UNION, UNION ALL, INTERSECT i MINUS(n unele implementeri oracle operatorul MINUS se numete EXCEPT). Toi operatorii pe mulimi au aceeai preceden. Dac o instruciune SQL conine mai muli operatori pe mulimi, server-ul Oracle evalueaz cererea de la stnga la dreapta (sau de sus n jos). Pentru a schimba aceast ordine de evaluare, se pot utiliza paranteze.
1

n mod implicit, pentru toi operatorii cu excepia lui UNION ALL, rezultatul este ordonat cresctor dup valorile primei coloane din clauza SELECT. Pentru o cerere care utilizeaz operatori pe mulimi, cu excepia lui UNION ALL, server-ul Oracle elimin liniile duplicat. n instruciunile SELECT asupra crora se aplic operatori pe mulimi, coloanele selectate trebuie s corespund ca numr i tip de date. Nu este necesar ca numele coloanelor s fie identice. Numele coloanelor din rezultat sunt determinate de numele care apar n clauza SELECT a primei cereri. n cazul n care cererile componente selecteaz date de tip caracter, tipul de date al valorii returnate poate fi CHAR, dac valorile selectate de ambele cereri sunt de tip CHAR, sau VARCHAR2, dac valorile selectate de cel puin una din cele dou cereri sunt de tip VARCHAR2. Observaii: Comenzile SELECT, care intervin n cereri ce conin operatori pe mulimi, trebuie s satisfac anumite condiii: toate comenzile SELECT trebuie s aib acelai numr de coloane; opiunea DISTINCT este implicit (excepie UNION ALL); numele coloanelor sunt cele din prima comand SELECT; dimensiunea coloanei implicit este cea mai mare dintre cele dou coloane; sunt admise combinaii de forma: 1. SELECT1 UNION SELECT2 INTERSECT SELECT3 i ordinea de execuie este de la stnga la dreapta; 2. SELECT1 UNION (SELECT2 INTERSECT SELECT3) i ordinea este dat de paranteze. UNION Operatorul UNION adaug rndurile din setul de nregistrri al unei interogri la cel al unei alte interogri i, n acelai timp, elimin rndurile duplicate, ntr-un mod similar cu cel al cuvntului cheie DISTINCT. Operatorul UNION returneaz deci toate liniile selectate de dou cereri, eliminnd duplicatele. Operaia este permis numai dac interogrile sunt compatibile din punctul de vedere al uniunii, ceea ce nseamn c au acelai numr de coloane i c tipurile de date ale coloanelor corespondente sunt compatibile. Acest operator nu ignor valorile null i are preceden mai mic dect operatorul IN.

Exemplu: S se afieze pe o singur coloan toate valorile nenule pentru taxa de inchiriere i taxa de ntrziere din tabelul FILM_NCHIRIAT. SELECT taxa_inchiriat AS TAXA FROM FILM_INCHIRIAT WHERE taxa_inchiriat IS NOT NULL UNION SELECT taxa_intarziere AS TAXA FROM FILM_INCHIRIAT WHERE taxa_intarziere IS NOT NULL; Exemplu: S se afieze codurile operelor de art pentru care a fost ncheiat o poli de asigurare sau care beneficiaz de un sistem de securitate. Fiecare cod va fi afiat o singur dat. SELECT FROM UNION SELECT FROM cod_opera polita_asig cod_opera securitate;

Uneori, pentru a respecta regula conform creia expresiile din clauzele SELECT trebuie s concorde ca numr i tip de date, se pot utiliza coloane artificiale i funcii de conversie pentru tipurile de date. Exemplu: S se listeze codul operelor de art, codul i numele artitilor. SELECT FROM UNION SELECT FROM cod_opera, cod_artist, TO_CHAR(null) nume opera TO_NUMBER(null), cod_artist, nume artist;

Exemplu s se listeze codul salariailor, codul i numele departamentelor.

SELECT FROM UNION SELECT FROM

employee_id, department_id, TO_CHAR(NULL) nume employees TO_NUMBER(NULL), department_id, department_name departments;

Daca se utilizeaza UNION ALL obtinem suma celor doua cereri. UNION ALL Operatorul UNION ALL funcioneaz la fel ca i operatorul UNION, exceptnd faptul c rndurile duplicate nu sunt eliminate. Precizrile fcute asupra operatorului UNION sunt valabile i n cazul operatorului UNION ALL. n cererile asupra crora se aplic UNION ALL nu poate fi utilizat cuvntul cheie DISTINCT. Exemplu: S se determine codul operelor de art pentru care s-a ncheiat o poli de asigurare sau pentru care s-a achiziionat un sistem de securitate. S se afieze firma i data contractrii, respectiv a instalrii sistemului. ntruct o oper poate avea mai multe polie de asigurare sau mai multe sisteme de securitate ncheiate, respectiv instalate la aceeai firm i dat, nu se vor suprima liniile duplicat. Rezultatul va fi ordonat dup codul operelor. SELECT cod_opera, firma, semnat_contract FROM polita_asig UNION ALL SELECT cod_opera, firma, data_inst FROM polita_asig ORDER BY cod_opera; Clauza ORDER BY poate aprea numai o singur dat ntr-o cerere compus. Dac se utilizeaz, clauza trebuie plasat la sfritul cererii i accept nume de coloane, alias-uri sau notaia poziional. Numele de coloane i alias-urile din clauza ORDER BY trebuie s fie din lista SELECT a primei instruciuni.

INTERSECT Operatorul INTERSECT gsete valorile selectate dintr-o interogare, care apar i ntr-o alt interogare. n esen, gsete intersecia valorilor din cele dou interogri. Acest operator nu ignor valorile null. Totui, doar un numr mic de sisteme DBMS (cele mai importance fiind Oracle i DB2) implementeaz acest operator. Nu exista in Microsoft SQL Server sau MySQL. Exemplu: Exist n tabelul FILM filme pentru care preul pentru DVD este egal cu preul pentru VHS? SELECT pret_DVD AS TAXA FROM FILM WHERE pret_DVD IS NOT NULL INTERSECT SELECT pret_VHS AS TAXA FROM FILM WHERE pret_VHS IS NOT NULL; Exemplu: S se afieze codul operelor de art, respectiv data la care s-a ncheiat o poli de asigurare i s-a instalat un sistem de securitate. SELECT cod_opera, semnat_contract FROM polita_asig INTERSECT SELECT cod_opera, data_inst FROM securitate; Exemplu: S se obin, utiliznd operatorul INTERSECT, codurile crilor din care sunt mai puin de 15 exemplare i care au fost mprumutate de cel puin trei ori. SELECT codel FROM carte WHERE nrex < 15 INTERSECT
5

SELECT codel FROM imprumuta GROUP BY codel HAVING COUNT(*) > 3; Exemplu S se obin, folosind operatorul INTERSECT, angajaii care au salariul < 5000 i al cror nume conine litera l pe poziia 3. SELECT employee_id, last_name FROM employees WHERE salary<5000 INTERSECT SELECT employee_id, last_name FROM employees WHERE UPPER(last_name) LIKE '__L%'; MINUS Operatorul MINUS sau EXCEPT gsete diferenele dintre dou seturi de rezultate, returnnd, n esen, valorile din prima interogare care nu apar n cea dea doua interogare. Pentru ca operatorul MINUS s funcioneze, este necesar ca toate coloanele din clauza WHERE s se afle i n clauza SELECT. Foarte puine sisteme DBMS implementeaz acest operator. n unele implementri, precum Oracle, operatorul se numete MINUS, nu EXCEPT. Exemplu: S se determine codul i valoarea operelor de art al cror pre nu este de 20 de ori mai mare dect valoarea poliei de asigurare. SELECT FROM MINUS SELECT FROM cod_opera, valoare opera cod_opera, valoare*20 polita_asig;

Exemplu: S se afieze codurile cititorilor care nu au mprumutat cri. SELECT codec FROM cititor MINUS SELECT DISTINCT codec FROM imprumuta; Operatorii pe mulimi pot fi utilizai n subcereri. Coloanele care apar n clauza WHERE a interogrii trebuie s corespund, ca numr i tip de date, celor din clauza SELECT a subcererii. Exemplu: S se afieze codurile departamentelor care nu au angajai, implementnd operatorul MINUS SELECT department_id FROM departments MINUS SELECT DISTINCT department_id FROM employees;

Operaia de compunere (JOIN)


S-au prezentat pn acum instruciuni SQL care selecteaz date dintr-un singur tabel. Deseori, este util s se combine date din tabele multiple ntr-o singur interogare. De exemplu, n listingul celor trei coloane ale tabelului FILM din figura urmtoare, observai valorile afiate pentru coloan FILM_GEN_COD. Atunci cnd s-a proiectat baza de date pentru magazinul de produse video, s-au folosit coduri n locul descrierilor complete pentru genurile filmelor n tabelul FILM. Din discuia despre procesul de normalizare, s-a evitat anomalia de actualizare dac se schimb descrierea unui gen, nu este nevoie s actualizm acea descriere pentru toate filmele asociate genului respectiv n tabelul FILM. n timpul normalizrii, descrierea genurilor a fost mutat n tabelul, FILM_GEN, iar coloan FILM_GEN_COD a devenit cheie extern n tabelul FILM, referind coloan cheie primar (cu acelai nume) din tabelul FILM_GEN. S-a optat pentru folosirea unui cod mnemonic pentru codurile genurilor.
7

Tabelul FILM (trei coloane) FILM_COD FILM_GEN_COD


1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 Drama ActAd Comedie ActAd ActAd ActAd Drama ActAd ActAd Drama Rmce Comedie Comedie Drama Drama Comedie Rmce Drama ActAd Forgn

FILM_TITLU
Mystic River The Last Samurai Something's Gotta Grve The Italian Kill Bill: Voi. 1 Pirates of the Caribbean: Trie Curse of the Black Pearl Big Fish Man on Fire Master and Commander The Far Side of the World LosI n Translation Two Weeks Notice 50 First Dates Matchstick Men Cold Mountain Road to Perdition The School of Rock 13 Going on30 Monster The Day After Tomorrow Das Boot

Daca se doreste a afisa descrierea genului trebuie sa combinam datelor din mai multe tabele ntr-o singur interogare. Figura urmtoare prezint un listing al tabelului FILM_GEN. Tabelul FILM_GEN FILM_GEN_COD ActAd Anime ChFam Class Comedie Doc FILM_GEN_DESCRIERE Actiune Animatie Copii i Familie Clasic Comedie Documentar
8

Drama Forgn Hor Indep Music Rmce SciFi Sport Thriller

Drama Strain Horror Independent Muzical Romance(Romantic, Idila) Stiintifico-Fantastic Sport Groaza

Uniuni (join) O uniune (join) este o operaie ntr-o baz de date relaionale care combin coloane din dou sau mai multe tabele n rezultatele unei singure interogri. O uniune apare de fiecare dat cnd clauza FROM a unei instruciuni SELECT specific numele mai multor tabele. De exemplu: SELECT FILM_ID, FILM_GEN_DESCRIERE AS GEN, FILM_TITLU FROM FILM, FILM_GEN ORDER BY FILM_ID; FILM_ID 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 GEN Actiune i Aventura Animatie Clasic Documentar Strain Independent Groaza Sport SF Musical Horror Drama Comedie Copii i Familie Thriller Actiune i Aventura FILM_TITLU Mystic River Mystic River Mystic River Mystic River Mystic River Mystic River Mystic River Mystic River Mystic River Mystic River Mystic River Mystic River Mystic River Mystic River Mystic River The Last Samurai
9

Sport The Last Samurai SF The Last Samurai Romantic The Last Samurai Musical The Last Samurai Independent The Last Samurai Horror The Last Samurai Animatie The Last Samurai Copii i Familie The Last Samurai Documentar The Last Samurai Strain The Last Samurai Drama The Last Samurai Comedie The Last Samurai Clasic The Last Samurai .. ... ............... Setul de rezultate al interogrii a fost trunchiat dup primele dou titluri de filme. Problema este c am cerut bazei de date s uneasc tabelele, dar nu i-am spus care este corespondena dintre rndurile celor dou tabele. Rezultatul este cunoscut sub numele de produs cartezian (dup numele filozofului i matematicianului francez Rene Descartes) i, n bazele de date relaionale, este un set de rezultate obinut prin uniunea dintre fiecare rnd al unui tabel cu fiecare rnd dintr-un alt tabel. Soluia este s specificm cum se va face unirea tabelelor. Trebuie indicat ce coloane ar trebui s se potriveasc pentru a uni dou rnduri din cele dou tabele, n mod normal, cele dou coloane vor fi cheia primar dintr-un tabel i cheia extern din cellalt tabel, dar pot exist i excepii. Pentru a realiza acest lucru trebuie s se fac o o uniune standard relaional, cunoscut i sub numele de uniune de egalitate (equijoin). Join-ul este operaia de regsire a datelor din dou sau mai multe tabele, pe baza valorilor comune ale unor coloane. De obicei, aceste coloane reprezint cheia primar, respectiv cheia extern a tabelelor. Condiia de join se scrie n clauza WHERE a instruciunii SELECT. ntr-o instruciune SELECT care unete tabele prin operaia de join, se recomand ca numele coloanelor s fie precedate de numele tabelelor pentru claritate i pentru mbuntirea timpului de acces la baza de date. Dac acelai nume de coloan apare n mai mult de dou tabele, atunci numele coloanei se prefixeaz obligatoriu cu numele tabelului corespunztor. Pentru a realiza un join ntre n tabele, va fi nevoie de cel puin n 1 condiii de join.

2 2 2 2 2 2 2 2 2 2 2 2 2

10

Equijoin-ul corespunde situaiei n care valorile de pe coloanele ce apar n condiia de join trebuie s fie egale. Un astfel de join mai poart numele de join simplu sau inner join. Un nonequijoin este o condiie de join care conine ali operatori dect operatorul egalitate. Un self join realizeaz compunerea unui tabel cu el nsui.

Uniuni de egalitate (equijoin)


Avem o uniune de egalitale (equijoin), numit i uniune intern (inner join), atunci cnd legm una sau mai multe coloane dintr-un tabel (de obicei, o cheie extern) cu coloane similare dintr-un alt tabel (de obicei, cheia primar), folosind condiia de egalitale, aceasta fiind cea mai des folosit form de uniune. Totusi, termenul uniune de egalitate (equijoin) este rareori folosit n afara mediilor academice, find preferate denurmirile uniune intern (inner join) sau uniune standard (standard join). Exist dou modaliti de specificare a coloanelor corespondente: folosind clauza WHERE sau folosind clauza JOIN. Clauza JOIN a fost adugat relativ recent n standardul SQL, aa c programatorii mai vechi sunt obisnuii cu metoda bazat pe clauza WHERE. Realizarea uniunilor folosind clauza WHERE Folosirea clauzei WHERE pentru unirea tabelelor seamn cu folosirea acesteia pentru eliminrea rndurilor de care nu avei nevoie din setul de rezultate. Totui, exist unele diferene. n clauza WHERE : Se compar o coloan cu o alt coloan, nu o coloan cu o constant sau o expresie. Atunci cnd coloanele din cele dou tabele au acelai nume (o soluie recomandat) trebuie s specificati numele complet al coloanelor (adic numele cu calificator), astfel nct motorul SQL s tie care dintre cele dou coloane este referit. Nu numai coloanele din clauza WHERE, ci din orice alt loc al instrucunii, inclusiv n lista SELECT trebuiesc precedate de calificaor. Cea mai simpl form de calificator este chiar numele tabelului, separat cu caracterul punct de numele coloanei. n continuare este prezentat un exemplu de uniune realizat prin clauza WHERE, cu numele coloanelor specificate complet, folosind numele tabelelor. Observai c interogarea selecteaz coloanele FILM_ID i FILM_TITLU din
11

tabelul FILM i genul corespunztor (FILM_GEN_DESCRIERE) din tabelul FILM_GEN. SELECT FILM_ID, FILM_GEN_DESCRIERE AS GEN, FILM_TITLU FROM FILM, FILM_GEN WHERE FILM.FILM_GEN_COD= FILM_GEN.FILM_GEN_COD ORDER BY FILM_ID; FILM_ID
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 Drama Actiune i Aventura Comedie Actiune i Aventura Actiune i Aventura Actiune i Aventura Drama Actiune i Aventura Actiune i Aventura Drama Romantic Comedie Comedie Drama Drama Comedie Romantic Drama Actiune i Aventura Strain

FILM_GEN

FILM_TITLU
Mystic River The Last Samurai Something's Gotta Give The Italian Job Kill Bill Vol. 1 Pirates of the Caribbean Big Fish Man on Fire Master and Commander Lost n Translation Two Weeks Notice 50 First Dates Matchstick Men Cold Mountain Road to Perdition The School of Rock 13 Going on 30 Monster The Day After Tomorrow Das Boot

Exemplu: S se obin codurile i titlurile crilor mprumutate. SELECT carte.codel, titlu FROM carte, imprumuta WHERE carte.codel = imprumuta.codel;

12

Folosirea numelor complete ale tabelelor pentru specificarea coloanelor poate fi obositoare i consumatoare de timp, mai ales deoarece numele tabelelor pot avea 30 sau mai multe caractere n sistemele DBMS moderne. Din aceast cauz, n SQL este permis i folosirea pseudonimelor (aliases) pentru numele tabelelor. Acestea funcioneaz la fel ca i pseudonimele coloanelor din clauza SELECT, exceptnd faptul c nu este folosit cuvntul cheie AS" (n cele mai multe implementri SQL) - doar lsai un spaiu ntre numele tabelului i pseudonim n lista FROM. Dei unii folosesc mnemonice pentru pseudonimul tabelelor, este mult mai des ntlnit folosirea secvenelor de majuscule (adic A", B,C i aa mai departe). Dup ce se asociaz un pseudonim unui nume de tabel n clauza FROM, trebuie s folosii pseudonimul n locul numelui de tabel n ntreaga instruciune SQL. Folosirea pseudonimelor n clauza SELECT poate prea puin ciudat la nceput deoarece folosii un pseudonim nainte de a-l defini (clauza SELECT precede clauza FROM i s-ar putea s par mai simplu s completai clauza FROM nainte de a completa lista de coloane din clauza SELECT atunci cnd scriei instruciunile SQL. Exemplul urmtor prezint instruciunea anterioar, dup adugarea pseudonimelor pentru numele tabelelor. Dei nu era necesar, pseudonimele au fost adugate i n lista de coloane din clauzele SELECT i ORDER BY, pentru a va arta cum sunt folosite.

Exemplu: SELECT A.FILM_ID, B.FILM_GEN_DESCRIERE AS GEN, A.FILM_TITLU FROM FILM A, FILM_GEN B WHERE A.FILM_GEN_COD = B.FILM_GEN_COD ORDER BY A.FILM_ID; Exemplu: a) S se afieze informaii despre operele de art achiziionate n 2008 i galeriile n care au fost expuse. SELECT cod_opera, titlu, o.cod_galerie, nume_galerie, adresa FROM opera o, galerie g WHERE o.cod_galerie = g.cod_galerie AND TO_CHAR(data_achizitiei, 'yyyy') = '2008'; b) S se afieze informaii referitoare la operele de art, artitii care le-au creat i galeriile n care sunt expuse.
13

SELECT cod_opera, titlu, data_crearii, a.cod_artist, nume, prenume, g.cod_galerie, nume_galerie, adresa FROM opera o, galerie g, artist a WHERE o.cod_artist = a.cod_artist AND o.cod_galerie = g.cod_galerie; c) Sa se afiseze angajatul, codul si numele departamentului pentru fiecare dintre angajati. SELECT employee_id,last_name, e.department_id, department_name FROM employees e, departments d WHERE e.department_id=d.department_id

Uniuni de inegalitate (non-equijoin)


S-ar putea ca tabelele legate prin operaia de compunere s nu aib coloane comune (non-equijoin). n acest caz n clauza WHERE nu apare operatorul egalitate i sunt folosii operatorii: <=, >=, BETWEEN. Un self join realizeaz compunerea unui tabel cu el nsui. Exemplu: S se obin pentru fiecare salariat numele, salariul i grila de salarizare . SELECT e.last_name, e.salary, g.grade_level FROM employees e, job_grades g WHERE e.salary BETWEEN g.lowest_sal AND g.highest_sal Exemplu: S se obin titlurile i preurile crilor mai scumpe dect cartea avnd titlul Baze de date, al crui autor este POPA (self join). SELECT FROM WHERE AND AND x.titlu, x.pret carte x, carte y x.pret > y.pret y.titlu = Baze de date y.autor = POPA;
14

Realizarea uniunilor folosind clauza JOIN


Clauza JOIN este scris ca o referin de tabel din clauza FROM i combin lista de tabele din clauza FROM i condiia de legtur scris anterior n clauza WHERE ntr-o singur clauz. Sintaxa general a clauzei JOIN pentru o uniune intern, urmat de cteva exemple. Sintaxa corespunztoare standardului SQL3 este urmtoarea: SELECT tabel_1.nume_coloan, tabel_2.nume_coloan FROM tabel_1 [CROSS JOIN tabel_2] | [NATURAL JOIN tabel_2] | [JOIN tabel_2 USING (nume_coloan) ] | [JOIN tabel_2 ON (tabel_1.nume_coloan = tabel_2.nume_coloan) ] | [LEFT | RIGHT | FULL OUTER JOIN tabel_2 ON (tabel_1.nume_coloan = tabel_2.nume_coloan) ];

Clauza ON permite specificarea unei condiii similare cu cea din clauza WHERE . Clauza USING specific numele coloanelor folosite pentru legarea rndurilor. Totui, clauza USING acioneaz numai atunci cnd coloanele pe care se face legtur au nume identice n ambele tabele. JOIN tabel_2 USING nume_coloan efectueaz un equijoin pe baza coloanei cu numele specificat n sintax. Aceast clauz este util dac exist coloane avnd acelai nume, dar tipuri de date diferite. Coloanele referite n clauza USING trebuie s nu conin calificatori (s nu fie precedate de nume de tabele sau alias-uri) n nici o apariie a lor n instruciunea SQL. Clauzele NATURAL JOIN i USING nu pot coexista n aceeai instruciune SQL. JOIN tabel_2 ON tabel_1.nume_coloan = tabel_2.nume_coloan efectueaz un equijoin pe baza condiiei exprimate n clauza ON. Aceast clauz permite specificarea separat a condiiilor de join, respectiv a celor de cutare sau filtrare (din clauza WHERE).

15

Exemple: JOIN cu condiie ON: SELECT FILM_ID, FILM_GEN_DESCRIERE AS GEN, FILM_TITLU FROM FILM JOIN FILM_GEN ON FILM.FILM_GEN_COD = FILM_GEN.FILM_GEN_COD ORDER BY FILM_ID; JOIN cu pseudonime n loc de nume de tabele: SELECT FILM_ID, FILM_GEN_DESCRIERE AS GEN, FILM_TITLU FROM FILM A JOIN FILM_GEN B ON A.FILM_GEN_COD = B.FILM_GEN_COD ORDER BY FILM_ID; JOIN folosind cuvntul cheie USING (n locul condiiei ON) o scurtatur elegant atunci cnd coloanele din cele dou tabele au acelai nume (nu e recunoscut de toate SGBD-urile). SELECT FILM_ID, FILM_GEN_DESCRIERE AS GEN, FILM_TITLU FROM FILM JOIN FILM_GEN USING (FILM_GEN_COD) ORDER BY FILM_ID; JOIN cu cheie extern pe mai multe coloane. Aceast interogare afieaz lista cu copiile filmelor din tabelul FILM_COPY care nu au fost vndute (coloan DATA_VANZARE conine o valoare nul dac nu a fost vndut) i care au fost nchiriate (uniune cu tabelul FILM_INCHIRIAT) dar nu au fost nc returnate (coloan RETUR_DATA conine o valoare nul pn la returnarea filmului). SELECT FILM_ID, COPY_NUMAR, DATA_RETURNARII FROM FILM_COPY JOIN FILM__INCHIRIAT USING (FILM_ID, COPY_NUMAR) WHERE DATA_VANZARE IS NULL AND RETUR_DATA IS NULL; FILM _ID 2 3 COPY_NUMAR 2 2 DATA_RETURNARII 02/27/2009 03/04/2009
16

5 5 10 17

1 2 1 1

02/27/2009 02/19/2009 03/04/2009 03/04/2009

Instruciunile care folosesc clauza JOIN sunt mai scurte. Interogarea precedent scris folosind condiii de legtur n clauza WHERE. Se remarc faptul c n acest caz trebuie specificat numele complet al coloanelor FILM_ID i COPY_NUMAR, pentru a evita referirea ambigu a lor. Instruciunea de mai jos afieaz aceleai rezultate ca i instruciunea anterioar. SELECT A.FILM_ID, A.COPY_NUMAR, DATA_RETURNARII FROM FILM_COPY A, FILM_INCH B WHERE A.FILM_ID = B.FILM_ID AND A.COPY_NUMAR = B.COPY_NUMAR AND DATA_VANZARE IS NULL AND RETURN_DATA IS NULL; Uniuni naturale O uniune natural (natural join) se bazeaz pe toate coloanele cu acelai nume din dou tabele, n esen, toate uniunile de egalitate sunt uniuni naturale. Totui, sintaxa unei uniuni naturale este mult mai simpl, deoarece nu este necesar s specificai o condiie sau o list de coloane - se nelege de la sine care sunt coloanele folosite. Nu toate SGBD-urile accept aceast sintax pentru clauza JOIN (accepta sigur Oracle i MySQL ). Exemplu: uniunea tabelelor FILM i FILM_GEN, rescris sub forma unei uniuni naturale: SELECT FILM_ID, FILM_GEN_DESCRIERE AS GEN, FILM_TITLU FROM FILM NATURAL JOIN FILM_GEN ORDER BY FILM_ID; Uniunile pot implica mai mult de dou tabele. Exemplul urmtor prezint o uniune natural care obine coloana FILM_ID din tabelul FILM, coloana FILM_GEN_DESCRIERE din tabelul FILM_GEN i din tabelul MPAA_RATING, coloana MPAA_RATING_DESCRIERE , pentru primele trei

17

filme din tabelul FILM. Folosirea clauzei WHERE permte s se elimine din setul de rezultate rndurile de care nu avem nevoie. Exemplul folosete dou clauze JOIN. Prima clauz JOIN cere motorului SQL s lege tabelele FILM i FILM_GEN, iar a dou clauz JOIN i cere s lege rndurile deja unite (n esen, un set de rezultate intermediar) cu tabelul MPAA_RATING. SELECT FILM_ID, FILM_GEN_DESCRIERE AS GEN, MPAA_RATING_COD AS RATING, MPAA_RATING_DESCRIERE AS RATING_DESC FROM FILM NATURAL JOIN FILM_GEN NATURAL JOIN MPAA_RATING WHERE FILM_ID < 4 ORDER BY FILM_ID;

FILM_ID

GEN

RATING

RATING_DESC

1 2 3

Drama

Sub 17 ani acompaniati de parinti Sub 17 ani acompaniati de parinti Cu acordul strict a parintilor

Aciune si Aventura R

Comedie

PG-13

Dac se folosete o implementare SQL care nu accept uniunile naturale, aceeai interogare scris folosind cuvintele cheie JOIN i ON este: SELECT A.FILM_ID, B.FILM_GEN_DESCRIERE AS GEN, C.MPAA_RATING__COD AS RATING, C.MPAA_RATING__DESCRIERE AS RATING_DESC FROM FILM A JOIN FILM_GEN B ON A.FILM_GEN_COD = B.FILM_GEN_COD JOIN MPAA_RATING C ON A.MPAA_RATING_COD = C.MPAA_RATING_COD WHERE FILM_ID < 4 ORDER BY FILM_ID; Exemple la schema galerii de arta a) S se determine titlul operelor de art expuse n galeriile avnd codul 10 sau 30, respectiv numele i prenumele artitilor care le-au realizat.
18

SELECT FROM WHERE

titlu, nume, prenume opera NATURAL JOIN artist cod_galerie IN (10, 30);

Folosind clauza USING, acest exemplu poate fi rescris astfel: SELECT titlu, nume, prenume FROM opera JOIN artist USING (cod_artist) WHERE cod_galerie IN (10, 30); Urmtoarea cerere va returna eroarea ORA-25154: column part of USING clause cannot have qualifier, ntruct coloana specificat n clauza USING apare, n clauza WHERE, precedat de un alias de tabel. SELECT o.titlu, a.nume, a.prenume FROM opera o JOIN artist a USING (cod_artist) WHERE a.cod_artist IN (50,60); b) S se afieze titlurile operelor de art, firmele la care sunt asigurate i descrierea polielor de asigurare corespunztoare. SELECT o.titlu, p.firma, p.descriere FROM opera o JOIN polita_asig p ON (o.cod_opera = p.cod_opera);

Uniuni externe (outer joins)


Toate uniunile pe care le-am descris pn acum sunt uniuni exclusiv (uniuni interne), ceea ce nseamn c singurele rnduri care apar n setul de rezultate sunt cele pentru care a fost gsit o legtur n toate tabelele unite. Exist situaii n care se dorete s includei n rezultatele interogrii i rnduri pentru care nu exist o legtur. De exemplu, dac se dorete o list cu toate genurile de filme, mpreun cu toate titlurile asociate cu fiecare gen? O uniune extern (outer join) - pentru care un nume mai potrivit ar fi uniune inclusiv - include n setul de rezultate i rndurile pentru care nu exist legturi din cel puin unul dintre tabele. Atunci cnd exist rnduri fr legturi, datele selectate din tabelul n care nu a fost gsit o legtur primesc valoarea nul.
19

Un outer join esye utilizat in doua moduri : Cu Operatorul (+) Cu outer join left|right|full OUTER JOIN Operatorul (+) Un outer join este utilizat pentru a obine n rezultat i nregistrrile care nu satisfac condiia de join. Operatorul pentru outer join este semnul plus inclus ntre paranteze (+), care se plaseaz n acea parte a condiiei de join care este deficient n informaie. Efectul acestui operator este de a uni liniile tabelului care nu este deficient n informaie i crora nu le corespunde nici o linie n cellalt tabel cu o linie cu valori null. Operatorul (+) poate fi plasat n orice parte a condiiei de join, dar nu n ambele pri. O condiie care presupune un outer join nu poate utiliza operatorul IN i nu poate fi legat de alt condiie prin operatorul OR. Exemplu: Se presupune c tabelul artist conine i artiti care nu au opere expuse n muzeu. S se afieze artitii i operele acestora, inclusiv cei care nu au opere corespunztoare n tabelul opera. SELECT a.cod_artist, nume, prenume, cod_opera, titlu FROM artist a, opera o WHERE a.cod_artist = o.cod_artist (+); Uniune extern cu outer join Sintaxa general pentru o uniune extern este: nume_tabel {RIGHT | LEFT | FULL} [OUTER] JOIN nume_tabel { ON condiie | USING (nume_coloan [ ,nume_coIoan. ..]) } Exist trei tipuri de baz: Uniune extern ctre stnga (left outer join). Returneaz toate rndurile din tabelul din stnga (cel specificat primul n clauza JOIN), mpreun cu toate rndurile din tabelul din dreapta pentru care poate fi gsit o legtur. (asemnatoare interogrilor din tabele aflate in relaia 1:m) Uniune extern ctre dreapta (right outer join). Returneaz toate rndurile din tabelul din dreapta (cel specificat al doilea n clauza JOIN), mpreun cu toate rndurile din tabelul din stnga pentru care poate fi gsit o legtur, n esen, o uniune extern ctre stnga poale fi rescris ca o uniune extern ctre dreapta
20

inversnd ordinea de specificare a tabelelor i nlocuind cuvntul cheie LEFT cu RIGHT. Uniune extern complet (full outer join). Returneaz toate rndurile din ambele tabele. Acest tip de uniune este cel mai puin probabil s fie acceptat de toate implementari;e SQL. Aceast uniune nu este acelai lucru cu un produs cartezian, care leag fiecare rnd dintr-un tabel cu fiecare rnd din cellalt tabel. O uniune extern complet leag fiecare rnd dintr-un tabel cu zero sau mai multe rnduri corespondente din cellalt tabel. Este folosit mai mult pentru tabelele aflate in relaia m:m Exemple de uniuni externe: S se afieze toate descrierile genurilor de filme, mpreun cu filmele asociate fiecrui gen. n setul de rezultate rndurile care nu au nici o valoare n coloan FILM_TITLU - acestea sunt genurile de filme care nu au filme asociate. Dac implementarea DBMS nu accept uniuni realizate cu cuvntul cheie USING, modificai instruciunea astfel nct s utilizeze cuvntul cheie ON, ca n exemplul care urmeaz dup acesta. SELECT FILM_GEN_DESCRIERE AS GEN, FILM_TITLU FROM FILM_GEN LEFT OUTER JOIN FILM (FILM_GEN_COD); GEN Actiune i Aventura Actiune i Aventura Actiune i Aventura Actiune i Aventura Actiune i Aventura Actiune i Aventura Actiune i Aventura Anime and Animation Copii i Familie FILM_TITLU Kill Bill: Vol. 1 Man on Fire Pirates of the Caribbean Master and Commander The Day After Tomorrow The Last Samurai The Italian Job

USING

21

Clasic Comedie Comedie Comedie Comedie Documentar Drama Drama Drama Drama Drama Drama Strain Horror Independent Musical Romantic Romantic

50 First Dates Matchstick Men The School of Rock Something's Gotta Give Big Fiah Road to Perdition Mystic River Monster Cold Mountain Lost n Translation Das Boot

13 Going on 30 Two Weeks Notice

Interogarea anterioar, rescris ca uniune extern ctre dreapta, cu condiie ON.

SELECT FILM_GEN_DESCRIERE AS GEN, FILM_TITLU FROM FILM RIGHT OUTER JOIN FILM_GEN ON FILM.FILM_GEN_COD =FILM_GEN.FILM_GEN_COD; Interogarea anterioar, rescris ca uniune extern complet. Deoarece fiecare film trebuie s aib asociat un gen, aceast interogare va produce aceleai rezultate ca i uniunea extern ctre dreapta din interogarea anterioar. Totui, dac genurile filmelor ar fi opionale, uniunea extern complet v-ar fi permis s afiai att genurile care nu au filme asociate, ct i filmele care nu au genuri asociate. SELECT FILM_GEN_DESCRIERE AS GEN, FILM_TITLU FROM FILM FULL OUTER JOIN FILM_GEN ON FILM.FILM_GEN_COD = FILM_GEN.FILM_GEN_COD;

22

Afiai descrierile genurilor care nu au nume asociate. Exist i alte moduri de a face acest lucru, dar exemplul de fa folosete faptul c rndurile pentru care nu exist legturi returneaz valori nule pentru a selecta numai genurile care nu au nume asociate. SELECT FILM_GEN_DESCRIERE AS GEN FROM FILM RIGHT OUTER JOIN FILM_GEN ON FILM.FILM_GEN_COD = FILM_GEN.FILM_GEN_COD WHERE FILM_TITLU IS NULL; GEN Animatie Copii i Familie Clasic Documentar Horror Independent Musical SF Special Interes Sport Thriller Ca rspuns la cererile clienilor, mai muli productori de baze de date relaionale au introdus uniunile externe inainte de standardizarea clauzei JOIN. Seciunile urmtoare prezint cteva implementri specifice ale sintaxei uniunii externe. Aceste soluii particulare sunt prezentate aici numai pentru c s-ar putea s le intlnii n instruciuni SQL mai vechi Exemplu: a) S se afieze titlurile operelor de art i firmele la care acestea sunt asigurate. Se vor lua n considerare i operele de art pentru care nu au fost ncheiate polie de asigurare. SELECT titlu, firma FROM opera o LEFT OUTER JOIN polita_asig p ON (o.cod_opera = p.cod_opera);

23

b) S se afieze artitii (nume, prenume) i operele acestora, inclusiv cei care nu au opere expuse n cadrul muzeului. SELECT nume, prenume, titlu FROM opera o RIGHT OUTER JOIN artist a ON (o.cod_artist = a.cod_artist); c) S se afieze numele i prenumele artitilor, precum i titlurile operelor create de acetia. Se vor afia i artitii care nu au opere expuse n cadrul muzeului, precum i titlurile operelor al cror autor este necunoscut. SELECT nume, prenume, titlu FROM opera o FULL OUTER JOIN artist a ON (o.cod_artist = a.cod_artist); S se obin titlurile crilor i numele domeniului cruia i aparin, remarcnd si situaiile n care domeniul nu ar avea cri (dac domeniul este fr cri atunci apare null la titlul crii). SELECT titlu, intdom FROM carte, domeniu WHERE carte.coded(+) = domeniu.coded; Exemplu: Considerm c tabelele dept i emp au urmtorul coninut: dept emp deptno dname empno deptno 1 algebra 101 null 2 analiza 102 null 103 null 105 1 106 1 Interogarea urmtoare furnizeaz lista tuturor salariailor si informatii despre departamentele in care lucreaza, inclusiv a celor care nu sunt asignai nici unui departament (right outher join). SELECT a.deptno, a.dname, b.empno, b.deptno FROM dept a, emp b WHERE a.deptno(+) = b.deptno; Rezultatul cererii anterioare va fi: a.deptno a.dname b.empno b.deptno 101 102
24

103 1 algebra 105 1 1 algebra 106 1 Interogarea urmtoare afieaz lista departamentelor, inclusiv a celor care nu au salariai (left outer join). SELECT a deptno, a.dname, b.empno, b.deptno FROM dept a, emp b WHERE a.deptno = b.deptno(+); Rezultatul cererii anterioare va fi: a.deptno a.dname b.empno b.deptno 1 algebra 105 1 1 algebra 106 1 2 analiza null null Interogarea urmtoare produce ca rezultat departamentele, chiar i cele fr funcionari, i funcionarii, chiar i cei care nu sunt asignai nici unui departament (full outer join). SELECT NVL(TO_CHAR(b.empno),***) id, NVL(a.dname,***) nume_dep FROM dept a, emp b WHERE a.deptno = b.deptno(+) UNION SELECT NVL(TO_CHAR(b.empno),***) id, NVL(a.dname,***) nume_dep FROM dept a, emp b WHERE a.deptno(+) = b.deptno; Rezultatul cererii va fi: id nume_dep *** analiza 101 *** 102 *** 103 *** 105 algebra 106 algebra

25

Exemplu utilizand ambele variant de outer join: Comanda corecta care afiseaza numele salariatilor si numele departamentelor in care lucreaza acestia, incluzand in rezultat si salariatii care nu lucreaza in niciun departament este: SELECT e.employee_id,last_name, e.department_id, department_name FROM employees e , departments d WHERE e.DEPARTMENT_ID= d.DEPARTMENT_ID(+); SELECT e.employee_id,last_name, e.department_id, department_name FROM employees e LEFT OUTER JOIN departments d ON (e.DEPARTMENT_ID= d.DEPARTMENT_ID); Utilizand USING in loc de ON (nu trebuie sa mai avem alias-uri) SELECT employee_id,last_name, department_id, department_name FROM employees e LEFT OUTER JOIN departments d USING (DEPARTMENT_ID); 2. Comanda corecta care afiseaza numele salariatilor si numele departamentelor in care lucreaza acestia, incluzand in rezultat si departamentele fara salariati este: SELECT e.employee_id,last_name, e.department_id, department_name FROM employees e , departments d WHERE e.DEPARTMENT_ID(+)= d.DEPARTMENT_ID; SELECT e.employee_id,last_name, e.department_id, department_name FROM employees e RIGHT OUTER JOIN departments d ON (e.DEPARTMENT_ID= d.DEPARTMENT_ID); Utilizand USING in loc de ON (nu trebuie sa mai avem alias-uri) SELECT employee_id,last_name, department_id, department_name FROM employees RIGHT OUTER JOIN departments USING (DEPARTMENT_ID);

26

Comanda corecta care afiseaza numele salariatilor si numele departamentelor in care lucreaza acestia, incluzand in rezultat si salariatii fara departamente si departamentele fara salariati este: SELECT employee_id,last_name, department_id, department_name FROM employees FULL OUTER JOIN departments USING (DEPARTMENT_ID); FULL OUTER JOIN nu poate fi implementat cu operatorul (+), deoarece acesta nu poate fi pus in ampele parti a semnului egal. Se poate folosi operatorul pe multimi UNION. SELECT e.employee_id,last_name, e.department_id, department_name FROM employees e , departments d WHERE e.DEPARTMENT_ID(+)= d.DEPARTMENT_ID UNION SELECT e.employee_id,last_name, e.department_id, department_name FROM employees e LEFT OUTER JOIN departments d ON (e.DEPARTMENT_ID= d.DEPARTMENT_ID); Uniuni ncruciate (cross joins) O uniune ncruciat (cross join) nu este altceva dect sintaxa standard pentru un produs cartezian. Interogarea care unea tabelele FILM i FILM_GEN i obinea un produs cartezian SELECT FILM_ID, FILM_GEN_DESCRIERE AS GEN, FILM_TITLU FROM FILM, FILM_GEN ORDER BY FILM_ID; poate fi rescris ca mai jos, folosind o uniune ncruciat: SELECT FILM_ID, FILM_GEN_DESCRIERE AS GEN, FILM_TITLU FROM FILM CROSS JOIN FILM_GEN ORDER BY FILM_ID; Se observa diferenta dintre FULL OUTER JOIN si CROSS JOIN(care este produs cartezian) SELECT employee_id, last_name, department_id, department_name FROM employees CROSS JOIN departments d; ON (e.DEPARTMENT_ID= d.DEPARTMENT_ID);

27

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