Sunteți pe pagina 1din 17

Cereri pe tabele multiple (continuare)

n sistemul Oracle10g, operaia de compunere se poate implementa i prin intermediul unei sintaxe specifice acesteia, introdus de standardul SQL3. Fa de compunerea realizat prin specificarea condiiei n clauza WHERE, aceast sintax nu aduce beneficii n privina performanei. Conform standardului SQL3, tipurile de compunere descrise anterior se pot rescrie, echivalent, prin cuvintele cheie NATURAL JOIN, FULL OUTER JOIN, JOIN cu clauzele USING i ON. Sintaxa corespunztoare standardului SQL3 este urmtoarea: SELECT tabel_1.nume_coloan, tabel_2.nume_coloan FROM tabel_1 [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) ]; Utiliznd aceste modaliti de specificare a operaiei de compunere, clauza FROM nlocuiete clauzele FROM i WHERE din exemplele anterioare. n lista SELECT sunt enumerate coloanele, calificate cu numele tabelelor din care provin, ale cror date sunt regsite. Operaia de compunere poate fi implementat cu ajutorul clauzei NATURAL JOIN n cazul n care coloanele pe baza crora se realizeaz compunerea au acelai nume n ambele tabele. Clauza determin selectarea liniilor din cele dou tabele, care au valori egale n toate coloanele ale cror nume coincid. Dac tipurile de date ale coloanelor cu nume identice sunt diferite, va fi returnat o eroare. Coloanele avnd acelai nume n cele dou tabele trebuie s nu conin calificatori (s nu fie precedate de numele sau alias-ul tabelului corespunztor). Pentru a putea preciza n mod explicit coloanele pe baza crora are loc compunerea, se poate utiliza clauza JOIN tabel_2 USING nume_coloan. Aceasta efectueaz un equijoin pe baza coloanei cu numele specificat n sintax. Clauza este util atunci cnd exist coloane avnd acelai nume, dar care nu trebuie s intre n condiia de join. Coloanele referite n clauza USING nu pot conine calificatori n nicio apariie a lor n instruciunea SQL. Clauzele NATURAL JOIN i USING nu pot exista simultan n aceeai instruciune SQL. Pentru a delimita condiiile de join i cele de cutare sau filtrare, este util clauza JOIN tabel_2 ON tabel_1.nume_coloan = tabel_2.nume_coloan, care efectueaz un equijoin pe baza condiiei exprimate n opiunea ON. Condiiile de cutare sau filtrare vor aprea distinct n clauza WHERE.

Exemplu. S se determine numele i tipul activitilor de publicitate realizate pentru prezentrile coordonate de ctre organizatorii avnd codurile 121 sau 134. Se va afia i denumirea prezentrilor de mod. Se vor funiza trei variante de rezolvare, utiliznd sintaxa specific standardului SQL3. SELECT denumire, nume, tip FROM prezentare NATURAL JOIN publicitate WHERE cod_organizator IN (121, 134); SELECT denumire, nume, tip FROM prezentare JOIN publicitate USING (cod_prezentare) WHERE cod_organizator IN (121, 134); SELECT p1.denumire, p2.nume, p2.tip FROM prezentare p1 JOIN publicitate p2USING (cod_prezentare) WHERE cod_organizator IN (121, 134); n cazul n care coloana din clauza USING este precedat de un alias de tabel n alt opiune a instruciunii SELECT, sistemul va returna eroarea ORA25154: column part of USING clause cannot have qualifier. O astfel de situaie este generat de cererea urmtoare: SELECT p1.denumire, p2.nume, p2.tip FROM prezentare p1 JOIN publicitate p2 ON (p1.cod_prezentare = p2.cod_prezentare); Cu ajutorul sintaxei specifice standardului SQL3, operaia de compunere ntre trei tabele poate fi realizat folosind clauzele ON sau USING. Operaiile de compunere se vor efectua de la stnga spre dreapta. Exemplu. S se afieze codul i denumirea organizatorilor, codul i denumirea prezentrilor, respectiv denumirea i valoarea vestimentaiilor prezentate. Se vor furniza dou variante de rezolvare, cu ajutorul sintaxei SQL3. SELECT o.cod_organizator, o.denumire, p.cod_prezentare, p.denumire, v.denumire, v.valoare FROM organizator o JOIN prezentare p ON p.cod_organizator = o.cod_organizator JOIN vestimentatie v ON p.cod_prezentare = v.cod_prezentare;

SELECT FROM JOIN JOIN

o.cod_organizator, o.denumire, p.cod_prezentare, p.denumire, v.denumire, v.valoare organizator o prezentare p USING (cod_organizator) vestimentatie v USING (cod_prezentare);

Prima operaie de compunere care se realizeaz este cea dintre tabelele organizator i prezentare. Condiia de join corespunztoare poate s fac referin la coloane din tabelele organizator i prezentare, dar nu poate face referin la coloane din tabelul vestimentatie. n a doua compunere, cea cu tabelul vestimentatie, condiia de join poate face referin la coloane din toate cele trei tabele. Condiiile suplimentare ale unei interogri pot fi specificate att n clauza WHERE, ct i n clauza ON. Exemplu. S se obin denumirile prezentrilor, tipul i numele locaiilor n care s-au desfurat, pentru prezentrile care au nceput n cursul lunii trecute. SELECT p.denumire, l.tip, l.denumire FROM prezentare p JOIN locatie l ON (p.cod_locatie = l.cod_locatie) AND TO_CHAR(p.data_start, 'MM/YYYY ') = TO_CHAR(ADD_MONTHS(SYSDATE, -1), 'MM/YYYY '); Instruciunea anterioar este corect i este echivalent cu comanda obinut nlocuind operatorul AND cu clauza WHERE. Prin intermediul clauzelor LEFT, RIGHT i FULL OUTER JOIN tabel_2 ON (tabel_1.nume_coloan = tabel_2.nume_coloan) se efectueaz compunerea extern la stnga, dreapta, respectiv compunerea extern complet pe baza condiiei exprimate n clauza ON. Compunerea extern complet (full outer join) returneaz rezultatele unui inner join, dar i cele ale outer join-urilor la stnga i la dreapta. Exemplu. S se afieze denumirile prezentrilor de mod i sumele cu care acestea au fost sponsorizate. Rezultatul va conine i prezentrile de mod nesponsorizate. SELECT denumire, suma FROM prezentare p LEFT OUTER JOIN finanteaza f ON (p.cod_prezentare = f.cod_prezentare); Exemplu. S se afieze denumirile organizatorilor i prezentrile coordonate de ctre acetia. Rezultatul va include i organizatorii care nu coordonat nicio prezentare de mod.

SELECT o.denumire, p.prezentare FROM prezentare p RIGHT OUTER JOIN organizator o ON (p.cod_organizator = o.cod_organizator); Exemplu. S se afieze denumirile organizatorilor i ale prezentrilor coordonate de acetia. Rezultatul va conine i organizatorii care nu au coordonat nicio prezentare, precum i prezentrile al cror organizator este necunoscut. SELECT o.denumire, p.denumire FROM prezentare p FULL OUTER JOIN organizator o ON (p.cod_organizator = o.cod_organizator);

Produsul cartezian
Compunerea este o submulime a unei combinaii mai generale de dou tabele, i anume produsul cartezian. De obicei, produsul cartezian genereaz un numr mare de linii i constituie o operaie puin util n practic. Un caz de utilizare a acestei operaii apare atunci cnd este necesar obinerea unui volum mare de date utile pentru anumite teste de simulare. Similar aplicrii sale n cazul mulimilor, produsul cartezian a dou tabele este un alt tabel care conine toate perechile posibile de linii din cele dou tabele. Coloanele tabelului produs sunt toate coloanele din primul tabel, urmate de toate coloanele din cel de-al doilea. Dac se specific o interogare asupra a dou tabele, fr o clauz WHERE, limbajul SQL va produce drept rezutat al interogrii produsul cartezian al acestora. Pentru produsul cartezian, standardul SQL3 prezint un format special al instruciunii SELECT: SELECT tabel_1.nume_coloan, tabel_2.nume_coloan FROM tabel_1 CROSS JOIN tabel_2; Exemplu. S se afieze toate modalitile de combinare ale liniilor tabelului prezentare cu cele ale tabelului organizator (2 variante de scriere). SELECT * FROM prezentare, organizator; SELECT * FROM prezentare CROSS JOIN organizator; Procedura de generare a rezultatelor unei instruciuni SELECT referitoare la o compunere este urmtoarea: 1) formarea produsului cartezian al tabelelor enumerate n clauza FROM;

2) dac exist o clauz WHERE, condiia de cutare se aplic fiecrui rnd al tabelului produs, fiind reinute cele care satisfac condiia; 3) pentru fiecare linie rmas, se determin valoarea fiecrui element din lista SELECT, pentru a produce o singur linie n tabelul rezultant; 4) dac a fost specificat cuvntul cheie DISTINCT, se elimin liniile duplicat din tabelul rezultant; 5) dac exist o clauz ORDER BY, se sorteaz tabelul rezultant conform criteriilor specificate. n termeni de algebr relaional, pasul 2 descris anterior creeaz o restricie a produsului cartezian, iar etapele 3 i 4 sunt echivalente unei proiecii a restriciei asupra coloanelor menionate n lista SELECT.

Subcereri
Prin intermediul subcererilor se pot construi interogri complexe pe baza unor instruciuni simple. O subcerere (subinterogare) este o comand SELECT integrat ntr-o clauz a altei instruciuni SQL, numit instruciune printe sau instruciune exterioar. Subcererile mai sunt numite instruciuni SELECT imbricate sau interioare. Rezultatele subcererii sunt utilizate n cadrul cererii exterioare, pentru a determina coninutul rezultatului final. n funcie de modul de evaluare a subcererii n raport cu cererea exterioar, subcererile pot fi nesincronizate (necorelate) sau sincronizate (corelate). Prima clas de subcereri este evaluat dinspre interior ctre exterior, adic interogarea extern acioneaz pe baza rezultatului cererii interne. Al doilea tip de subcerere este evaluat invers, adic interogarea extern furnizeaz valori cererii interne, iar rezultatele subcererii sunt transferate cererii externe. Din punct de vedere al numrului de linii i coloane returnate, exist trei tipuri de subcereri: scalare, care returneaz o singur coloan i o singur linie i pot fi folosite atunci cnd este necesar o singur valoare; pe o linie, care returneaz coloane multiple, dar o singur linie, i pot fi utile atunci cnd este necesar un constructor de valori ale liniei (de regul, n predicate); pe un tabel, care returneaz una sau mai multe coloane i linii multiple. Subcererile ofer funcionaliti complexe instruciunilor care le conin. Astfel, prin intermediul lor este posibil: furnizarea de valori necesare condiiilor specificate n clauzele

WHERE, HAVING i START WITH ale instruciunilor SELECT; definirea unei mulimi de nregistrri care urmeaz s fie introduse ntr-un tabel printr-o instruciune INSERT sau CREATE TABLE; definirea unei mulimi de nregistrri care urmeaz s fie inserate ntr-o vizualizare sau vizualizare materializat, prin intermediul unei instruciuni CREATE VIEW sau CREATE MATERIALIZED VIEW; definirea uneia sau mai multor valori care urmeaz s fie atribuite unor linii existente ntr-o instruciune UPDATE; definirea unei vizualizri asupra creia va opera cererea extern, prin plasarea subcererii n clauza FROM sau n instruciunile INSERT, UPDATE, DELETE. O astfel de subcerere se mai numete vizualizare in-line.

Exist anumite reguli care se impun n utilizarea unei subcereri. Astfel, subcererea trebuie inclus ntre paranteze, iar pentru claritate, ea se plaseaz n partea dreapt a operatorului de comparaie. Operatorul folosit trebuie s fie conform cu tipul cererii. Cererea va genera o eroare dac este utilizat un operator single-row n faa unei subcereri care fie nu returneaz nicio linie, fie returneaz mai multe linii. Subcererile nu puteau s conin clauza ORDER BY nainte de versiunea Oracle8i. ncepnd cu aceast versiune, clauza poate fi utilizat i este deosebit de util n efectuarea analizei top-n, care const n obinerea celor mai mari sau celor mai mici n valori ale unei coloane. Serverul Oracle nu impune nicio limit asupra numrului de subcereri. Limita acestora depinde de dimensiunea buffer-ului utilizat de cerere.

Subcereri nesincronizate
Utilizarea unei subcereri nesincronizate (necorelate) este echivalent cu efectuarea a dou cereri secveniale i utilizarea rezultatului cererii interne ca valoare de filtrare sau cutare n cererea extern. O astfel de subcerere poate fi privit ca o realizare a unui tabel temporar, cu rezultate care pot fi accesate i utilizate de ctre instruciunea exterioar. Modul de evaluare al unei cereri care conine o subcerere nesincronizat este urmtorul: subcererea este executat prima i determin un rezultat (acesta este constituit dintr-o valoare sau o mulime de valori); cererea extern se execut o singur dat, utiliznd rezultatul furnizat de subcerere. Forma general a unei subcereri nesincronizate care apare n clauza WHERE a unei interogri este urmtoarea:

SELECT FROM WHERE

expresie1, expresie2, ... nume_tabel1 expresie_condiie operator (SELECT expresie FROM nume_tabel2);

Operatorul ce intervine n specificarea condiiei poate fi de tip: single-row (>, =, >=, <, <>, <=), care poate fi utilizat dac subcererea returneaz o singur linie; multiple-row (IN, ANY, ALL), care poate fi folosit dac subcererea returneaz mai mult de o linie. Cuvintele cheie ANY i ALL pot fi utilizate cu subcererile care produc o singur coloan de valori. Dac subcererea este precedat de ctre cuvntul cheie ALL, atunci condiia va fi adevrat numai dac este satisfcut de ctre toate valorile produse de subcerere. Astfel, <ALL are semnificaia mai mic dect minimul, iar >ALL este echivalent cu mai mare dect maximul. Dac subcererea este precedat de ctre cuvntul cheie ANY, condiia va fi adevrat dac este satisfcut de ctre oricare (una sau mai multe) dintre valorile produse de subcerere. n comparaii, <ANY are semnificaia mai mic dect maximul; >ANY reprezint mai mare dect minimul; =ANY este echivalent cu operatorul IN. Dac subcererea returneaz mulimea vid, atunci condiia ALL va returna valoarea true, iar condiia ANY va returna valoarea false. Standardul ISO permite utilizarea cuvntului cheie SOME, n locul lui ANY. Condiiile specificate cu ajutorul operatorilor multiple-row pot fi negate cu ajutorul cuvntului cheie NOT. Exemplu. S se afieze denumirea i valoarea vestimentaiilor concepute de creatorul care a realizat vestimentaia avnd codul 225 i care au fost purtate de ctre unul dintre modelele care a participat la prezentrile Fall 2007 sau Spring 2008. SELECT denumire, valoare FROM vestimentatie WHERE cod_creator = (SELECT cod_creator FROM vestimentatie WHERE cod_vestimentatie = 225) AND cod_model IN (SELECT cod_model FROM vestimentatie WHERE cod_prezentare IN (SELECT cod_prezentare FROM prezentare

WHERE denumire IN ('Fall 2007 ', 'Spring 2008 '))); Exemplu. S se determine creatorul de mod pentru care valoare medie a vestimentaiilor realizate este minim. SELECT cod_creator, AVG(valoare) FROM vestimentatie GROUP BY cod_creator HAVING AVG(valoare) = (SELECT MIN(AVG(valoare)) FROM vestimentatie GROUP BY cod_creator); Exemplu. Pentru fiecare model, s se afieze numele, prenumele i valoarea celei mai scumpe vestimentaii pe care a prezentat-o. SELECT a.nume, a.prenume, v.valoare FROM vestimentatie v, model m, angajat_temp a WHERE v.cod_model = m.cod_angajat AND m.cod_angajat = a.cod_angajat AND (cod_model, valoare) IN (SELECT cod_model, MIN(valoare) FROM vestimentatie GROUP BY cod_model); Exemplu. S se afieze vestimentaiile a cror valoare este mai mic dect valoarea unei vestimentaii expuse n cadrul prezentrii avnd codul 200 i mai mare dect a oricrei vestimentaii purtate de modelul avnd codul 45. Se vor furniza dou variante de rezolvare. SELECT cod_vestimentatie, denumire, valoare FROM vestimentatie WHERE valoare < ANY (SELECT valoare FROM vestimentatie WHERE cod_prezentare = 200) AND valoare > ALL (SELECT valoare FROM vestimentatie WHERE cod_model = 45); SELECT cod_vestimentatie, denumire, valoare FROM vestimentatie WHERE valoare < (SELECT MAX(valoare) FROM vestimentatie WHERE cod_prezentare = 200) AND valoare > (SELECT MAX(valoare) FROM vestimentatie

WHERE

cod_model = 45);

Exemplu. S se afieze valoarea total a celor mai scumpe 3 sponsorizri oferite, precum i numele sponsorilor respectivi. Rezultatul va conine o coloan care va indica numrul de ordine al nregistrrii. SELECT ROWNUM "Nr.Crt", suma, nume FROM (SELECT cod_sponsor, suma FROM finanteaza ORDER BY suma DESC) sm, sponsor s WHERE sm.cod_sponsor = s.cod_sponsor AND ROWNUM <= 3; Exemplu. S se afieze numele i prenumele creatorilor care nu au creat vestimentaii mai scumpe dect 2000. SELECT nume, prenume FROM creator WHERE cod_creator NOT IN (SELECT cod_creator FROM vestimentatie WHERE valoare > 2000 AND cod_creator IS NOT NULL); Necesitatea testrii valorilor null returnate de ctre subcerere provine din faptul c, dac pentru una dintre vestimentaii valoarea coloanei cod_creator este null, atunci ntreaga cerere nu va returna nicio linie, chiar dac exist nregistrri cu proprietatea cerut. Justificarea este c testul de neapartenen a unei valori la o mulime (NOT IN) este echivalent cu o conjuncie de condiii avnd forma expresie != valoare. Atunci cnd unul dintre operanzii valoare este null, condiia respectiv va fi null i rezult c ntreaga conjuncie va avea, de asemenea, valoarea null. Prin urmare, dac este este utilizat operatorul NOT IN n faa unei subcereri, iar rezultatul subcererii ar putea s conin valori null, atunci aceste valori trebuie excluse cu ajutorul operatorului IS NOT NULL. Acest operator este echivalent cu <>ALL. Dac se utilizeaz operatorul IN, nu mai este nicio problem atunci cnd n rezultatul subcererii apar valori null. Operatorul IN este echivalent cu =ANY. O alt modalitate de a depi problema valorilor null n subcererile precedate de NOT IN const n utilizarea funciei NVL n clauza SELECT a subcererii. n exemplul anterior, aceasta se poate rescrie prin specificaia SELECT NVL(cod_creator, 0). Exemplu. S se afieze codul, denumirea prezentrilor i valoarea total a vestimentaiilor expuse. SELECT p.cod_prezentare, p.denumire, s.suma FROM prezentare p,

10

WHERE

(SELECT cod_prezentare ,SUM(valoare) suma FROM vestimentatie GROUP BY cod_prezentare) s p.cod_prezentare = s.cod_prezentare;

Subcereri sincronizate
Subcererile sincronizate sunt importante n rezolvarea unor probleme care sunt mai dificil de tratat cu ajutorul operaiilor de compunere (join) sau al cererilor nesincronizate. Aceste subcereri permit compararea valorilor unei linii cu date determinate pe baza acestor valori. O cerere sincronizat se recunoate cu uurin, prin faptul c ea nu poate fi evaluat independent, fcnd referin la instruciunea extern i fiind executat o dat pentru fiecare linie procesat de ctre instruciunea extern. Aceast instruciune poate fi SELECT, UPDATE sau DELETE. Subcererile sincronizate necesit calificarea explicit a numelui coloanelor care refer cererea extern, cu numele sau alias-ul tabelului corespunztor. Modul de evaluare al unei cereri sincronizate este urmtorul: 1) cererea extern determin o linie candidat; 2) subcererea este executat utiliznd valorile liniei candidat; 3) rezultatul subcererii este utilizat de ctre cererea extern pentru calificarea sau descalificarea liniei candidat; 4) paii precedeni se repet pn cnd nu mai exist linii candidat. Forma general a unei subcereri sincronizate care apare n clauza WHERE a unei interogri este urmtoarea: SELECT expresie_ext1, expresie_ext2 ... FROM nume_tabel_1 extern WHERE expresie_ext_comparatie operator (SELECT expresie_int FROM nume_tabel_2 WHERE expresie_int_comparaie = extern.expresie_ext); Exemplu. S se afieze vestimentaiile a cror valoare este mai mare dect media celor expuse n cadrul aceleiai prezentri. SELECT denumire, valoare, cod_prezentare FROM vestimentatie v WHERE valoare > (SELECT AVG(valoare) FROM vestimentatie WHERE cod_prezentare = v.cod_prezentare); Conceptual, procesarea acestei instruciuni se realizeaz urmnd paii

11

descrii n continuare. Cererea extern regsete prima linie de informaii din tabelul vestimentatie. Aceasta este prima linie candidat. Subcererea este evaluat pe baza valorii coloanei v.cod_prezentare de pe linia candidat, calculnd valoarea medie pentru prezentarea respectiv. Clauza WHERE a cererii externe este evaluat pe baza acestui rezultat. Se determin dac linia candidat este selectat n rezultatul cererii. Dac valoarea este mai mare dect media calculat de subcerere, atunci linia este reinut n rezultatul final. Aceti pai se repet pentru urmtoarele linii candidat din tabel, pn cnd sunt procesate toate liniile tabelului. Exemplu. S se afieze codul, numele i prenumele artitilor care au cel puin dou opere de art expuse n muzeu. SELECT denumire, valoare, cod_prezentare FROM vestimentatie v WHERE 3 <= (SELECT COUNT(*) FROM accesoriu WHERE cod_vestimentatie = v.cod_vestimentatie); Exemplu. S se determine codul prezentrii, valoarea total a vestimentaiilor pentru prezentarea respectiv i valoarea total a vestimentaiilor din prezentarea respectiv, pentru fiecare dintre creatorii avnd codurile 55, 60, 65. Se vor eticheta coloanele corespunztor. Se vor furniza dou metode de rezolvare. SELECT cod_prezentare, SUM(DECODE(cod_creator, 55, valoare)) "Creator 55", SUM(DECODE(cod_creator, 60, valoare)) "Creator 60", SUM(DECODE(cod_creator, 65, valoare)) "Creator 65", SUM(valoare) Total FROM vestimentatie GROUP BY job_id; SELECT cod_prezentare, (SELECT SUM(valoare) FROM vestimentatie WHERE cod_creator = 55 AND cod_prezentare = p.cod_prezentare) Cr55, (SELECT SUM(valoare) FROM vestimentatie

12

WHERE cod_creator = 60 AND cod_prezentare = p.cod_prezentare) Cr60, (SELECT SUM(valoare) FROM vestimentatie WHERE cod_creator = 65 AND cod_prezentare = p.cod_prezentare) Cr65, SUM(valoare) Total FROM prezentare p GROUP BY cod_prezentare;

Operatorul EXISTS
Operatorul EXISTS este proiectat pentru a fi utilizat numai n contextul subcererilor. Acest operator produce un rezultat simplu, de tip boolean. Condiia obinut cu ajutorul cuvntului cheie EXISTS este true dac exist cel puin o linie returnat de ctre subcerere, i este false dac subcererea returneaz o mulime rezultat vid. Acest operator este util pentru a testa dac valoarea recuperat de cererea extern exist n mulimea valorilor regsite de o cerere intern sincronizat a sa. Deoarece operatorul EXISTS nu face dect s verifice existena sau inexistena liniilor n rezultatul subcererii, aceasta poate conine orice numr de coloane. Nefiind necesar ca subcererea s returneze o anumit valoare, se poate selecta o constant. De altfel, din punct de vedere al performanei, selectarea unei constante asigur mai mare rapiditate dect selectarea unei coloane. Un avantaj al operatorului EXISTS este dat de faptul c nu mai este continuat cutarea n cererea intern dup ce aceasta regsete o linie. Ca alternativ a lui EXISTS, poate fi utilizat operatorul IN ntr-o cerere nesincronizat. Exemplu. S se determine, n dou moduri (cu i fr sincronizare), codul i denumirea organizatorilor care au coordonat cel puin o prezentare. SELECT cod_organizator, denumire FROM organizator o WHERE EXISTS (SELECT 1 FROM prezentare WHERE cod_organizator = o.cod_organizator); SELECT FROM WHERE cod_organizator, denumire organizator cod_organizator IN (SELECT FROM

cod_organizator prezentare);

13

Exemplu. S se determine, n dou moduri, codurile modelelor care nu au participat la nicio prezentare. SELECT cod_angajat FROM model m WHERE NOT EXISTS (SELECT 'x' FROM vestimentatie WHERE m.cod_angajat = cod_model); SELECT cod_angajat FROM model m WHERE cod_angajat NOT IN (SELECT NVL(cod_model, 0) FROM vestimentatie WHERE m.cod_angajat = cod_model); Exemplu. S se obin numele i prenumele modelelor care au defilat cel puin n aceleai prezentri ca i modelul avnd codul 144. Pentru rezolvarea acestei cereri, trebuie selectate modelele pentru care este vid lista prezentrilor la care a lucrat modelul 144 mai puin lista prezentrilor la care au defilat acele modele. SELECT nume, prenume FROM vestimentatie v, model m, angajat_temp a WHERE v.cod_model = m.cod_angajat AND m.cod_angajat = a.cod_angajat AND NOT EXISTS (SELECT cod_prezentare FROM vestimentatie WHERE cod_model = 144 MINUS SELECT cod_prezentare FROM vestimentatie WHERE cod_model = m.cod_angajat); Exemplu. S se obin numele i prenumele modelelor care au lucrat cel mult la aceleai prezentri ca i modelul avnd codul 144. SELECT nume, prenume FROM vestimentatie v, model m, angajat_temp a WHERE v.cod_model = m.cod_angajat AND m.cod_angajat = a.cod_angajat AND NOT EXISTS (SELECT cod_prezentare FROM vestimentatie

14

WHERE MINUS SELECT FROM WHERE Exemplu. S se obin modelul avnd codul 144. SELECT nume, prenume FROM vestimentatie WHERE v.cod_model = AND m.cod_angajat AND NOT EXISTS (SELECT FROM WHERE MINUS SELECT FROM WHERE AND NOT EXISTS (SELECT FROM WHERE MINUS SELECT FROM WHERE AND cod_model !=

cod_model = m.cod_angajat cod_prezentare vestimentatie cod_model = 144); modelele care au lucrat la aceleai prezentri ca i

v, model m, angajat_temp a m.cod_angajat = a.cod_angajat cod_prezentare vestimentatie cod_model = 144 cod_prezentare vestimentatie cod_model = m.cod_angajat) cod_prezentare vestimentatie cod_model = m.cod_angajat cod_prezentare vestimentatie cod_model = 144) 144;

Operatorul NOT EXISTS este util n implementarea operaiei de diviziune din algebra relaional. Diviziunea este o operaie binar care definete o relaie ce conine valorile atributelor dintr-o relaie care apar n toate valorile atributelor din cealalt relaie. Operatorul DIVISION al algebrei relaionale este legat de cuantificatorul universal () care nu exist n SQL. Cuantificatorul universal poate fi ns simulat cu ajutorul cuantificatorului existenial () utiliznd relaia: x P(x) x P(x). Prin urmare, operatorul DIVISION poate fi exprimat n SQL prin succesiunea a doi operatori NOT EXISTS. O alt modalitate de implementare a operatorului DIVISION este cu ajutorul funciei COUNT.

15

Exemplu. S se obin codurile sponsorilor care au finanat toate prezentrile care au nceput n anul 2008. Se vor furniza dou soluii. SELECT DISTINCT cod_sponsor FROM finanteaza f WHERE NOT EXISTS (SELECT 1 FROM prezentare p WHERE TO_CHAR(data_start, 'YYYY ') = 2008 AND NOT EXISTS (SELECT 'x' FROM finanteaza fi WHERE p.cod_prezentare = fi.cod_prezentare AND fi.cod_sponsor = f.cod_sponsor)); SELECT cod_sponsor FROM finanteaza WHERE cod_prezentare IN (SELECT cod_prezentare FROM prezentare WHERE TO_CHAR(data_start, 'YYYY') = 2008) GROUP BY cod_sponsor HAVING COUNT(cod_prezentare)= (SELECT COUNT(*) FROM prezentare WHERE TO_CHAR(data_start, 'YYYY') = 2008);

Definirea blocurilor de cerere n clauza WITH


Atunci cnd o interogare face referin de mai multe ori la o aceeai subcerere, este util definirea blocului de cerere corespunztor nainte de a fi utilizat n interogarea respectiv. Acest lucru este posibil prin intermediul clauzei WITH i este deosebit de util atunci cnd cererea astfel definit este complex, coninnd operaii de compunere i funcii agregat. Clauza permite reutilizarea aceluiai bloc de cerere ntr-o instruciune SELECT complex. Serverul Oracle regsete rezultatele unui bloc de cerere definit n clauza WITH i le stocheaz n spaiul tabel temporar al utilizatorului, fapt ce poate determina mbuntirea performanelor. Intern, clauza WITH este tratat ca o vizualizare inline (subcerere n clauza FROM) sau ca un tabel temporar. Optimizorul alege decizia adecvat pe baza costului sau beneficiului stocrii temporare a rezultatelor clauzei WITH.

16

Clauza WITH poate fi folosit numai pentru instruciuni SELECT. Un nume de bloc de cerere este vizibil tuturor cererilor din clauza WITH definite ulterior (inclusiv subcererilor acestora). De asemenea, un nume de bloc de cerere este vizibil cererii principale i subcererilor acesteia. Atunci cnd un nume de cerere coincide cu numele unui tabel, numele de cerere are preceden asupra numelui tabelului. n clauza WITH se pot defini mai mult dect o singur cerere. n acest caz, cererile sunt separate prin virgule. Exemplu. S se obin numele creatorilor de mod i valoarea total a obiectelor realizate de ctre acetia. Se vor considera att creatorii de vestimentaii ct i cei de accesorii, a cror valoare total a obiectelor este mai mare dect media valorilor totale ale obiectelor tuturor creatorilor. Interogarea va utiliza cereri definite n clauza WITH. WITH val_creator_vestim AS (SELECT nume, prenume, SUM(valoare) AS total FROM vestimentatie v, creator c WHERE v.cod_creator = c.cod_creator GROUP BY nume, prenume), val_creator_accesorii AS (SELECT nume, prenume, SUM(valoare) AS total FROM accesoriu a, creator c WHERE a.cod_creator = c.cod_creator GROUP BY nume, prenume), val_medie_vestim AS (SELECT SUM(total)/COUNT(*) AS medie FROM val_creator_vestim) val_medie_accesorii AS (SELECT SUM(total)/COUNT(*) AS medie FROM val_creator_accesorii) SELECT * FROM val_creator_vestim WHERE total > (SELECT medie FROM val_medie) UNION SELECT * FROM val_creator_accesorii WHERE total > (SELECT medie

17

FROM ORDER BY nume;

val_medie)

Subcereri scalare
O subcerere scalar trebuie s returneze o singur coloan i o singur linie. Dac subcererea scalar returneaz 0 linii, valoarea ei este null, iar dac ntoarce mai mult de o linie, serverul genereaz o eroare. Subcererile scalare pot aprea n toate clauzele instruciunii SELECT, cu excepia lui GROUP BY, n clauza VALUES a instruciunii INSERT i n partea stng a operatorului, n clauzele SET i WHERE ale instruciunii UPDATE. De asemenea, ele pot aprea n condiiile i expresiile care fac parte din DECODE sau CASE. Subcererile scalare nu pot aprea ca valori implicite pentru coloane sau ca expresii hash pentru grupri. De asemenea, ele nu sunt permise n clauza RETURNING a instruciunilor LMD, n clauza GROUP BY, n constrngerile de tip CHECK i condiiile WHEN. Exemplu. S se afieze codul, denumirea prezentrilor i cea a organizatorului doar dac acesta este Expo&Show. n caz contrar, se va afia irul alt organizator. SELECT cod_prezentare, denumire, (CASE WHEN cod_organizator = (SELECT cod_organizator FROM organizator WHERE denumire = 'Expo&Show') THEN 'Expo&Show' ELSE 'Alt organizator' END) organizator FROM prezentare;

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