CURS BD Combinat

410
1. GENERALITĂŢI DESPRE BAZE DE DATE 1.1. Introducere Baza de date este un ansamblu structurat de date coerente, fără redondanţă inutilă, astfel încât acestea pot fi prelucrate eficient de mai mulţi utilizatori într-un mod concurent. Baza de date este o colecţie de date persistente, care sunt folosite de către sistemele de aplicaţii ale unei anumite „întreprinderi“. Datele din baza de date persistă deoarece, după ce au fost acceptate de către sistemul de gestiune pentru introducerea în baza de date, ele pot fi şterse din bază numai printr-o cerere explicită adresată sistemului de gestiune. Aici, termenul de „întreprindere“ este un cuvânt generic, utilizat pentru a desemna orice organizaţie independentă, de natură tehnică, comercială, ştiinţifică sau de alt tip. Întreprinderea poate fi, de exemplu, un spital, o bancă, o facultate, o fabrică, un aeroport etc. Fiecare întreprindere are regulile proprii de funcţionare şi conţine o mulţime de date referitoare la modul său de operare. Datele din baza de date pot fi atît integrate, cât şi partajate. Noţiunea de integrat se referă la faptul că baza de date poate fi considerată ca o unificare a mai multor fişiere, iar prin partajare se înţelege că baza de date poate fi partajată concurent între diferiţi utilizatori. Un sistem de gestiune a bazelor de date (SGBD – Data Base Management System) este un produs software care asigură interacţiunea cu o bază de date, permiţând definirea, consultarea şi actualizarea datelor din baza de date. Toate cererile de acces la baza de date sunt tratate şi controlate de către SGBD. Organizarea datelor în baze de date constituie o formă de centralizare a acestora. Aceasta implică existenţa unui administrator al bazei de date (DBA – Data Base Administrator) care este o persoană sau un grup de persoane ce răspund de ansamblul activităţilor (analiză, proiectare, implementare, exploatare, întreţinere etc.) legate de baza de date. Atribuţiile unui administrator pot fi grupate în patru mari categorii: atribuţii de proiectare, atribuţii administrative, atribuţii operative şi atribuţii de coordonare. Concepte ale bazelor de date relaţionale În această parte se face o prezentare generală a conceptelor bazelor de date relaţionale. O bază de date relațională este o colecţie de informaţii interrelaţionate gestionate ca o singură unitate.

description

Cursuri diverse de baze de date

Transcript of CURS BD Combinat

Page 1: CURS BD Combinat

1. GENERALITĂŢI DESPRE BAZE DE DATE

1.1. Introducere Baza de date este un ansamblu structurat de date coerente, fără

redondanţă inutilă, astfel încât acestea pot fi prelucrate eficient de mai mulţi utilizatori într-un mod concurent.

Baza de date este o colecţie de date persistente, care sunt folosite de către sistemele de aplicaţii ale unei anumite „întreprinderi“. Datele din baza de date persistă deoarece, după ce au fost acceptate de către sistemul de gestiune pentru introducerea în baza de date, ele pot fi şterse din bază numai printr-o cerere explicită adresată sistemului de gestiune.

Aici, termenul de „întreprindere“ este un cuvânt generic, utilizat pentru a desemna orice organizaţie independentă, de natură tehnică, comercială, ştiinţifică sau de alt tip. Întreprinderea poate fi, de exemplu, un spital, o bancă, o facultate, o fabrică, un aeroport etc. Fiecare întreprindere are regulile proprii de funcţionare şi conţine o mulţime de date referitoare la modul său de operare.

Datele din baza de date pot fi atît integrate, cât şi partajate. Noţiunea de integrat se referă la faptul că baza de date poate fi considerată ca o unificare a mai multor fişiere, iar prin partajare se înţelege că baza de date poate fi partajată concurent între diferiţi utilizatori.

Un sistem de gestiune a bazelor de date (SGBD – Data Base Management System) este un produs software care asigură interacţiunea cu o bază de date, permiţând definirea, consultarea şi actualizarea datelor din baza de date. Toate cererile de acces la baza de date sunt tratate şi controlate de către SGBD. Organizarea datelor în baze de date constituie o formă de centralizare a acestora. Aceasta implică existenţa unui administrator al bazei de date (DBA – Data Base Administrator) care este o persoană sau un grup de persoane ce răspund de ansamblul activităţilor (analiză, proiectare, implementare, exploatare, întreţinere etc.) legate de baza de date. Atribuţiile unui administrator pot fi grupate în patru mari categorii: atribuţii de proiectare, atribuţii administrative, atribuţii operative şi atribuţii de coordonare.

Concepte ale bazelor de date relaţionale În această parte se face o prezentare generală a conceptelor bazelor

de date relaţionale. O bază de date relațională este o colecţie de informaţii

interrelaţionate gestionate ca o singură unitate.

Page 2: CURS BD Combinat

2 A ceastă definiţie este foarte largă, deoarece există mari diferenţe

între concepţiile diferiţilor producători care pun la dispoziţie sisteme de baze de date. De exemplu, Oracle Corporation defineşte o bază de date ca fiind o colecţie de fişiere fizice gestionate de o singură instanţă (copie) a produsului software pentru baze de date, în timp ce Microsoft defineşte o bază de date SQL Server ca fiind o colecţie de date şi alte obiecte.

Un obiect al bazei de date este o structură de date denumită, stocată în bază de date, cum ar fi un tabel, o vizualizare sau un index.

Există mari diferenţe între implementările furnizorilor de baze de date. În majoritatea sistemelor de baze de date, datele sunt stocate în mai multe fişiere fizice, dar în Microsoft Access toate obiectele bazei de date, împreună cu datele care aparţin unei baze de date sunt stocate într-un singur fişier fizic.(Un fişier este o colecţie de înregistrări înrudite stocate ca o singură untiate de sistemul de operare al calculatorului.) Totuşi, unul dintre principalele avantaje ale bazelor de date relaţionale este faptul că detaliile de implementare fizică sunt separate de definiţiile logice ale obiectelor bazei de date, astfel încât majoritatea utilizatorilor bazei de date nu au nevoie să ştie unde (şi cum) sunt stocate obiectele bazei de date în sistemul de fişiere al calculatorului.

Sistem de gestionare a bazei de date (DBMS sau SGBD)

Un sistem de gestionare a bazei de date (DBMS database

management system) este un produs software furnizat de producătorul bazei de date. Produse software precum Microsoft Access, Microsoft SQL Server, Oracle Database,Sybase, DB2,INGRES, MySQL şi Postgre SQL fac parte din categoria DBMS sau, mai corect, DBMS relaţionale (RDBMS).

RDBMS-urile sunt cunoscute şi sub numele de SGBD-uri. Ambele prescurtări vor fi folosite în acestă expunere.

Sistemul DBMS pune la dispoziţie toate serviciile de bază necesare pentru organizarea şi întreţinerea bazei de date, inclusiv următoarele:

- Transferarea datelor în şi din fişierele fizice de date, în funcţie de cerinţe.

- Gestionarea accesului concurenţial la date al mai multor utilizatori, inclusiv prevenirea conflictelor care ar putea fi cauzate de actualizările simultane.

- Gestionarea tranzacţiilor, astfel încât toate modificările făcute asupra bazei de date printr-o tranzacţie să fie executate ca o singură unitate. Cu alte cuvinte, dacă tranzacţia reuşeşte, toate

Page 3: CURS BD Combinat

3

modificările efectuate de tranzacţie sunt înregistrate în bază de date; dacă tranzacţia eşuează, nici una dintre modificări nu este înregistrată în bază de date.Totuşi, reţineţi ca unele sisteme RDBMS nu asigură suportul pentru tranzacţii.

- Acceptă un limbaj de interogare, care reprezintă sistemul de comenzi folosit de utilizator pentru a obţine date din bază de date. SQL este principalul limbaj folosit pentru sistemele DBMS relaţionale.

- Funcţii pentru salvarea bazei de date şi pentru refacerea bazei de date în urma erorilor.

- Mecanisme de securitate pentru împiedicarea accesului neautorizat la date şi modificarea acestora.

Ce este o bază de date relaţională ? O bază de date relaţională este o bază de date care respectă modelul

relaţional, dezvoltat de Dr.E.F.Codd. Modelul relaţional prezintă datele sub forma familiarelor tabele bidimensionale, similar cu o foaie de calcul tabelar. Spre deosebire de o foaie de calcul tabelar, nu este obligatoriu ca datele să fie stocate într-o formă tabelară, iar modelul permite şi combinarea tabelelor (crearea uniunilor (joining), în terminologia relaţională) pentru formarea vizualizarilor, care sunt prezentate tot ca tabele bidimensionale. Flexibilitatea extraordinară a bazelor de date relaţionale este dată de posibilitatea de a folosi tabelele independent sau în combinaţii, fără nici o ierarhie sau secvenţă predefinită în care trebuie să se facă accesul la date.

Dicţionarul datelor (catalog de sistem), structurat şi administrat

ca o bază de date (metabază de date), contine „date despre date“, furnizează descrierea tuturor obiectelor unei baze de date, starea acestor obiecte, diversele constrângeri de securitate şi de integritate etc. Dicţionarul poate fi interogat, la fel, ca orice altă bază de date.

Page 4: CURS BD Combinat

4

1.2. Gestiunea bazelor de date

Un sistem de baze de date presupune următoarele componente principale, care definesc arhitectura acestuia:

• baza de date propriu-zisă în care se memorează datele; • sistemul de gestiune a bazei de date, care realizează gestionarea şi

prelucrarea complexă a datelor; • un dicţionar al bazei de date (metabaza de date), ce conţine

informaţii despre date, structura acestora, statistici, documentaţie; • mijloace hardware (comune sau specializate); • reglementări administrative destinate bunei funcţionări a

sistemului; • personalul implicat (utilizatori finali, administratorul datelor,

administratorul bazei de date, proiectanţi, programatori de aplicaţii).

Se pot identifica patru categorii de persoane implicate în mediul bazelor de date:

• administratorii de date şi baze de date, • proiectanţii (designeri) de baze de date, • programatorii de aplicaţii, • utilizatorii finali. Administratorul de date (DA) este un manager, nu un tehnician, ce: • decide care date trebuie stocate în baza de date; • stabileşte regulile de întreţinere şi de tratare a acestor date după ce

sunt stocate. De exemplu, o regulă ar putea fi aceea prin care se stabilesc pentru utilizatori privilegii asupra informaţiilor din baza de date, cu alte cuvinte o anumită politică de securitate a datelor.

Administratorul bazei de date (DBA) este responsabil cu implementarea deciziilor administratorului de date şi cu controlul general al sistemului, la nivel tehnic. El este un profesionist în domeniul IT, care:

• creează baza de date reală; • implementează elementele tehnice de control; • este responsabil cu asigurarea funcţionării sistemului la

performanţe adecvate, cu monitorizarea performanţelor; • furnizează diverse servicii tehnice etc. Proiectanţii de baze de date pot acoperi atât aspectul fizic, cât şi cel

logic al concepţiei. Proiectantul de baze de date care abordează direcţia logică trebuie să

posede o cunoaştere completă şi amănunţită a modelului real de proiectat şi a regulilor de funcţionare ale acestuia. Practic, acesta proiectează

Page 5: CURS BD Combinat

5

conceptual baza de date, iar modelul creat este independent de programele de aplicaţii, de limbajele de programare. De asemenea, va proiecta logic baza de date, proiectare care este îndreptată spre un anumit model de date (relaţional, orientat obiect, ierarhic etc.).

Proiectantul de baze de date fizice preia modelul logic de date şi stabileşte cum va fi realizat fizic. Acesta trebuie să cunoască funcţionalităţile SGBD-ului, avantajele şi dezavantajele fiecărei alternative corespunzătoare unei implementări. Practic, se face transpunerea modelului logic într-un set de tabele supuse unor constrângeri, se selectează structuri de stocare şi metode de acces specifice, astfel încât să se asigure performanţe, se iau măsuri privind securitatea datelor.

Utilizatorii finali sunt cei care accesează interactiv baza de date. Aceasta a fost proiectată, implementată, întreţinută pentru a satisface necesităţile informaţionale ale clienţilor. Utilizatorii finali pot fi utilizatori simpli, care nu cunosc nimic despre baza de date, despre SGBD, dar accesează baza prin intermediul unor programe de aplicaţie. În general, această clasă de utilizatori alege anumite opţiuni din meniul aplicaţiei. Există utilizatori finali sofisticaţi, care sunt familiarizaţi cu structura bazei de date. Ei pot utiliza limbaje speciale pentru a exploata posibilităţile oferite de baza de date.

Programatori de aplicaţii sunt responsabili de scrierea programelor aplicaţie ce conferă funcţionalitatea cerută de utilizatorii finali. Programele pot fi scrise în diferite limbaje de programare (C++, PL/SQL, Java etc.).

Cerinţe minimale care se impun unei baze de date: • asigurarea unei redundanţe minime în date; • furnizarea în timp util a informaţiilor solicitate (timpul de răspuns

la o interogare); • asigurarea unor costuri minime în prelucrarea şi întreţinerea

informaţiei; • capacitatea de a satisface, cu aceleaşi date, necesităţi

informaţionale ale unui număr mare de utilizatori, • posibilitatea de adaptare la cerinţe noi, răspunsuri la interogări

neprevăzute iniţial (flexibilitate); • exploatarea simultană a datelor de către mai mulţi utilizatori

(sincronizare); • asigurarea securităţii datelor prin mecanisme de protecţie împotriva

accesului neautorizat (confidenţialitate);

Page 6: CURS BD Combinat

6

• înglobarea unor facilităţi destinate validării datelor şi recuperării lor în cazul unor deteriorări accidentale, garantarea (atât cât este posibil) că datele din baza de date sunt corecte (integritate);

• posibilitatea de valorificare a eforturilor anterioare şi anticiparea nevoilor viitoare (compatibilitate şi expandabilitate);

• permisivitatea, prin ierarhizarea datelor după criteriul frecvenţei acceselor, a unor reorganizări (eventual dinamice) care sporesc performanţele bazei.

În cadrul unei baze de date putem vorbi de patru niveluri de abstractizare şi de percepţie a datelor: intern, conceptual, logic şi extern. Datele există doar la nivel fizic, iar celelalte trei niveluri reprezintă virtualizări ale acestora.

• Nivelul fizic (intern) este descris de schema fizică a datelor (bit, octet, adresă);

• Nivelul conceptual este descris de schema conceptuală a datelor (articol, înregistrare, zonă) şi reprezintă viziunea programatorilor de sistem asupra datelor;

• Nivelul logic este descris de una din schemele logice posibile ale datelor şi reprezintă viziunea programatorului de aplicaţie asupra datelor;

• Nivelul virtual (extern) reprezintă viziunea utilizatorului final asupra datelor.

Independenţa datelor cuprinde două aspecte fundamentale: o modificare a structurii fizice nu va afecta aplicaţia şi reciproc, modificări ale aplicaţiei vor lăsa nealterată structura fizică de date.

• Independenţa fizică: posibilitatea modificării schemei fizice a datelor fără ca aceasta să implice modificarea schemei conceptuale, a schemei logice şi a programelor de aplicaţie. Este vorba despre imunitatea programelor de aplicaţie faţă de modificările modului în care datele sunt stocate fizic şi accesate.

• Independenţa logică: posibilitatea modificării schemei conceptuale a datelor fără ca aceasta să implice modificarea schemei logice şi a programelor de aplicaţie. Prin independenţa logică a datelor se urmăreşte a se crea fiecărui utilizator iluzia că este singurul beneficiar al unor date pe care, în realitate, le foloseşte în comun cu alţi utilizatori.

Independenţă faţă de strategiile de acces permite programului să precizeze data pe care doreşte să o acceseze, dar nu modul cum accesează această dată. SGBD-ul va stabili drumul optim de acces la date.

Page 7: CURS BD Combinat

7

În limbajele de programare uzuale declaraţiile şi instrucţiunile executabile aparţin aceluiaşi limbaj. În lumea bazelor de date, funcţiile de declarare şi de prelucrare a datelor sunt realizate cu ajutorul unor limbaje diferite, numite limbaje pentru baze de date.

• Limbaje pentru definirea datelor (DDL – Data Description Language). Descrierea concretă a unui DDL este specifică fiecărui sistem de gestiune, dar funcţiile principale sunt aceleaşi. La nivel conceptual, DDL realizează definirea entităţilor şi a atributelor acestora, sunt precizate relaţiile dintre date şi strategiile de acces la ele, sunt stabilite criterii diferenţiate de confidenţialitate şi de validare automată a datelor utilizate.

• Limbaje pentru prelucrarea datelor (DML – Data Manipulation Language). Operaţiile executate în cadrul unei baze de date presupun existenţa unui limbaj specializat, în care comenzile se exprimă prin fraze ce descriu acţiuni asupra bazei. În general, o comandă are următoarea structură: operaţia (calcul aritmetic sau logic, editare, extragere, deschidere-închidere, adăugare, ştergere, căutare, reactualizare etc.), criterii de selecţie, mod de acces (secvenţial, indexat etc.), format de editare. Există limbaje DML procedurale, care specifică cum se obţine rezultatul unei comenzi DML şi limbaje neprocedurale, care descriu doar datele ce vor fi obţinute şi nu modalitatea de obţinere a acestora.

• Limbaje pentru controlul datelor (DCL – Data Control Language). Controlul unei baze de date se referă la asigurarea confidenţialităţii şi integrităţii datelor, la salvarea informaţiei în cazul unor defecţiuni, la obţinerea unor performanţe, la rezolvarea unor probleme de concurenţă.

Limbajele universale nu se utilizează frecvent pentru gestionarea

unei baze de date, dar există această posibilitate. De exemplu, sistemul Oracle este dotat cu precompilatoare (C, Pascal, ADA, Cobol, PL/1, Fortran) care ajută la incorporarea de instrucţiuni SQL sau blocuri PL/SQL în programe scrise în alte limbaje, de nivel înalt, numite limbaje gazdă.

Sistemul de gestiune a bazelor de date interacţionează cu programele de aplicaţie ale utilizatorului şi cu baza de date, oferind o mulţime de facilităţi. Realizarea optimă a acestor facilităţi este asigurată de obiectivele fundamentale ale unui sistem de gestiune. Câteva dintre aceste obiective vor fi enumerate în continuare.

• Independenţa fizică. Obiectivul esenţial este acela de a permite realizarea independenţei structurilor de stocare în raport cu

Page 8: CURS BD Combinat

8 structurile de date din lumea reală. Se defineşte mulţimea de date indiferent de forma acesteia din lumea reală, ţinând seama doar de a realiza un acces simplu la date şi de a obţine anumite performanţe.

• Independenţa logică. Grupul de lucru care exploatează baza de date poate să utilizeze diferite informaţii de bază (nu aceleaşi), pentru a-şi construi entităţi şi relaţii. Fiecare grup de lucru poate să cunoască doar o parte a semanticii datelor, să vadă doar o submulţime a datelor şi numai sub forma în care le doreşte. Această independenţă asigură imunitatea schemelor externe faţă de modificările făcute în schema conceptuală.

• Prelucrarea datelor de către neinformaticieni. Neinformaticienii văd datele independent de implementarea lor şi pot exploata aceste date prin intermediul unui sistem de meniuri oferit de aplicaţia pe care o exploatează.

• Administrarea centralizată a datelor. Administrarea datelor presupune definirea structurii datelor şi a modului de stocare a acestora. Administrarea este în general centralizată şi permite o organizare coerentă şi eficace a informaţiei.

• Coerenţa datelor. Informaţia trebuie să satisfacă constrângeri statice sau dinamice, locale sau generale.

• Neredundanţa datelor. Fiecare aplicaţie posedă datele sale proprii şi aceasta conduce la numeroase dubluri. De asemenea, organizarea nejudicioasă a relaţiilor poate să genereze redundanţă în date. Administrarea coerentă a datelor trebuie să asigure neduplicarea fizică a datelor. Totuşi, nu sunt excluse nici cazurile în care, pentru a realiza performanţe referitoare la timpul de acces la date şi răspuns la solicitările utilizatorilor, să se accepte o anumită redundanţă a datelor.

• Partajabilitatea datelor. Aceasta permite ca aplicaţiile să partajeze datele din baza de date în timp şi simultan. O aplicaţie poate folosi date ca şi cum ar fi singura care le utilizează, fără a şti că altă aplicaţie, concurent, le poate modifica.

• Securitatea şi confidenţialitatea datelor. Datele trebuie protejate de un acces neautorizat sau rău intenţionat. Există mecanisme care permit identificarea şi autentificarea utilizatorilor şi există proceduri de acces autorizat care depind de date şi de utilizator. Sistemul de gestiune trebuie să asigure securitatea fizică şi logică a informaţiei şi să garanteze că numai utilizatorii autorizaţi pot efectua operaţii corecte asupra bazei de date.

Page 9: CURS BD Combinat

9

Sistemele de gestiune a bazelor de date au, din nefericire, şi dezavantaje dintre care se remarcă:

• complexitatea şi dimensiunea sistemelor pot să crească considerabil, datorită necesităţii extinderii funcţionalităţilor sistemului;

• costul, care variază în funcţie de mediu şi funcţionalitatea oferită, la care se adugă cheltuieli periodice de întreţinere;

• costuri adiţionale pentru elemente de hardware; • costul conversiei aplicaţiilor existente, necesară pentru ca acestea

să poată funcţiona în noua configuraţie hardware şi software; • impactul unei defecţiuni asupra aplicaţiilor, bazei de date sau

sistemului de gestiune.

Structura unui sistem de gestiune a bazelor de date este de complexitate variabilă, iar nivelul real de funcţionalitate diferă de la produs la produs. În orice moment apar noi necesităţi, care cer o nouă funcţionalitate, astfel încât aceasta nu va putea deveni niciodată statică. În general, un SGBD trebuie să includă cel puţin cinci clase de module:

• programe de gestiune a bazei de date (PGBD), care realizează accesul fizic la date ca urmare a unei comenzi;

• module pentru tratarea limbajului de definire a datelor, ce permit traducerea unor informaţii (care realizează descrierea datelor, a legăturilor logice dintre acestea şi a constrângerilor la care sunt supuse), în obiecte ce pot fi apoi exploatate în manieră procedurală sau neprocedurală;

• module pentru tratarea limbajului de prelucrare a datelor (interpretativ, compilativ, generare de programe), care permit utilizatorilor inserarea, ştergerea, reactualizarea sau consultarea informaţiei dintr-o bază de date;

• module utilitare, care asigură întreţinerea, prelucrarea, exploatarea corectă şi uşoară a bazei de date;

• module de control, care permit controlul programelor de aplicaţie, asigurarea confidenţialităţii şi integrităţii datelor, rezolvarea unor probleme de concurenţă, recuperarea informaţiei în cazul unor avarii sau defecţiuni hardware sau software etc.

Page 10: CURS BD Combinat

10 Modulele PGBD asigură accesul fizic la date ca urmare a unei

comenzi. Cum lucrează aceste module? • găsesc descrierea datelor implicate în comandă; • identifică datele şi tipul acestora; • identifică informaţii ce permit accesul la structurile fizice de

stocare (fişiere, volume etc.); • verifică dacă datele sunt disponibile; • extrag datele, fac conversiile, plasează datele în spaţiul de memorie

al utilizatorului; • transmit informaţii de control necesare execuţiei comenzii, în

spaţiul de memorie al utilizatorului; • transferă controlul programului de aplicaţie.

Prin urmare, din punct de vedere conceptual: • utilizatorul lansează o cerere de acces; • SGBD-ul acceptă cererea şi o analizează; • SGBD-ul inspectează pe rând, schema internă corespunzatoare

utilizatorului, schema conceptuală, definiţia structurii de stocare şi corespondenţele corespunzătoare;

• SGBD-ul execută operaţiile necesare în baza de date stocată. 1.3. Arhitectura sistemelor de gestiune a bazelor de date Asigurarea independenţei fizice şi logice a datelor impune adoptarea

unei arhitecturi de baze de date organizată pe trei niveluri: • nivelul intern (baza de date fizică); • nivelul conceptual (modelul conceptual, schema conceptuală); • nivelul extern (modelul extern, subschema, vizualizarea).

Nivelul central este nivelul conceptual. Acesta corespunde structurii

canonice a datelor ce caracterizează procesul de modelat, adică structura semantică a datelor fără implementarea pe calculator. Schema conceptuală permite definirea tipurilor de date ce caracterizează proprietăţile elementare ale entităţilor, definirea tipurilor de date compuse care permit regruparea atributelor pentru a descrie entităţile modelului şi legăturile între aceste entităţi, definirea regulilor pe care trebuie să le respecte datele etc.

Nivelul intern corespunde structurii interne de stocare a datelor. Schema internă permite descrierea datelor unei baze sub forma în care sunt

Page 11: CURS BD Combinat

11

stocate în memoria calculatorului. Sunt definite fişierele care conţin aceste date, articolele din fişiere, drumurile de acces la aceste articole etc.

La nivel conceptual sau intern, schemele descriu o bază de date. La nivel extern schemele descriu doar o parte din date care prezintă interes pentru un utilizator sau un grup de utilizatori. Schema externă reprezintă o descriere a unei părţi a bazei de date ce corespunde viziunii unui program sau unui utilizator. Modelul extern folosit este dependent de limbajul utilizat pentru prelucrarea bazei de date. Schema externă permite asigurarea unei securităţi a datelor. Un grup de lucru va accesa doar datele descrise în schema sa externă, iar restul datelor sunt protejate împotriva accesului neautorizat sau rău intenţionat.

Pentru o bază de date particulară există o singură schemă internă, o singură schemă conceptuală, dar există mai multe scheme externe.

În afară de aceste trei niveluri, arhitectura presupune şi anumite corespondenţe dintre acestea:

• corespondenţa conceptual-intern defineşte relaţia dintre nivelul conceptual şi baza de date stocată, specificând modul în care înregistrările şi câmpurile conceptuale sunt reprezentate la nivel intern;

• corespondenţa extern-conceptual defineşte relaţia dintre o anumită vizualizare externă şi nivelul (vizualizarea) conceptual, reprezentând cheia independenţei logice de date;

• corespondenţa extern-extern permite definirea unor vizualizări externe în funcţie de altele, fără a necesita o definiţie explicită a corespondenţei cu nivelul conceptual.

Arhitectura funcţională de referinţă propusă de grupul de lucru ANSI/X3/SPARC este axată pe dicţionarul datelor şi cuprinde două părţi:

• prima, permite descrierea datelor (compoziţia dicţionarului datelor);

• a doua, permite prelucrarea datelor (interogarea şi reactualizarea bazei de date).

În fiecare parte se regăsesc cele trei niveluri: intern, conceptual şi extern. Acestea nu sunt neapărat distincte pentru orice SGBD.

Interfeţele numerotate din figura 1.1, ce descriu arhitectura de referinţă a unui SGBD, corespund următoarelor transformări:

a) Limbaj de descriere a datelor conceptuale, format sursă – permite administratorului întreprinderii să definească schema conceptuală, format sursă.

Page 12: CURS BD Combinat

12 b) Limbaj de descriere a datelor conceptuale, format obiect – se

obţine din compilarea celui precedent şi permite aranjarea schemei obiect în dicţionarul datelor.

c) Limbaj de descriere a datelor conceptuale, format editare – permite administratorilor aplicaţiilor şi a bazelor să consulte schema conceptuală pentru a defini reguli de corespondenţă.

d) Limbaje de descriere a datelor externe, format sursă – permit administratorilor aplicaţiilor să definească scheme externe corespunzând schemei conceptuale. Deoarece sistemele de gestiune pot suporta mai multe modele externe, pot exista mai multe limbaje de descriere a datelor externe.

e) Limbaje de descriere a datelor externe, format obiect – corespund formelor compilate ale celor precedente şi permit aranjarea schemelor externe (obiect) în dicţionarul datelor.

f) Limbaj de descriere a datelor interne, format sursă – permite administratorului bazei de date să definească schema internă şi regulile de corespondenţă cu schema conceptuală.

g) Limbaj de descriere a datelor interne, format obiect – corespunde formei compilate a celui precedent şi permite aranjarea schemei interne (obiect) în dicţionarul datelor.

h) Limbaje de prelucrare a datelor externe, format sursă – permit programatorilor de aplicaţii sau utilizatorilor neinformaticieni să manipuleze date externe (view).

i) Limbaje de prelucrare a datelor externe, format obiect – corespund formelor compilate ale celor precedente.

j) Limbaj de prelucrare a datelor conceptuale, format obiect – produs de procesorul de transformare extern/ conceptual pentru a manipula datele externe.

k) Limbaj de prelucrare a datelor interne, format obiect –produs de procesorul de transformare conceptual/intern pentru a gestiona datele interne.

l) Limbaj de stocare a datelor, format obiect – corespunde interfeţei cu sistemul de stocare a datelor.

m) Interfaţa cu memoria secundară – permite efectuarea de intrări/ieşiri în/din unitatea de memorie secundară.

n) Interfaţa de acces la dicţionarul datelor – permite diverselor procesoare de transformare să acceseze scheme obiect şi reguli de corespondenţă.

Page 13: CURS BD Combinat

13

Procesoarele din figura 1.1 au următoarele funcţii: • procesorul schemei conceptuale compilează schema conceptuală şi

dacă nu sunt erori depune schema compilată în dicţionarul datelor; • procesorul schemei externe compilează schemele externe şi

regulile de corespondenţă externă şi dacă nu sunt erori aranjează schema compilată şi regulile de corespondenţă în dicţionarul datelor;

• procesorul schemei interne are rol similar pentru schema internă; • procesorul de transformare extern/conceptual transformă

manipulările externe în manipulări conceptuale şi invers, datele conceptuale în date externe;

• procesorul de transformare conceptual/intern transformă manipulările conceptuale în manipulări interne şi invers, datele interne în date conceptuale;

• procesorul de transformare intern/stocare transformă manipulările interne în primitive ale sistemului de stocare şi invers, eliberează datele stocate într-un format corespunzător schemei interne.

Page 14: CURS BD Combinat

14

Fig. 1.1. Arhitectura de referinţă a unui SGBD.

Gardarin a propus o arhitectură funcţională apropiată de arhitectura

sistemelor de gestiune actuale care are la bază doar două niveluri: • schema, care corespunde integrării schemelor interne şi

conceptuale; • vizualizarea, care este o schemă externă.

sistem de

alocare

DES

CR

IER

E

administratorul bazei de date

administrator întreprindere

programator aplicaţie utilizatori

procesor schema

conceptuală

procesor schema internă

procesor schema externă

dicţionarul datelor

procesor intern/ alocare

procesor conceptual/

intern

procesor extern/

conceptual

program aplicaţii extern

administratorul aplicaţiilor

PREL

UC

RA

RE

a c c

b

g

f d

e

n

k j

l i

h h m

memorii secundare

Page 15: CURS BD Combinat

15

Sistemul de gestiune gestionează un dicţionar de date care este alimentat prin comenzi de definire a schemei şi prin comenzi de definire a vizualizărilor.

Aceste comenzi, precum şi cererile de prelucrare sunt analizate şi tratate de un procesor numit analizor. Analizorul realizează analiza sintactică şi semantică a cererii şi o traduce în format intern. O cerere în format intern care face referinţă la o vizualizare este tradusă în una sau mai multe cereri care fac referinţă la obiecte ce există în baza de date (modificarea cererilor).

În cadrul acestei arhitecturi există un procesor, numit translator, care realizează modificarea cererilor, asigură controlul drepturilor de acces şi controlul integrităţii în cazul reactualizărilor.

Componenta cheie a sistemului de gestiune este procesorul optimizor care elaborează un plan de acces optim pentru a trata cererea. Acest procesor descompune cererea în operaţii de acces elementare şi alege o ordine de execuţie optimală. De asemenea, evaluează costul planului de acces înaintea execuţiei sale.

Planul de acces ales şi elaborat de optimizor este executat de un procesor numit executor. La acest nivel este gestionat controlul concurenţei.

1.4. Evoluţia bazelor de date Istoria bazelor de date şi a sistemelor de gestiune a bazelor de date

poate fi rezumată în trei generaţii: • sisteme ierarhice şi reţea, • sisteme relaţionale, • sisteme avansate (orientate obiect, relaţionale orientate obiect,

deductive, distribuite, multimedia, multibaze, active, temporale, decizionale, magazii de date etc.).

• Baze de date ierarhice şi reţea Pentru modelele ierarhice şi reţea, datele sunt reprezentate la nivel de

articol prin legături ierarhice (arbore) sau de tip graf. Slaba independenţă fizică a datelor complică administrarea şi prelucrarea acestora. Limbajul de prelucrare a datelor impune programatorului să specifice drumurile de acces la date.

Page 16: CURS BD Combinat

16

Baze de date relaţionale A doua generaţie de SGBD-uri este legată de apariţia modelelor

relaţionale (1970), care tratează entităţile ca nişte relaţii. Piaţa actuală de baze de date este acoperită în majoritate de sisteme relaţionale. Bazele de date relaţionale sunt caracterizate de:

• structuri de date simple, intuitive, • inexistenţa pointerilor vizibili pentru utilizator, • constrângeri de integritate, • operatori aplicaţi relaţiilor care permit definirea, căutarea şi

reactualizarea datelor. Dezvoltarea unei aplicaţii riguroase utilizand o bază de date

relaţionale necesită cunoaşterea a trei niveluri de instrumente, eterogene din punct de vedere conceptual:

• nivelul instrumentelor grafice (interfaţa); • nivelul aplicaţie, cu limbajele sale de dezvoltare; • nivelul SGBD, cu standardul SQL (Structured Query Language) ce

permite definirea, prelucrarea şi controlul bazei de date. Baze de date orientate obiect Bazele de date relaţionale nu folosesc însă obiecte complexe şi

dinamice, nu realizează gestiunea datelor distribuite şi nici gestiunea cunoştinţelor. A treia generaţie de SGBD-uri, sistemele avansate, încearcă să depăşească aceste limite ale sistemului relaţional.

Suportul obiectelor complexe şi dinamice şi prelucrarea acestora este dificilă pentru sistemele relaţionale, deoarece tipul datelor este limitat la câteva domenii alfanumerice, iar structura datelor este simplă. Sistemele relaţionale nu modelează obiecte complexe ca grafuri, liste etc. Un obiect complex poate să fie descompus în relaţii, dar apar dificultăţi atât la descompunerea, cât şi la refacerea acestuia prin compunere. De asemenea, limbajele modelului relaţional permit prelucrarea cu dificultate a obiectelor complexe.

Un sistem relaţional nu suportă obiecte dinamice care incorporează atât partea de date (informaţii) efective, cât şi o parte relativă la tratarea acestora.

Îmbinarea tehnicii limbajelor orientate obiect cu a bazelor de date a permis realizarea bazelor de date orientate obiect. Acestea permit organizarea coerentă a obiectelor partajate între utilizatori concurenţi. Sistemele de gestiune de baze de date orientate obiect (SGBDOO) prezintă o serie de avantaje:

Page 17: CURS BD Combinat

17

• realizează o modelare superioară a informaţiei, • furnizează posibilităţi superioare de deducţie (ierarhie de clase,

moştenire), • permit luarea în considerare a aspectelor dinamice şi integrarea

descrierii structurale şi comportamentale, • asigură îmbunătăţirea interfeţei cu utilizatorul. Cu toate avantajele incontestabile oferite de SGBDOO-uri,

impunerea lor pe piaţa bazelor de date nu a fost uşoară. Câteva motivaţii a acestei situaţii:

• absenţa unei fundamentări teoretice face imposibilă definirea unui SGBDOO de referinţă;

• gestiunea obiectelor complexe este mai dificilă decât accesul la relaţii prin cereri SQL;

• utilizatorii au investit sume uriaşe în sistemele relaţionale şi nu le pot abandona cu uşurinţă. Trecerea la noua tehnologie orientată obiect implică investiţii mari şi nu păstrează aproape nimic din vechile soluţii.

Baze de date relaţionale orientate obiect Simplitatea modelului relaţional, combinată cu puterea tehnologiei

orientate obiect a generat un domeniu nou şi promiţător în lumea bazelor de date, şi anume bazele de date relaţionale orientate obiect.

Construcţia unui sistem de gestiune de baze de date relaţionale orientate obiect (SGBDROO) trebuie să pornească de la cele existente. Aceasta se poate realiza în două moduri: dezvoltând un sistem relaţional prin adăugarea caracteristicilor obiectuale necesare sau pornind de la un sistem orientat obiect şi adăugând caracteristicile relaţionale.

Baze de date deductive O relaţie este o mulţime de înregistrări ce reprezintă fapte.

Cunoştinţele sunt aserţiuni generale şi abstracte asupra faptelor. Cunoştinţele permit să raţionezi, ceea ce permite deducerea de noi fapte, plecând de la fapte cunoscute. Un SGBD relaţional suportă o formă limitată de cunoştinţe, şi anume constrângerile de integritate, iar restul trebuie integrate în programele de aplicaţie. Aceasta generează probleme deoarece cunoştinţele trebuie codificate în programe şi apare imposibilitatea de a partaja cunoştinţe între utilizatori. Totul se complică dacă există un volum mare de fapte.

Page 18: CURS BD Combinat

18 Bazele de date deductive, utilizând programarea logică, gestionează

cunoştinţe relativ la baze de date care, în general, sunt relaţionale. Bazele de date deductive permit deducerea de noi informaţii, plecând de la informaţiile stocate în baza de date. Un SGBD deductiv posedă:

• un limbaj de definire a datelor care permite definirea structurii predicatelor sub formă de relaţii şi constrângeri de integritate asociate;

• un limbaj de prelucrare a datelor care permite efectuarea reactualizărilor asupra datelor şi formularea unor cereri;

• un limbaj de reguli de deducţie care permite ca, plecând cu predicatele definite anterior, să se specifice cum pot fi construite predicate derivate.

Baze de date distribuite Un sistem distribuit este un ansamblu de maşini ce sunt

interconectate printr-o reţea de comunicaţie şi utilizate într-un scop global. Administrarea şi prelucrarea datelor distribuite, situate pe diferite calculatoare şi exploatate de sisteme eterogene este obiectivul fundamental al bazelor de date distribuite.

Bazele de date distribuite sunt sisteme de baze de date cooperante care rezidă pe maşini diferite, în locuri diferite. Această mulţime de baze de date este exploatată de utilizator ca şi cum ar fi o singură bază de date. Programul de aplicaţie care exploatează o bază de date distribuite poate avea acces la date rezidente pe mai multe maşini, fără ca programatorul să cunoască localizarea datelor.

Modelul relaţional a rămas instrumentul principal prin care se realizează prelucrarea datelor distribuite.

Câteva dintre argumentele pentru a justifica această afirmaţie sunt: • bazele relaţionale oferă flexibilitate de descompunere în vederea

distribuirii; • operatorii relaţionali pot fi folosiţi pentru combinaţii dinamice ale

informaţiilor descentralizate; • limbajele sistemelor relaţionale sunt concise şi asigură o economie

considerabilă a transmiterii datelor. Ele fac posibil, pentru un nod oarecare al reţelei, să analizeze intenţia unei tranzacţii, să o descompună rapid în componente ce pot fi realizate local şi componente ce pot fi transportate altor noduri.

Page 19: CURS BD Combinat

19

Calculatoare şi maşini baze de date Soluţia pentru a descentraliza prelucrarea datelor, în scopul evitării

saturării memoriei şi a procesoarelor calculatorului central, a fost apariţia calculatoarelor baze de date şi a maşinilor baze de date. Descentralizarea presupune transferarea unei părţi din funcţiile unui SGBD către un calculator periferic (calculator backend) adică deplasarea algoritmilor de căutare şi a celor de actualizare a datelor mai aproape de memoria secundară. Acest calculator periferic permite utilizarea optimă a resurselor şi realizarea paralelismului în tratarea cererilor de informaţii.

Calculatorul periferic poate fi un calculator clasic, dar cu un software specific de SGBD (calculator bază de date) sau poate fi o maşină cu hardware specializat în gestiunea bazelor de date (maşină bază de date). Maşinile baze de date sunt înzestrate cu arhitecturi paralele special adaptate pentru gestionarea unui volum mare de date. Tratarea paralelă a cererilor permite reducerea timpului total de execuţie a acestora.

O execuţie în paralel solicită, fie descompunerea unui program în module, care pot fi executate în paralel (descompunere funcţională), fie descompunerea datelor în subgrupe, astfel încât toate procesoarele să execute acelaşi lucru, dar pe date diferite. Performanţele tratării paralele depind de modul în care sunt efectuate descompunerile.

Multibaze de date Diferite departamente ale unei organizaţii mai mari pot folosi diferite

sisteme de gestiune. Cu toate că fiecare sistem este dezvoltat pentru a satisface nevoile propriului său departament, informaţiile cu care lucrează pot fi utile şi altor departamente. De aceea, pentru ca organizaţia să funcţioneze bine, trebuie să existe o modalitate globală da a vedea datele din fiecare sistem. Există două caracteristici ale unor astfel de sisteme care fac acceasarea datelor în acest mediu integrat greoaie, uneori chiar imposibilă:

• autonomie – fiecare SGBD are o autonomie completă, ceea ce înseamnă că fiecare manager are control deplin asupra sistemului;

• eterogenitate – sistemele pot opera pe diferite platforme, cu diferite modele de date şi limbajele de interogare.

Una dintre soluţiile folosite pentru a depăşi dificultăţile întâmpinate în respectarea autonomiei şi a eterogenităţii este utilizarea sistemelor multibaze de date.

Page 20: CURS BD Combinat

20 Un sistem multibaze de date (SMB) este alcătuit din mai multe sisteme

de baze de date privite integrat, în care se construiesc una sau mai multe scheme globale pe baza schemelor fiecărei baze de date componente, astfel încât să se poată realiza accesul uniform şi integrat la fiecare din bazele de date componente. Fiecare schemă globală este construită pe baza unui model particular de date. De exemplu, se poate construi o schemă globală ce are la bază modelul relaţional pentru utilizatorii care sunt familiarizaţi cu acest model, dar se poate construi o schemă globală bazată pe modelul orientat obiect pentru utilizatorii bazelor de date orientate obiect.

Pentru o schemă globală dată, un sistem multibaze de date constă din sistemele componente împreună cu un sistem front-end, care suportă un singur model de date şi un singur limbaj de interogare. Principalele sarcini ale sistemului front-end sunt gestionarea schemei globale şi procesarea cererilor globale.

Un avantaj major al acestui model, faţă de altele, este faptul că o singură interogare poate accesa date din mai multe baze de date într-un mod integrat, fără să afecteze nici o aplicaţie care este scrisă utilizând una dintre bazele de date componente.

Baze de date cu suport decizional Sistemele informatice, în particular bazele de date, au ajuns la

maturitate. Marile companii au acumulat o mare cantitate de informaţii din domeniul lor de activitate, pe care le păstrează în tabele istorice şi sunt nefolositoare sistemelor operaţionale ale companiei, care funcţionează cu date curente. Analizate, aceste date ar putea oferi informaţii despre tendinţe şi evoluţii care ar putea interesa compania. Pentru a putea analiza aceste mari cantităţi de date este nevoie de tehnologii şi instrumente speciale.

Ideea de a analiza colecţii de date provenind din sistemele operaţionale ale companiei sau din surse externe pentru a le folosi ca suport în procesul de decizie nu aparţine ultimului deceniu, dar baze de date care să funcţioneze eficient după aceste criterii au fost studiate şi implementate în ultimii ani. Principalul scop al acestor baze de date a fost de a întâmpina nevoile sistemelor operaţionale, a căror natură este inerent tranzacţională.

Sistemele tranzacţionale sunt interesate, în primul rând, să controleze la un moment dat o singură tranzacţie. De exemplu, într-un sistem bancar, atunci când clientul face un depozit, sistemul operaţional bancar este responsabil de a înregistra tranzacţia într-un tabel al tranzacţiilor şi de a creşte nivelul curent al contului clientului, stocat în alt tabel.

Page 21: CURS BD Combinat

21

Un sistem operaţional tipic operează cu evenimente predefinite şi, datorită naturii lor, necesită acces rapid la date. Uzual, fiecare tranzacţie operează cu cantităţi mici de date.

De-a lungul timpului, nevoile sistemelor operaţionale nu se schimbă mult. Aplicaţia care înregistrează tranzacţia, ca şi cea care controlează accesul utilizatorului la informaţie (partea de raportare a sistemului bancar), nu se modifică prea mult. În acest tip de sistem, informaţia necesară în momentul în care un client iniţiază o tranzacţie trebuie sa fie actuală. Înainte ca o bancă să aprobe un împrumut este nevoie să se asigure de situaţia financiară stabilă a clientului în acel moment, şi nu cu un an înainte.

În ultimii ani s-au pus la punct principii şi tehnologii noi care să servească procesului de analiză şi administrare a datelor. O bază de date optimizată în acest scop defineşte o Data Warehouse (magazie de date), iar principiul pe care îl urmează este cunoscut sub numele de procesare analitică (OLAP – On Line Analytical Processing). Spre deosebire de acesta, principiul pe care se bazează sistemele tranzacţionale a fost numit procesare tranzacţională (OLTP – On Line Transactional Processing).

Aplicaţiile unei Data Warehouse trebuie să ofere răspunsuri unor întrebări de tipul: „Care zi din săptămână este cea mai aglomerată?“ „Ce clienţi, cu care avem relaţii intense, nu au beneficiat de reduceri de preţuri?“. O caracteristică a bazelor de date analitice este că interogările la care acestea trebuie să răspundă sunt ad-hoc, nu sunt predefinite, iar baza de date trebuie optimizată astfel încât să fie capabilă să răspundă la orice fel de întrebare care poate implica mai multe tabele.

În această abordare, organele generale de decizie necesită accesul la toate datele organizaţiei, oriunde s-ar afla acestea. Pentru o analiză corespunzătoare a organizaţiei, afacerilor, cerinţelor, tendinţelor este necesară nu numai accesarea valorilor curente din baza de date, ci şi a datelor istorice. Prin urmare, pentru a facilita acest tip specific de analiză a informaţiei a fost creată magazia de date, care conţine informaţii extrase din diverse surse, întreţinute de diverse unităţi operative, împreună cu istoricul şi rezumatul tranzacţiilor.

Sursele de date pentru o magazie cuprind: • date operaţionale, păstrate în baze de date ierarhice, de prima

generaţie; • date departamentale, păstrate în sisteme de fişiere patentate;

Page 22: CURS BD Combinat

22

• date cu caracter personal, păstrate pe staţii de lucru şi servere personale;

• sisteme externe (baze de date comerciale, Internet etc.) Data warehouse este o colecţie de date: • orientate spre subiect (principalele subiecte ale modelului sunt

clienţii, produsele, vânzările, în loc de domeniile de activitate), • nevolatile (datele nu sunt reactualizate, înlocuite în timp real, ci

sunt adăugate ca un supliment al bazei), • integrate (transpunerea datelor provenite din diverse surse de

informaţii se face într-un format consistent), • variabile în timp (concentrarea depozitului de date se face asupra

schimbărilor care au loc în timp).

Fig 1.2. Arhitectura unui depozit de date Înmagazinarea datelor se concentrează asupra gestionării a cinci

fluxuri de informaţii:

Sursa 1 Date operationale

FLUX INTERN

Sursa n Date operationale

Administrator incarcare date

Administrator cereri

Administrator Depozit de date

Administrator Depozit de date

SGBD Date detaliate

Date cu nivel mare de agregare

Metadate

Date cu nivel mic de agregare

Arhive/ date backup

Utilitare Data mining

Utilitare cereri,

rapoarte

Utilitare pentru accesul

utilizatorilor finali

Utilitare OLAP

META-FLUX

FLUX ASCENDENT

FLUX EXTERN

FLUX DESCENDENT

Page 23: CURS BD Combinat

23

• fluxul intern, care reprezintă procesele asociate extragerii şi încărcării datelor din fişierele sursă în magazia de date;

• fluxul ascendent, care reprezintă procesele asociate adăugării de valoare datelor din magazie, cu ajutorul împachetării şi distribuirii;

• fluxul descendent, care reprezintă procesele asociate arhivării, salvării, refacerii datelor din magazie;

• fluxul extern, care reprezintă procesele asociate punerii la dispoziţie a datelor pentru utilizatorii finali;

• meta-fluxul, care reprezintă procesele asociate gestionării meta-datelor (date despre date).

În arhitectura depozitului de date intervin câteva componente specifice acestei structuri.

• Administratorul pentru încărcarea datelor (componenta front-end) realizează toate operaţiile asociate cu obţinerea (extragerea) şi încărcarea datelor operaţionale într-un depozit de date.

• Administratorul depozitului de date realizează toate operaţiile legate de administrarea datelor din depozit. Operaţiile realizate de componenta de administrare a depozitului de date includ: analiza datelor pentru a asigura consistenţa acestora; transformarea şi mutarea datelor sursă din structurile temporare de stocare în tabelele depozitului de date; crearea de indecşi şi vizualizări asupra tabelelor de bază; generarea denormalizării (dacă este necesar); generarea agregărilor; crearea arhivelor şi a backup-urilor.

• Administratorul cererilor (componenta back-end) realizează toate operaţiile legate de administrarea cererilor utilizator. Această componentă este construită folosind utilitarele de acces la date disponibile utilizatorilor finali, utilitarele de monitorizare a depozitului de date, facilităţile oferite de sistemul de baze de date şi programele personalizate.

• În zona ce include date agregate sunt stocate toate agregările predefinite de date, pe diferite niveluri. Scopul, menţinerii acestora, este de a mări performanţa cererilor care necesită agregări. Datele agregate sunt actualizate permanent, pe măsură ce sunt încărcate noi informaţii în depozit.

• Scopul principal al depozitelor de date este de a oferi informaţii necesare utilizatorilor pentru luarea deciziilor strategice de marketing. Aceşti utilizatori interacţionează cu depozitul de date prin diferite utilitare de acces (utilitare pentru rapoarte şi cereri,

Page 24: CURS BD Combinat

24 utilitare pentru dezvoltarea aplicaţiilor, utilitare pentru procesarea analitică on-line (OLAP), utilitare data mining) etc.

Instrumentele de acces pentru utilizatorii finali ai magaziilor de date: • prelucrarea analitică on-line; • extensiile limbajului SQL; • instrumentele de extragere a datelor.

Prelucrarea analitică on-line (OLAP) reprezintă sinteza, analiza şi consolidarea dinamică a unor volume mari de date multidimensionale. Serverele de baze de date OLAP utilizează structuri multidimensionale pentru stocarea datelor şi a relaţiilor dintre date. Aceste structuri pot fi vizualizate prin cuburi de date şi cuburi în cadrul cuburilor etc. Fiecare latură a cubului reprezintă o dimensiune. Serverele de baze de date OLAP multidimensionale acceptă operaţiile analitice uzuale: consolidarea (gruparea), parcurgerea în jos (inversul consolidării), tranşarea, tăierea. OLAP necesită o modalitate de agregare a datelor conform mai multor grupări diferite, în număr foarte mare, iar utilizatorii trebuie să le aibă în vedere pe toate.

Instrumentele OLAP presupun organizarea informaţiei într-un model multidimensional care este susţinut de o bază de date:

• multidimensională (MOLAP), în care datele sunt stocate conceptual în celulele unui tablou multidimensional;

• relaţională (ROLAP), proiectată pentru a permite interogări multidimensionale.

În acest context, a devenit o necesitate extinderea limbajului SQL prin operaţii puternice, necesare pentru rezolvarea noului tip de abordare. Au fost introduse noi funcţii numerice (limita inferioară, limita superioară etc.), noi funcţii statistice (distribuţie, distribuţie inversă, corelaţie etc.), noi operatori de agregare, extensii ale clauzei GROUP BY etc.

De exemplu, RISQL (Red Brick Intelligent SQL), proiectat pentru analiştii din domeniul afacerilor, permite: ordonare după rang (pe diferite niveluri - de exemplu, gruparea filialelor în trei categorii pe baza venitului generat în anul precedent), partajarea pieţei, compararea anului curent cu cel precedent etc.

O altă problemă esenţială este extragerea datelor şi utilizarea acestora pentru luarea de decizii cruciale în domeniul afacerilor. Descoperirea unor noi corelaţii, tipare, tendinţe, prin extragerea unor cantităţi mari de date folosind strategia inteligenţei artificiale este una din modalităţile de rezolvare.

Extragerea datelor presupune capacitatea de a construi modele mai degrabă previzibile, decât retrospective. Modelarea predictivă utilizează

Page 25: CURS BD Combinat

25

informaţii pentru a forma un model al caracteristicilor importante ale unui fenomen.

Tehnicile asociate operaţiilor fundamentale de extragere sunt: • modelarea predictivă (clasificarea cu ajutorul unei reţele neurale

sau al unei inducţii de tip arbore şi previziunea valorilor, utilizând tehnici de regresie);

• segmentarea bazei de date (comasarea demografică şi comasarea neurală care se deosebesc prin metodele uilizate pentru a calcula distanţa dintre înregistrări, prin intrările de date permise);

• analiza legăturilor (descoperirea asocierilor, descoperirea tiparelor, descoperirea secvenţelor de timp similare);

• detectarea deviaţiilor (statistici şi vizualizări pentru identificarea împrăştierii datelor, utilizând tehnici moderne de vizualizare grafică). În această clasă pot fi considerate, de exemplu, detectarea fraudelor privind utilizarea cărţilor de credit, pretenţiile de despăgubire ale asiguraţilor etc.

În concluzie, spre deosebire de un sistem OLTP, Data Warehouse este o bază de date a cărei structură este proiectată pentru a facilita analiza datelor. Un sistem de suport decizional urmăreşte, în primul rând, obţinerea de informaţii din baza de date, în timp ce unul OLTP urmăreşte introducerea de informaţii în baza de date. Datorită acestor diferenţe, structura optimă a unei Data Warehouse este radical diferită de cea a unui sistem OLTP.

Depozitele de date şi sistemele OLTP sunt supuse unor cerinţe diferite, dintre care cele mai semnificative se referă la operaţii, actualizarea datelor, proiectare, operaţii tipice şi date istorice.

• Operaţii. Depozitele sunt create pentru a permite interogări ad hoc. Ele trebuie să fie suficient de flexibile pentru a putea răspunde interogărilor spontane ale utilizatorilor. Sistemele OLTP suportă numai operaţii predefinite. Aplicaţiile pot fi optimizate sau create special numai pentru acele operaţii.

• Actualizarea datelor. Utilizatorii finali ai unui depozit de date nu fac în mod direct actualizări ale depozitului. În sistemele OLTP, utilizatorii realizează, de obicei, în mod individual procedurile de modificare a bazei de date. În acest fel, baza de date OLTP este întotdeauna la zi şi reflectă starea curentă a fiecărei tranzacţii.

• Proiectare. Depozitele de date folosesc, în mod uzual, scheme denormalizate, în timp ce sistemele OLTP folosesc scheme normalizate pentru a optimiza performanţele operaţiilor.

Page 26: CURS BD Combinat

26

• Operaţii tipice. O simplă interogare a depozitului de date poate scana mii sau chiar milioane de înregistrări (de exemplu, cererea „Care sunt vânzările totale către toţi clienţii din luna trecută?“), în timp ce o operaţie tipică OLTP accesează doar o parte mai mică din înregistrări.

• Date istorice. Depozitele de date stochează datele pe o perioadă lungă de timp, luni sau ani. Acest lucru oferă suport pentru analiza istorică a informaţiei. Sistemele OLTP reţin date istorice atât timp cât este necesar pentru a îndeplini cu succes cerinţele tranzacţiilor curente.

Sistemele OLTP Data Warehouse

Păstrează date curente Păstrează date istorice

Stochează date detaliate Stochează date detaliate, agregate uşor sau puternic

Datele sunt dinamice Datele sunt în mare măsură statice

Prelucrare repetitivă Prelucrare ad-hoc, nestructurată şi euristică

Nivel înalt de transfer al tranzacţiilor

Nivel mediu sau scăzut de transfer al tranzacţiilor

Tipar de utilizare previzibil Tipar de utilizare imprevizibil Conduse prin tranzacţii Conduse prin analiză Susţin deciziile de zi cu zi Susţin deciziile strategice Deservesc un număr mare de utilizatori

Deservesc un număr relativ redus de utilizatori din administraţie

Orientate spre aplicaţii Orientate spre subiect Fig. 1.3. OLTP versus Data Warehouse O bază de date OLAP poate fi relaţională, dar datorită naturii ei

orientate spre dimensiuni, au fost dezvoltate pentru gestionarea acestor baze de date construcţii multidimensionale, mai potrivite pentru o raportare flexibilă. Spre deosebire de bazele de date relaţionale, structura unei baze de date multidimensionale nu implică tabele, linii şi coloane, ci obiecte de următoarele tipuri: variabile, dimensiuni, niveluri, ierarhii, atribute.

Data Warehouse, care cuprinde de obicei informaţii despre o întreagă companie, poate fi subîmpărţită în baze de date departamentale, numite rafturi de date (Data Marts). De exemplu, poate exista un Data

Page 27: CURS BD Combinat

27

Mart al departamentului financiar, un altul al departamentului vânzări şi un altul pentru departamentul marketing.

Construcţia unei astfel de baze de date poate fi abordată în două moduri.

• O primă abordare este de a construi mai întâi un schelet al bazei de date la care se lipesc ulterior rafturile de date. Aceasta necesită o analiză prealabilă a întregului şi o delimitare a blocurilor componente. Ea cere un timp mai lung de dezvoltare, dar rezultatul este o bază de date unitară.

• A doua metodă este de a construi mai întâi rafturi specifice, efortul constând, în acest caz, în asocierea acestora. Această soluţie oferă mai rapid, aplicaţii funcţionale utilizatorilor, dar au de suferit unitatea şi portabilitatea aplicaţiilor finale.

Utilizatorii trebuie să-şi schimbe optica asupra bazelor de date pentru a fi capabili să folosească puterea şi flexibilitatea instrumentelor analitice de care dispun. Instrumentele OLAP au evoluat ca o modalitate de a rezolva interogările complicate necesare procesului de analiză a datelor. Combinaţia între bazele de date multidimensionale şi instrumentele analitice prietenoase face uşoară analiza, sinteza şi consolidarea datelor.

În ultimii ani, marii producători de sisteme de gestiune a bazelor de date relaţionale, precum Oracle, au introdus în produsele lor construcţii care să faciliteze accesul la datele din sistemele fundamentale pentru luarea de decizii. Astfel, noile versiuni de SGBD-uri ale firmelor mari prevăd o modalitate mai inteligentă de a realiza operaţia de compunere între două sau mai multe tabele, metode de indexare noi, potrivite pentru marile cantităţi de date statice cu care operează sistemele Data Warehouse, capacitatea de a detecta şi optimiza interogări de un tip special, posibilitatea de a folosi mai multe procesoare pentru a rezolva o interogare.

Un sistem Data Warehouse are un efect fundamental asupra utilizatorilor. Ei pot manevra mult mai flexibil sistemul, au posibilităţi elevate pentru interogarea datelor, dar ei trebuie să ştie cum să prelucreze şi să vizualizeze datele şi cum să le folosească în procesul de decizie.

Un efort ce trebuie făcut pentru construirea unui sistem de suport pentru decizii (DSS – Decision Support System) constă în procesul de descoperire a informaţiilor utile din baza de date. Acest proces, numit Data Mining sau Knowledge Discovery in Databases (KDD), procesează mari cantităţi de date, a căror corelare nu este neapărat evidentă, în vederea descoperirii de tendinţe şi tipare.

Page 28: CURS BD Combinat

28

1.5. Arhitecturi multi-user pentru sisteme de gestiune a bazelor de date

Arhitecturile uzuale care sunt utilizate pentru implementarea

sistemelor de gestiune a bazelor de date multi-user sunt: teleprocesarea, arhitectura fişier-server arhitectura client-server.

Teleprocesarea este arhitectura tradiţională, ce cuprinde un calculator cu o singură unitate CPU şi un numar de terminale care sunt incapabile să funcţioneze singure. Terminalele trimit mesaje la programele aplicaţie ale utilizatorilor, care la rândul lor, utilizează serviciile SGBD.

Această arhitectură a plasat o greutate teribilă asupra calculatorului central, care pe lângă rularea programelor de aplicaţii şi ale SGBD-ului, mai trebuie să preia şi din munca terminalelor (de exemplu, formatarea datelor pentru afişarea pe ecran).

Arhitectura fişier-server, presupune deja că procesarea este distribuită în reţea (de obicei o reţea locală LAN). Arhitectura cuprinde fişierele cerute de aplicaţii şi SGBD-ul. Aplicaţiile şi funcţiile SGBD sunt executate pe fiecare staţie de lucru, solicitând când este nevoie fişiere de pe server-ul de fişiere. Dintre dezavantaje se remarcă:

• existenţa unui trafic intens pe reţea; • necesitatea unei copii complete a SGBD-ului pe fiecare

staţie de lucru; • acelaşi fişier poate fi accesat de mai multe SGBD-uri,

ceea ce implică un control complex al integrităţii, simultaneităţii, reconstituirii.

Arhitectura client-server se referă la modul în care interacţionează componentele software pentru a forma un sistem. Există un proces client, care necesită resurse şi un proces server, care oferă resurse.

În arhitectura client-server, clientul (front end) emite, prin intermediul reţelei locale, o cerere SQL care este executată pe server (back-end); acesta trimite ca răspuns ansamblul înregistrărilor rezultat. Într-o astfel de interacţiune maşinile sunt eterogene, iar protocoalele de reţea pot fi distincte.

În contextul bazelor de date, client-ul: • administrează interfaţa cu utilizatorul şi logica aplicaţiei; • acceptă şi verifică sintaxa intrărilor utilizatorilor; • procesează aplicaţiile; • generează cerinţele pentru baza de date şi le trimite server-ului;

Page 29: CURS BD Combinat

29

• transmite răspunsul înapoi la utilizator. În contextul bazelor de date, server-ul: • primeşte şi procesează cerinţele clienţilor pentru baza de date; • verifică autorizarea; • garantează respectarea constrângerilor de integritate; • efectuează procesarea interogare-reactualizare şi trimite clientului

răspunsul; • realizează optimizarea interogărilor; • asigură controlul concurenţei dintre mai multi clienţi care se ignoră

(mecanisme de blocare); • intreţine dictionarul datelor; • oferă acces simultan la baza de date; • asigură robusteţea în cazul defecţiunilor; • oferă controlul reconstituirii etc. Arhitectura tradiţională client-server pe „două etaje (straturi)“

presupune: • client-ul – responsabil, în primul rand, de prezentarea datelor către

client; • server-ul – responsabil, în primul rand, de furnizarea serviciilor

către client. Arhitectura client-server pe „trei etaje“ presupune trei straturi,

fiecare fiind rulat, potenţial, pe o platformă diferită. • stratul (client) format din interfaţa cu utilizatorul, care este rulat pe

calculatorul utilizatorului final; • stratul (server de aplicaţie), ce manevrează logica aplicaţiilor şi

prelucrării datelor, şi care poate servi mai mulţi clienţi (conectare la celelalte două straturi se face prin reţele locale LAN sau de mare suprafaţă WAN);

• stratul (server-ul de baze de date), care se ocupă cu validarea datelor şi accesarea bazei de date (stochează date necesare stratului din mijloc).

Arhitectura se potriveşte natural mediului Web. Un browser Web acţionând drept client şi un server Web fiind server de aplicaţie.

Middleware este un strat, evident software, între aplicaţia postului client şi server-ul de baze de date, constituit dintr-o interfaţă de programare a aplicaţiilor (API - Application Programming Interface) şi un protocol de reţea.

Page 30: CURS BD Combinat

30 API descrie tipul de interacţiune dintre o aplicaţie client şi un server

la distanţă, via un protocol de comunicaţie şi de formatare a datelor. Scopul existenţei interfeţei de programare a aplicaţiilor este de a oferi o interfaţă unică mai multor server-e de baze de date.

Este convenabil ca sistemele de baze de date să fie considerate ca fiind formate dintr-un server (sistemul SGBD însăşi) şi un set de clienţi (aplicaţiile). Frecvent, clienţii şi server-ul pot fi rulate pe calculatoare diferite, realizându-se un tip simplu de procesare distribuită. În general, fiecare server poate deservi mai multi clienţi, iar fiecare client poate accesa mai multe server-e. Dacă sistemul oferă transparenţă totală (fiecare client se poate comporta ca şi cum ar comunica cu un singur server, de pe un singur calculator) atunci este vorba despre un sistem de baze de date distribuite.

1.6. Tehnologia Web şi sistemele SGBD Internet = o colecţie mondială de reţele de calculatoare. Intranet = un sit Web sau un grup de sit-uri care aparţin unei

organizaţii, accesibil numai pentru membrii acesteia. Extranet = o reţea intranet care este parţial accesibilă utilizatorilor

externi autorizaţi. Reţea Web (World Wide Web) = un sistem bazat pe hipermedii care

pune la dispoziţie un mijloc simplu, de tip „indicare-clic“ de răsfoire a informaţiilor pe Internet, folosind hiperlegăturile.

HTTP = protocolul utilizat pentru a transfera pagini Web prin intermediul Internetului.

HTML = limbajul de formatare a documentelor utilizat în proiectarea majorităţii paginilor Web.

Adresa URL = şir de caractere alfanumerice care reprezintă adresa unei resurse pe Internet şi modul în care trebuie accesată resursa.

Interfaţa de poartă comună (CGI) = defineşte modul în care scripturile comunică cu server-ul Web. Este tehnica de bază de integrare a bazelor de date în reţeaua Web.

În mediul Web funcţionează modelul three tier format din: • un strat de interfaţă cu utilizatorul (client), • un strat de logică a afacerii şi prelucrare a datelor (server de

aplicaţii), • un sistem SGBD (server de baze de date) distribuit pe calculatoare

diferite. Avantajele reţelei Web ca platformă de baze de date:

• avantagele SGBD;

Page 31: CURS BD Combinat

31

• simplitate; • independenţa de platformă; • interfaţa grafică cu utilizatorul; • acces transparent în reţea; • standardizare (HTML standard de facto).

Arhitectura de calcul în reţea a sistemului Oracle (NCA Network Computing Architecture) se axează în principal pe furnizarea extensibilităţii pentru mediile distribuite. Arhitectura este construită pe baza tehnologiei CORBA pentru manipularea obiectelor. Este o structură three tier care se bazează pe utilizarea de:

• cartuşe de software care permit utilizatorilor să adauge funcţionalităţi individuale în aplicaţii (cartuşele pot fi construite în Java, C/C++, Visual Basic, SQL şi pot fi conectate la oricare din cele 3 straturi);

• protocoale deschise şi interfeţe standardizate care permit comunicarea între cartuşe (distribuite într-o reţea) prin intermediul unui program magistrală (ICX);

• clienţi extensibili, server-e de aplicaţie, server-e de baze de date;

• dezvoltarea şi administrarea integrată a cartuşelor. Un cartus utilizeaza un limbaj de definire a interfetelor (IDL)

pentru a putea fi identificat de alte obiecte intr-un sistem distribuit. De exemplu, PL/SQL este un astfel de cartus.

Arhitectura multitier a sistemului Oracle9i Arhitectura cu mai multe niveluri (multitier) conţine următoarele

elemente: • unul sau mai mulţi client-i care iniţiază operaţii; • unul sau mai multe server-e de aplicaţii care execută părţi ale

operaţiilor; • un server de baze de date care stochează datele folosite de operaţii. Client-ul, care poate fi un browser Web sau un proces user, iniţiază o

cerere pentru a executa o operaţie referitoare la informaţiile stocate în baza de date. Conectarea la server-ul bazei de date se face printr-unul sau mai multe server-e de aplicaţii.

Server-ul de aplicaţii constituie interfaţa dintre client-i şi server-ul bazei de date, asigurând accesul la informaţii. De asemenea, el include un nivel adiţional pentru securitate. Server-ul de aplicaţii îşi asumă identitatea client-ului, atunci când execută, pe server-ul de baze de date, operaţiile solicitate de acesta.

Arhitectura multitier permite folosirea unui server de aplicaţii pentru

Page 32: CURS BD Combinat

32 acreditarea client-ului, conectarea la server-ul de baze de date şi execuţia operaţiilor iniţiate de client. Privilegiile server-ului de aplicaţii sunt limitate pentru a preveni execuţia operaţiilor nedorite sau inutile în timpul unei operaţii client.

Server-ul de baze de date pune la dispoziţia server-ului de aplicaţii informaţiile necesare pentru soluţionarea operaţiilor lansate de către client. De asemenea, acesta face distincţia între operaţiile pe care server-ul de aplicaţii le cere în favoarea client-ului şi cele pe care le solicită în nume propriu.

Fig. 1.4. Arhitectura three-tier a sistemului Oracle9i

Clienti HTTP

Nivel 1

Oracle9i Application Server

Nivel 2

Oracle9i Database

Nivel 3

Oracle9i Developer Suite

HTTP

Page 33: CURS BD Combinat

Proiectarea bazelor de da te orientate ob iect MODEL AREA BAZELO R D E DAT E

2.1. Preliminarii Un model este o reprezentare a obiectelor şi evenimentelor lumii reale şi

a asocierilor dintre ele. De fapt, el reprezintă o abstracţie asupra aspectelor semnificative ale unei „întreprinderi“, ale unui sistem real, ignorând proprietăţile accidentale. Modelul este cel pe care utilizatorii trebuie să-l cunoască; implementarea unui model este cea pe care utilizatorii nu este necesar să o cunoască. Diferenţa dintre model şi implementare este, de fapt, un caz special şi important al deosebirii uzuale dintre logic şi fizic.

Modelele se impun prin sintaxa şi prin semantica lor şi, din acest punct de vedere, există trei tipuri fundamentale de modele:

• modele care descriu aspectele statice ale procesului modelat; • modele care descriu aspectele dinamice ale procesului modelat; • modele care descriu aspectele funcţionale ale procesului modelat. Un model de date reprezintă o colecţie integrată de concepte necesare

descrierii: • datelor, • relaţiilor dintre ele, • constrângerilor existente asupra datelor sistemului real analizat. Modelarea unei baze de date permite trecerea de la percepţia unor fapte

din lumea reală la reprezentarea lor prin date. Modelul de date trebuie să reflecte fidel fenomene ale lumii reale, să urmărească evoluţia acestei lumi şi comunicarea dintre fenomenele lumii reale.

Modelul trebuie să asigure conceptele de bază care permit proiectantului bazei de date şi utilizatorilor să comunice, fără ambiguităţi, cunoştinţele lor privind funcţionarea şi organizarea modelului real analizat. Prin urmare, un model de date trebuie să reprezinte datele şi să le facă înţelese.

În esenţă, modelul de date are trei componente: • o mulţime de reguli conform cărora sunt construite bazele de date

(partea structurală); • o mulţime de operaţii permise asupra datelor, care sunt utilizate pentru

reactualizarea sau regăsirea datelor (partea de prelucrare); • o mulţime de reguli de integritate, care asigură coerenţa datelor. Abordarea generală a problemei modelării semantice a datelor se face în

patru etape.

2 MODELAREA ENTITATE - RELAŢIE

Page 34: CURS BD Combinat

58 PROIECTAREA BAZELOR DE DATE

• Se identifică o mulţime de concepte semantice care sunt utile în descrierea lumii reale. Se presupune că lumea reală (modelul real analizat) este formată din entităţi care au anumite proprietăţi, că fiecare entitate are o identitate, că există legături, corelaţii între entităţi. Conceptul de corelaţie, ca şi cel de entitate, este util, în mod intuitiv, la descrierea modelului.

• Se caută o mulţime de obiecte formale, simbolice care sunt utilizate pentru reprezentarea conceptelor semantice anterioare.

• Se dau reguli de integritate formale şi generale (constrângeri) care să reflecte restricţiile la care este supus modelul.

• Se defineşte o mulţime de operatori formali prin care pot fi prelucrate şi analizate obiectele formale.

2.2. Modelul entitate-relaţie Una dintre cele mai cunoscute abordări ale modelării semantice (cu

siguranţă una dintre cele mai utilizate) este cea bazată pe modelul entitate-relaţie (E/R). Acesta a fost introdus de către Peter.P. Chen în 1976 şi rafinat de atunci în diverse moduri de către acesta şi de mulţi alţi cercetători, ca un model de date conceptual, pentru a uşura proiectarea bazelor de date. Pentru reprezentarea grafică a modelului sunt utilizate diagramele E/R, care sunt modele neformalizate pentru reprezentarea unui model, unui sistem din lumea reală.

Diagramele E/R constituie o tehnică de reprezentare a structurii logice a bazei de date, într-o manieră grafică. Aceste diagrame oferă un mijloc simplu şi inteligibil de comunicare a caracteristicilor importante ale designului unei anumite baze de date.

Diagrama E/R este un model de date conceptual de nivel înalt, independent de platforma hardware utilizată şi de tipul SGBD-ului. Modelul este constituit din concepte care descriu structura bazei de date şi tranzacţiile de regăsire sau reactualzare asociate.

Popularitatea modelului E/R ca modalitate de abordare a proiectării bazelor de date poate fi atribuită în principal tehnicii de realizare a diagramelor E/R. Această tehnică, ca şi modelul E/R însuşi, a evoluat de-a lungul timpului datorită noilor problematici care au apărut în proiectarea bazelor de date.

Baza de date poate fi definită ca o mulţime de date ce modelează un

sistem real. Acest sistem este format din obiecte legate între ele. Modelul E/R împarte elementele unui sistem real în două categorii: entităţi şi relaţii (legături, asocieri) între aceste entităţi. Entităţiile şi legăturile au anumite caracteristici, numite atribute. Nu trebuie confundat conceptul de relaţie, în sensul de asociere, care intervine în definirea diagramei E/R cu conceptul de relaţie care este specific modelului relaţional.

Page 35: CURS BD Combinat

Modelarea entitate-relaţie 59

Studiu de caz Exemplele din acest capitol se referă la proiectarea unui model de date ce

furnizează informaţii despre prezentări de modă, evenimente care reprezintă momente importante în lumea caselor de modă.

Vom prezenta modelul de date, restricţiile pe care trebuie să le respecte şi vom încerca, într-o manieră didactică, să construim diagrama E/R corespunzătoare. Vom considera, în abordarea iniţială, anumite situaţii care nu sunt optime, în sensul că pot genera redundanţă, anomalii la reactualizări sau nu permit rezolvarea anumitor interogări asupra modelului. Vom încerca să arătăm care sunt deficienţele modelului, situaţiile care le-au generat şi cum pot fi corectate (parţial sau total) anomaliile respective.

Modelul de date va gestiona informaţii legate de organizarea şi funcţionarea prezentărilor de modă. Există firme organizatoare care se ocupă de buna desfăşurare a acestor prezentări. O firmă organizatoare poate fi contactată prin angajaţi specializaţi pe diferite domenii (financiar, social, publicitate, securitate, sisteme de iluminare, coregrafie, sisteme de sonorizare, cazare, primiri/plecări aeroport etc.).

Firme specializate sunt angajate pentru soluţionarea problemelor legate de securitate, publicitate, asigurări, iar restul problemelor sunt rezolvate cu salariaţii proprii ai caselor de modă şi a firmei organizatoare. Modalităţile de securitate, asigurări, publicitate proprii caselor de modă, modelelor sau agenţiilor de modele nu intră în proiectarea modelului.

Prezentările pot fi sponsorizate, considerându-se doar informaţiile referitoare la persoane (fizice sau juridice) care au contribuit efectiv la finanţarea prezentărilor de modă. Mai exact, nu sunt incluşi sponsorii posibili.

La aceste evenimente participă case de modă, care prezintă vestimentaţii concepute de creatorii casei respective. Creatorii pot fi cei care concep vestimentaţia (designeri) sau cei care o realizează efectiv, incluzând croitori, lucrători care se ocupă cu broderia sau cu realizarea diverselor accesorii.

În cadrul prezentării de modă, vestimentaţiile sunt purtate de manechine care aparţin anumitor agenţii de modele. Casele de modă angajează modele care să le prezinte vestimentaţiile cu prilejul acestor evenimente. Modelul de date prezintă şi un istoric al activităţii manechinelor (în cadrul diverselor agenţii).

Casele de modă angajează pentru o prezentare stilişti care se ocupă cu machiajul şi coafura modelelor.

De asemenea, modelul analizează informaţii legate de localizarea şi accesarea firmelor de publicitate, a persoanelor de contact din firmele organizatoare, a caselor de modă, a agenţiilor şi a modelelor, a sponsorilor, a societăţilor de asigurare şi a firmelor care asigură securitatea evenimentelor.

Modelul de date respectă anumite restricţii de funcţionare. • Casele de modă pot fi organizatori de prezentări. • Chiar dacă o casă de modă este organizator, ea apelează la serviciile

unei firme specializate în organizarea unor astfel de evenimente.

Page 36: CURS BD Combinat

60 PROIECTAREA BAZELOR DE DATE

• Un model sau un stilist este angajat (temporar) pentru o prezentare, de o singură casă de modă.

• O casă de modă poate angaja mai multe modele şi mai mulţi stilişti pentru o prezentare.

• Orice prezentare de modă are un organizator unic, care poate apela la serviciile altor instituţii specializate (securitate, asigurări, publicitate).

• Pentru organizator s-a considerat un singur cont în/din care se pot face plăţile.

• O casă de modă poate avea mai mulţi designeri, dar un designer poate lucra pentru o singură casă de modă.

• Pentru contactarea unei persoane fizice sau juridice s-a considerat câte un singur număr de telefon fix, telefon mobil, fax şi o singură adresă de mail.

• Pentru localizarea unei persoane fizice sau juridice s-a considerat o singură adresă de bază.

• Sunt luaţi în considerare doar angajaţii firmei de pază şi protecţie care participă efectiv la asigurarea securităţii prezentărilor de modă.

• Creatorii de accesorii pot fi angajaţi permanenţi ai unei case de modă. Dacă pentru anumite vestimentaţii sunt necesare accesorii create de specialişti care nu aparţin casei de modă, aceştia vor fi consideraţi angajaţi special pentru evenimentul respectiv.

• S-a considerat că proprietarul unei case de modă fie este unic, fie, dacă sunt mai mulţi, va fi considerat drept proprietar cel care deţine numărul maxim de acţiuni.

Entitate Entitatea este un obiect sau un concept, care este semnificativ pentru

modelul real analizat. O entitate poate fi dependentă (slabă), existenţa sa depinzând de altă entitate sau independentă (tare), caz în care ea nu depinde de existenţa altei entităţi.

Entitatea poate fi persoană, loc, concept, activitate etc. Prin urmare, ea poate fi un obiect cu existenţă fizică, reală sau poate fi un obiect cu existenţă conceptuală, abstractă.

Pentru o analiză didactică a problematicii abordate, construirea diagramelor E/R, se vor considera şi aspecte ale modelului real analizat, care nu apar în diagrama finală.

Pentru modelul de date referitor la prezentările de modă, structurile PUBLICITATE, ORGANIZATOR, PERS_CONTACT, PREZENTARE, SPONSOR, FIRMA_PUB, CASA_MODA, CREATOR, VESTIMENTATIE, MODEL, ACCESORIU, LOCALIZARE, AGENTIE, ISTORIC, FIRMA_SEC, ANGAJAT_SEC,SOCIETATE_ASIG, ANGAJAT_TEMP, INFO_CONTACT, LOCATIE reprezintă entităţi.

Observaţii • Entităţile devin tabele în modelele relaţionale. • În general, entităţile se scriu cu litere mari.

Page 37: CURS BD Combinat

Modelarea entitate-relaţie 61

• Entităţile sunt substantive, dar nu orice substantiv este o entitate. Trebuie ignorate substantivele nerelevante.

• Cheia primară identifică unic o entitate şi face distincţie între valori diferite ale entităţii. Aceasta trebuie să fie unică şi cunoscută la orice moment. Cheia primară trebuie să fie controlată de administratorul bazei, să nu conţină informaţii descriptive, să fie simplă, fără ambiguităţi, să fie stabilă, să fie familiară utilizatorului astfel încât acesta să o poată folosi cu uşurinţă.

• Pentru fiecare entitate este obligatoriu să se dea o descriere detaliată. • Nu pot exista, în aceeaşi diagramă, două entităţi cu acelaşi nume, sau

o aceeaşi entitate cu nume diferite. Vom prezenta entităţile modelului de date, dând o descriere completă a fiecăreia. De asemenea, pentru fiecare entitate se va preciza cheia primară. Toate entităţile care vor fi prezentate sunt independente, cu excepţia entităţilor dependente ACCESORIU, ISTORIC şi a subentităţii MODEL. ORGANIZATOR = firmă (persoană juridică) specializată, care se ocupă cu organizarea şi buna desfăşurare a unei prezentări de modă. Ea poate apela la societăţi specializate pentru rezolvarea problemelor ce apar în organizarea prezentării de modă sau poate oferi servicii proprii pentru desfăşurarea optimă a evenimentului. Cheia primară a entităţii este cod_organizator. PERS_CONTACT = persoană fizică, aparţinând firmei organizatoare, care este responsabilă cu un anumit domeniu de activitate specific organizării prezentării de modă. Ea poate fi contactată pentru diversele probleme care privesc prezentarea, fiind punctul de legătură dintre direcţiile din firma organizatoare şi cele din societăţile externe, care se ocupă efectiv cu realizarea tuturor problemelor ce apar în organizarea evenimentului. Atributul cod_pers_contact reprezintă cheia primară a entităţii. SPONSOR = persoană fizică sau juridică ce contribuie financiar sau în altă manieră la desfăşurarea prezentării de modă. Cheia primară a acestei entităţi este cod_sponsor. FIRMA_PUB = persoană juridică ce asigură publicitatea evenimentului. Firma organizatoare poate apela la mai multe firme de publicitate. Cheia primară a acestei entităţi este cod_firma_pub. PUBLICITATE = activitatea efectivă de publicitate asigurată de o firmă de publicitate. Firmele de publicitate asigură diferite modalităţi de realizare a publicităţii (presă, televiziune, radio etc.). Cheia primară a acestei entităţi este cod_publicitate. FIRMA_SEC = persoană juridică ce asigură securitatea prezentării de modă. Se consideră că o singură firmă asigură securitatea evenimentului. Cheia primară a acestei entităţi este cod_firma_sec.

Page 38: CURS BD Combinat

62 PROIECTAREA BAZELOR DE DATE

ANGAJAT_SEC = persoană fizică, angajată a unei firme de securitate, care participă efectiv la asigurarea serviciilor de pază şi protecţie a prezentărilor de modă. Cheia primară a acestei entităţi este cod_angajat. SOC_ASIG = persoană juridică responsabilă de asigurarea (din punctul de vedere al societăţii organizatoare) tuturor activităţilor pe care le implică prezentarea de modă. Se consideră că firma organizatoare apelează la o singură societate de asigurări. Modelul de date nu ia în considerare asigurările făcute de agenţiile de modele pentru angajatele sale, asigurările încheiate chiar de către modele sau asigurările contractate de casele de modă. Cheia primară a acestei entităţi este cod_soc_asig. PREZENTARE = evenimentul efectiv al prezentării de modă. Modelul de date consideră doar prezentări de modă semnificative din lumea caselor de modă. Cheia primară a acestei entităţi este cod_prezentare. CASA_MODA = persoană juridică a cărei activitate constă în crearea de vestimentaţii şi accesorii pentru aceste vestimentaţii. Cheia primară a entităţii este cod_casa_moda. CREATOR = persoană fizică, angajată (permanent sau special) a unei case de modă, care creează efectiv vestimentaţiile sau accesoriile acestora prezentate în cadrul evenimentului respectiv. Cheia primară a entităţii este cod_creator. VESTIMENTATIE = vestimentaţia concepută şi realizată de creatorii unei case de modă. Cheia primară a entităţii este cod_vestimentatie. ACCESORIU = entitate dependentă de VESTIMENTATIE, care conţine informaţii referitoare la accesoriile unei anumite vestimentaţii. Cheia primară a entităţii este compusă din cod_accesoriu şi cod_ vestimentatie. ANGAJAT_TEMP = persoană fizică, angajată temporar pentru o anumită prezentare de către o casă de modă, fie pentru realizarea machiajului şi a coafurii modelelor care vor prezenta vestimentaţii în cadrul prezentării (stilist), fie pentru a purta creaţiile acesteia la prezentarea respectivă (model). Cheia primară a entităţii este cod_angajat_temp. MODEL = subentitate a entităţii ANGAJAT_TEMP, ce conţine informaţii specifice manechinelor. Cheia primară a entităţii este cod_angajat_temp. AGENTIE = agenţia de modele care se ocupă cu gestionarea activităţilor (participare la prezentări de modă, contracte pentru reclama diverselor produse etc.) modelelor sale. Cheia primară a entităţii este cod_agentie. ISTORIC = entitate dependentă de MODEL, care conţine istoricul angajărilor unui model la diferite agenţii. Cheia primară a entităţii este compusă din cod_model şi data_angajare. LOCALIZARE = identifică localizarea unei persoane fizice (sponsor, persoană de contact, model, creator, stilist), juridice (firmă de publicitate, securitate, asigurări, organizator, casă de modă, agenţie de modele) sau eveniment (prezentare de modă). Cheia primară a entităţii este cod_localizare.

Page 39: CURS BD Combinat

Modelarea entitate-relaţie 63

LOCATIE = entitate care identifică locaţia în care se desfăşoară o anumită prezentare de modă. Cheia primară a entităţii este cod_locatie. INFO_CONTACT = identifică modalitatea de contact a unei persoane fizice (sponsor, persoană de contact, angajat temporar, creator) sau juridice (firmă de publicitate, securitate, asigurări, organizator, casă de modă, agenţie de modele). Cheia primară a entităţii este cod_info_contact.

Relaţie Relaţia (asocierea) este o comunicare între două sau mai multe entităţi. O

valoare a unei relaţii este o comunicare între valorile entităţilor pe care le leagă. Relaţia exprimă un raport care există între aceste entităţi. Gradul unei

relaţii este dat de numărul de entităţi participante într-o relaţie (de exemplu, relaţie binară, ternară, cvadruplă, n-ară).

Existenţa unei relaţii este subordonată existenţei entităţilor pe care le leagă. Între două entităţi pot exista mai multe relaţii.

O relaţie în care aceeaşi entitate participă mai mult decât o dată în diferite roluri defineşte o relaţie recursivă. Uneori, aceste relaţii sunt numite unare.

Observaţii • În modelul relaţional, relaţiile devin tabele speciale sau coloane

speciale care referă chei primare. • Relaţiile sunt verbe, dar nu orice verb este o relaţie. • Pentru fiecare relaţie este important să se dea o descriere detaliată. • În aceeaşi diagramă pot exista relaţii diferite cu acelaşi nume. În acest

caz, ele sunt diferenţiate de către entităţile care sunt asociate prin relaţia respectivă.

• Pentru fiecare relaţie trebuie stabilită cardinalitatea (maximă şi minimă) relaţiei, adică numărul de tupluri ce aparţin relaţiei.

Asupra entităţilor participante într-o relaţie pot fi impuse constrângeri care trebuie să reflecte restricţiile care există în lumea reală asupra relaţiilor. O clasă de constrângeri, numite constrângeri de cardinalitate, este definită de numărul de înregistrări posibile pentru fiecare entitate participantă (raport de cardinalitate). Cel mai întâlnit tip de relaţii este cel binar, iar în acest caz rapoartele de cardinalitate sunt, în general, one-to-one (1:1), one-to-many (1:n) sau many-to-many (m:n).

De exemplu, în modelul analizat este definită relaţia organizeaza care leagă entităţile ORGANIZATOR şi PREZENTARE, relaţie care poate fi scrisă sub forma ORGANIZATOR_organizeaza_PREZENTARE, pentru a percepe mai uşor asocierile existente. Relaţia are cardinalitatea minimă 1:1 şi cardinalitatea maximă 1:n. Vom prezenta relaţiile modelului de date, dând o descriere completă a fiecăreia. De fapt, denumirile acestor legături sunt sugestive, reflectând

Page 40: CURS BD Combinat

64 PROIECTAREA BAZELOR DE DATE

conţinutul acestora şi entităţile pe care le leagă. Pentru fiecare relaţie se va preciza cardinalitatea minimă şi maximă. FIRMA_PUB_face_PUBLICITATE = relaţie care leagă entităţile FIRMA_PUB şi PUBLICITATE, reflectând legătura dintre acestea (ce publicitate face o anumită firmă de publicitate). Ea are cardinalitatea minimă 1:1 (o firmă de publicitate trebuie să realizeze cel puţin o publicitate şi o publicitate trebuie făcută de cel puţin o firmă de publicitate) şi cardinalitatea maximă 1:n (o firmă de publicitate poate asigura mai multe publicităţi, iar o publicitate poate fi făcută de o singură firmă specializată). PUBLICITATE_se_face_PREZENTARE = relaţie care leagă entităţile PUBLICITATE şi PREZENTARE, reflectând legătura dintre acestea (pentru o prezentare, ce publicitate se face). Relaţia are cardinalitatea minimă 1:1 şi cardinalitatea maximă 1:n. ORGANIZATOR_are_PERS_CONTACT = relaţie dintre ORGANIZATOR şi PERS_CONTACT, reflectând legătura dintre acestea (ce persoane din firma organizatoare pot fi contactate pentru soluţionarea diverselor probleme). Ea are cardinalitatea minimă 1:1 şi cardinalitatea maximă 1:n. FIRMA_SEC_are_ANGAJAT_SEC = relaţie dintre entităţile FIRMA_SEC şi ANGAJAT_SEC, reflectând legătura dintre acestea (ce angajaţi, implicaţi în acţiunea de pază a prezentărilor de modă, au firmele de securitate). Ea are cardinalitatea minimă 1:1 şi cardinalitatea maximă 1:n. ANGAJAT_SEC_paza_PREZENTARE = relaţie de tip many-to-many dintre entitatea PREZENTARE şi ANGAJAT_SEC, reflectând legătura dintre acestea (ce angajaţi ai firmei de securitate asigură buna desfăşurare a prezentărilor de modă). Ea are cardinalitatea minimă 1:1 şi cardinalitatea maximă m:n. SOC_ASIG_asigura_PREZENTARE = relaţie dintre entitatea PREZENTARE şi SOC_ASIG, reflectând legătura dintre acestea (ce societate este angajată pentru asigurarea diverselor aspecte din cadrul prezentării de modă). Ea are cardinalitatea minimă 1:1 şi cardinalitatea maximă 1:n. CASA_MODA_participa_PREZENTARE = relaţie de tip many-to-many dintre entităţile CASA_MODA şi PREZENTARE (ce case de modă participă la prezentări). Ea arată şi dacă respectivele case participă, sau nu, ca organizator la prezentari. Relaţia are cardinalitatea minimă 1:1 şi cardinalitatea maximă m:n. CASA_MODA_lucreaza_CREATOR = relaţie dintre entităţile CASA_MODA şi CREATOR (la ce case de modă lucrează creatorii). Relaţia are cardinalitatea minimă 1:1 şi cardinalitatea maximă 1:n. CREATOR_creeaza_VESTIMENTATIE = relaţie dintre entităţile CREATOR şi VESTIMENTATIE (ce creatori realizează vestimentaţiile). Relaţia are cardinalitatea minimă 1:0 şi cardinalitatea maximă1:n.

Page 41: CURS BD Combinat

Modelarea entitate-relaţie 65

VESTIMENTATIE_are_ACCESORIU = relaţie dintre entităţile ACCESORIU şi VESTIMENTATIE (ce accesorii au vestimentaţiile). Relaţia are cardinalitatea minimă 1:0 şi cardinalitatea maximă 1:n. MODEL_prezintă_VESTIMENTATIE = relaţie ce leagă entităţile MODEL şi VESTIMENTATIE (ce vestimentaţii au fost purtate de modele). Relaţia are cardinalitatea minimă 1:1 şi cardinalitatea maximă 1:n. CREATOR_face_ACCESORIU = relaţie ce leagă entităţile CREATOR şi ACCESORIU (ce creatori au realizat accesoriile). Relaţia are cardinalitatea minimă 1:0 şi cardinalitatea maximă 1:n. PREZENTARE_prezinta_VESTIMENTATIE = relaţie care leagă entităţile PREZENTARE şi VESTIMENTATIE (ce vestimentaţii au fost prezentate la evenimentele de modă). Relaţia are cardinalitatea minimă 1:1 şi cardinalitatea maximă 1:n. PREZENTARE_are_LOCATIE = relaţie ce leagă entităţile PREZENTARE şi LOCATIE (ce prezentări de modă se desfăşoară într-o locaţie). Deoarece într-o locaţie pot să fie mai multe prezentări, relaţia are cardinalitatea minimă 1:1 şi cardinalitatea maximă n:1. MODEL_lucreaza_AGENTIE = relaţie dintre entităţile MODEL şi AGENTIE (la ce agenţie este angajat un model). Relaţia are cardinalitatea minimă 1:1 şi cardinalitatea maximă n:1. MODEL_are_ISTORIC = relaţie dintre entităţile MODEL şi ISTORIC (istoricul activităţii unui model, prin diferite agentii). Relaţia are cardinaliatea minimă 1:0 şi cardinalitatea maximă 1:n. ISTORIC_refera_AGENTIE = relaţie ce leagă entităţile ISTORIC şi AGENTIE (la ce agenţie se referă fiecare înregistrare din istoricul unui model). Relaţia are cardinalitatea minimă 1:1 şi cardinalitatea maximă 1:n. SPONSOR_finanteaza_PREZENTARE = relaţie de tip many-to-many dintre entităţile SPONSOR şi PREZENTARE, reflectând legătura dintre acestea (ce sponsori finanţează prezentările de modă). Relaţia are cardinalitatea minimă 0:1 şi cardinalitatea maximă m:n. PERS_CONTACT_are_LOCALIZARE = relaţie ce leagă entităţile LOCALIZARE şi PERS_CONTACT (localizarea unei persoane de contact). Ţinând cont de restricţiile impuse modelului, relaţia are cardinalitatea minimă 1:1 şi cea maximă 1:1. O astfel de relaţie este definită şi pentru entităţile FIRMA_PUB, FIRMA_SEC, PREZENTARE, ORGANIZATOR, CASA_MODA, SPONSOR, ANGAJAT_TEMP, SOC_ASIG, CREATOR, LOCATIE şi AGENTIE, care sunt legate de entitatea LOCALIZARE, permiţând astfel localizarea tuturor structurilor modelului. PERS_CONTACT_are_INFO_CONTACT = relaţie care leagă INFO_CONTACT şi PERS_CONTACT (modalitatea de accesare a unei persoane de contact). Ţinând cont de restricţiile impuse modelului, relaţia are cardinalitatea minimă 1:1 şi cea maximă 1:1. O astfel de relaţie este definită şi

Page 42: CURS BD Combinat

66 PROIECTAREA BAZELOR DE DATE pentru entităţile FIRMA_PUB, FIRMA_SEC, ORGANIZATOR, CASA_MODA, SPONSOR, ANGAJAT_TEMP, SOC_ASIG, CREATOR, LOCATIE şi AGENTIE, care sunt legate de entitatea INFO_CONTACT, permiţând astfel accesarea tuturor structurilor modelului. ANGAJAT_TEMP_primeste_la_PREZENTARE_de_la_CASA_MODA = relaţie de tip 3 ce leagă entităţile ANGAJAT_TEMP, PREZENTARE şi CASA_MODA, reflectând cine a fost angajat temporar, de ce casă de modă, pentru ce prezentare. Denumirea acestei relaţii va fi primeste.

Atribut Atributul este o proprietate descriptivă a unei entităţi sau a unei relaţii. De

exemplu, numele unei case de modă este un atribut al entităţii CASA_MODA, iar data la care o casă de modă participă la o prezentare este un atribut al relaţiei participă ce leagă entităţile PREZENTARE şi CASA_MODA.

Atributele pot fi simple (de exemplu, suma cu care este plătit un model de către o casă de modă pentru o prezentare), compuse (de exemplu, adresa unei firme de publicitate), cu valori multiple (de exemplu, numerele de telefon ale unei persoane de contact), derivate (de exemplu, vârsta unei persoane se obţine din data naşterii).

Observaţii • Trebuie făcută distincţia între atribut care uzual devine coloană în

modelele relaţionale şi valoarea acestuia, care devine valoare în coloane. • Atributele sunt substantive, dar nu orice substantiv este atribut. • Fiecărui atribut trebuie să i se dea o descriere completă în

specificaţiile modelului (exemple, contraexemple, caracteristici). • Pentru fiecare atribut trebuie specificat numele, tipul fizic (integer,

float, char etc.), valori posibile, valori implicite, reguli de validare, constrângeri, tipuri compuse.

În continuare vor fi prezentate, parţial, atributele entităţilor şi relaţiilor dând o descriere a fiecăruia, a caracteristicilor şi a constrângerilor pe care trebuie să le îndeplinească. Semnificaţia unor atribute a căror denumire nu este semnificativă sau care include mai multe caracteristici decât denumirea va fi comentată pe parcursul lucrării. Entitatea independentă ANGAJAT_TEMP are ca atribute: cod_angajat_temp = variabilă de tip întreg, de lungime maximă 5, care reprezintă codul unui angajat temporar. nume = variabilă de tip caracter, de lungime maximă 25, care reprezintă numele angajatului. prenume = variabilă de tip caracter, de lungime maximă 25, care reprezintă prenumele angajatului. data_nastere = variabilă de tip dată calendaristică, care reprezintă data naşterii angajatului respectiv. sex = variabilă de tip caracter, luând valorile m sau f, de lungime 1, care reprezintă sexul angajatului.

Page 43: CURS BD Combinat

Modelarea entitate-relaţie 67

nationalitate = variabilă de tip caracter, de lungime maximă 12, care reprezintă naţionalitatea unui angajat temporar. cod_localizare = variabilă de tip întreg, de lungime maximă 5, care reprezintă codul localizării angajatului. Atributul trebuie să corespundă la o valoare a cheii primare din tabelul LOCALIZARE. cod_info_acces = variabilă de tip caracter, de lungime maximă 5, care reprezintă codul informaţiei de acces pentru angajatul respectiv. Atributul trebuie să corespundă la o valoare a cheii primare din tabelul INFO_CONTACT. tip = variabilă de tip caracter, de lungime 10, care reprezintă funcţia pentru care a fost angajată persoana respectivă. De exemplu, poate să fie model, stilist sau eventual poate lua alte valori. Subentitatea MODEL are ca atribute: cod_angajat_temp = variabilă de tip întreg, de lungime maximă 5, care reprezintă codul modelului. cod_agentie = variabilă de tip întreg, de lungime maximă 5, care reprezintă codul agenţiei la care este angajat în prezent modelul. Atributul trebuie să corespundă la o valoare a cheii primare din tabelul AGENTIE. inaltime = variabilă de tip numeric, de lungime 3, care reprezintă înălţimea modelului în centimetri. nr_pantof = variabilă de tip numeric (real), care reprezintă numărul pe care îl poartă la pantof modelul respectiv. info = variabilă de tip text, care include informaţii speciale despre model (dimensiuni, greutate, preferinţe, elemente confidenţiale, palmares etc.). Entitatea PUBLICITATE are atributele: cod_publicitate, cod_firma_pub, cod_prezentare, tip, nume, suma, observatii. Atributul tip poate lua valorile radio, televiziune, presa, panouri publicitare etc. Atributul nume este legat de atributul tip în sensul că poate reprezenta numele postului de radio, al celui de televiziune, al publicaţiei care face publicitatea. Entitatea FIRMA_PUB are atributele: cod_firma_pub, nume, info, director, observatii, nume_pers_contact, cod_localizare, cod_info_acces. Entitatea ORGANIZATOR are atributele: cod_organizator, denumire, banca, cont, informatii, cod_localizare, cod_info_acces. Entitatea PERS_CONTACT are atributele: cod_pers_contact, cod_organizator, nume, prenume, directie, cod_localizare, cod_info_acces. Entitatea PREZENTARE are atributele: cod_prezentare, denumire, data_start, data_final, cod_organizator, cod_soc_asig, cod_locatie. Entitatea SPONSOR are atributele: cod_sponsor, tip, nume, info, cod_localizare, cod_info_acces. Atributul tip poate lua valorile persoana fizică sau persoana juridică. În primul caz, atributul nume va reprezenta numele şi prenumele persoanei fizice, iar în cel de al doilea caz, va reprezenta numele societăţii.

Page 44: CURS BD Combinat

68 PROIECTAREA BAZELOR DE DATE

Entitatea CASA_MODA are atributele: cod_casa_moda, nume, cifra_afaceri, proprietar, director, istoric, data_creare, cod_localizare, cod_info_acces. Entitatea CREATOR are atributele: cod_creator, nume, prenume, data_nastere, data_angajare, cod_casa_moda, tip, mod_angajare, info, cod_localizare, cod_info_acces. Atributul tip poate lua valorile designer, croitor, broder, creator_accesorii. Atributul mod_angajare poate lua valorile permanent sau special. Entitatea VESTIMENTATIE are atributele: cod_vestimentatie, denumire, valoare, descriere, cod_creator, cod_model, cod_prezentare. Entitatea ACCESORIU are atributele: cod_vestimentatie, cod_accesoriu, tip, descriere, valoare, cod creator. Entitatea AGENTIE are atributele: cod_agentie, nume, data_creare, director, cifra_afaceri, info, cod_localizare, cod_info_acces. Entitatea ISTORIC are atributele: cod_model, data_angajare, data_final, cod_agentie, conditii. Entitatea LOCALIZARE are atributele: cod_localizare, adresa, cod_postal, oras, tara. Entitatea LOCATIE are atributele: cod_locatie, denumire, tip, capacitate, cod_localizare, cod_info_acces. Atributul tip reprezintă tipul locaţiei respective şi poate lua valorile: hotel, esplanadă, teatru, mall etc. Entitatea INFO_CONTACT are atributele: cod_info_contact, telefon_mobil, mail, telefon_fix, fax. Entitatea FIRMA_SEC are atributele: cod_firma_sec, nume_firma, tip_servicii, director, observatii, cod_localizare, cod_info_acces. Entitatea ANGAJAT_SEC are atributele cod_angajat, nume, prenume, data_nastere, specializare, nivel, observatii, cod_localizare, cod_firma_sec, cod_info_acces. Entitatea SOC_ASIG are atributele: cod_soc_asig, conditii, suma, director, observatii, nume_pers_contact_firma, cod_localizare, cod_info_acces. Relaţia CASA_MODA_participa_PREZENTARE are ca atribute: cod_prezentare = variabilă de tip întreg, de lungime maximă 5, care reprezintă codul prezentării. Atributul trebuie să corespundă la o valoare a cheii primare din tabelul PREZENTARE. cod_casa_moda = variabilă de tip întreg, de lungime maximă 5, care reprezintă codul casei de modă. Atributul trebuie să corespundă la o valoare a cheii primare din tabelul CASA_MODA. tip = variabilă de tip caracter, de lungime maximă 15, care reprezintă modalitatea în care o casă de modă participă la o prezentare, în sensul că poate fi organizator sau neorganizator.

Page 45: CURS BD Combinat

Modelarea entitate-relaţie 69

data = variabilă de tip dată calendaristică reprezentând ziua în care defilează modelele casei de modă. Atributul nu este multiplu, deoarece s-a presupus că defilarea unei case de modă are loc într-o singură zi. Relaţia SPONSOR_finanteaza_PREZENTARE are ca atribute: cod_sponsor, cod_prezentare, data_emitere, suma, banca, cont_emitent, cod_ordin_plata. Relaţia ANGAJAT_SEC_paza_PREZENTARE are atributele: cod_angajat, cod_prezentare, tip_paza, dotare, observaţii. Relaţia ANGAJAT_TEMP_primeste_la_PREZENTARE_de_la_CASA_MODA are ca atribute: cod_angajat_temp, cod_casa_moda, cod_prezentare suma, data_achitare, cont, banca. Nu s-au introdus atributele cont şi banca la entitatea ANGAJAT_TEMP, deoarece modelul de date nu-şi propune să furnizeze informaţii complete referitoare la toate conturile şi băncile modelelor, stiliştilor etc. Se consideră doar banca şi contul în care casa de modă depune bani pentru prezentarea la care aceştia au fost angajaţi.

2.3. Diagrama entitate- relaţie Pentru proiectarea diagramei entitate-relaţie au fost stabilite anumite

reguli (care nu sunt unice): • entităţile sunt reprezentate prin dreptunghiuri; • relaţiile dintre entităţi sunt reprezentate prin arce neorientate; • atributele care reprezintă chei primare trebuie subliniate sau marcate

prin simbolul „#“, plasat la sfârşitul numelui acestor atribute; • cardinalitatea minimă este indicată în paranteze, iar cardinalitatea

maximă se scrie fără paranteze; • nu este necesar să fie specificate, în cadrul diagramei, toate atributele. Vom comenta câteva cazuri speciale de entităţi, relaţii, atribute şi modul

lor de reprezentare în cadrul diagramei entitate-relaţie. • Dependenţa. Există entităţi, numite entităţi dependente care nu pot

exista în mod independent. De exemplu, se observă că entitatea ACCESORIU depinde de VESTIMENTATIE, iar LOCATIE depinde de entitatea PREZENTARE. Cheia primară a unei entităţi dependente include cheia primară a sursei (cod_vestimentatie) şi cel puţin o descriere a entităţii (cod_accesoriu). Entitatea dependentă se dese-nează prin dreptunghiuri cu linii mai subţiri.

• Moştenirea atributelor. O subentitate (subclasă) este o submulţime a unei alte entităţi, numită superentitate (superclasă). De exemplu, ANGAJAT_TEMP este o superentitate pentru MODEL, iar MODEL este o subentitate pentru ANGAJAT_TEMP. Subentitatea se desenează prin dreptunghiuri incluse în superentitate. Există o relaţie

Page 46: CURS BD Combinat

70 PROIECTAREA BAZELOR DE DATE

între o subentitate şi o superentitate, numită ISA, care are cardinalitatea maximă 1:1 şi minimă 1:0.

• Cheile primare, atributele şi relaţiile unei superentităţi sunt valabile pentru orice subentitate. Afirmaţia reciprocă este falsă. De exemplu, un informatician, considerat ca subentitate a entităţii PERS_CONTACT, poate avea ca atribute limbajele de programare cunoscute şi nivelul de cunoaştere a acestora, dar aceste atribute nu sunt semnificative pentru o persoană de contact care coordonează asigurarea securităţii prezentării de modă. Cheia primară a subentităţii INFORMATICIAN este cod_pers_contact, care este cheia primară a superentităţii PERS_CONTACT.

• Specializare. După valorile unor atribute clasificatoare se pot determina clase. Un grup de subentităţi reciproc exclusive defineşte o clasă. Clasele se aliniază în desen vertical. De exemplu, pentru entitatea PUBLICITATE, după valorile atributului tip, pot fi definite subentităţile PANOURI_PUBLICITARE, PRESA, TELEVIZIUNE, RADIO, fiecare având atributele sale proprii.

• Generalizare. Din entităţi similare care au mai multe atribute comune se pot crea superentităţi. Aceste superentităţi conţin atributele comune, iar atributele speciale sunt asignate la subentităţi. Pentru noile superentităţi se introduc chei primare artificiale. De exemplu, din entităţile FIRMA_PUB, FIRMA_SEC şi SOC_ASIG se poate crea superentitatea FIRMA având drept atribute: cod_firma (cheie primară artificială), informaţii de accesare, informaţii de localizare, director, observatii.

• Într-o diagramă E/R se pot defini relaţii recursive. De exemplu, poate fi definită relaţia PERS_CONTACT_supervizeaza_PERS_CONTACT.

• Unele relaţii sunt relative la două entităţi şi le numim de tip 2, iar dacă relaţiile implică mai mult de două entităţi, le vom numi de tip 3. Trei relaţii de tip 2 sunt diferite de o relaţie de tip 3. Rupând o relaţie de tip 3 în trei relaţii de tip 2, poate să apară informaţie incorectă.

• Trebuie excluse din model relaţiile indirecte pentru că ele pot conduce la redundanţă în baza de date.

• Atributele derivabile trebuie eliminate şi introduse expresii prin care aceste atribute pot fi calculate.

• Uneori apare o incertitudine referitoare la faptul că o anumită informaţie poate fi considerată o relaţie sau un atribut. O relaţie poate fi reprezentată ca un atribut, sau putem folosi relaţii în loc de atribute. Dacă un atribut al unei entităţi reprezintă cheia primară a unei alte entităţi, atunci el referă o relaţie.

• Uneori este greu de stabilit dacă informaţia analizată reprezintă o entitate sau o relaţie. Dacă există o incertitudine, se cercetează cheia primară. Dacă această cheie combină cheile primare a două entităţi, atunci se defineşte o relaţie. Cheia primară a relaţiei organizeaza

Page 47: CURS BD Combinat

Modelarea entitate-relaţie 71

combină atributele cod_organizator şi cod_prezentare, care reprezintă cheile primare ale entităţilor ORGANIZATOR şi PREZENTARE. Prin urmare, ORGANIZATOR_organizeaza_PREZENTARE va defini o relaţie şi nu o entitate.

• Un atribut indirect este inoportun. El nu descrie real relaţia sau entitatea. Prin urmare, atributele indirecte trebuie reasignate. De fapt, un atribut indirect este un caz special de relaţie indirectă care trebuie eliminată pentru că introduce redundanţă în date.

• Există atribute opţionale, a căror valoare este uneori necunoscută, alteori neaplicabilă. Aceste atribute trebuie introduse la subentităţi.

Algoritmul pentru proiectarea diagramei E/R cuprinde următoarele etape: 1. identificarea entităţilor din cadrul sistemului analizat; 2. identificarea relaţiilor (asocierilor) dintre entităţi şi stabilirea cardi-

nalităţii; 3. identificarea atributelor aferente entităţilor şi asocierilor dintre

entităţi; 4. stabilirea atributelor de identificare a entităţilor, adică stabilirea

cheilor. Relaţiile reflectă legături naturale care există între componentele

sistemului. Aceeaşi realitate poate fi însă percepută diferit de către diverşi analişti pentru un acelaşi sistem, putând fi obţinute modele structurale distincte. O diagramă E/R pentru modelul comentat în această secţiune este reprezentată în figura 2.1. Diagrama este corectă, dar este optimizabilă.

Construirea diagramei conceptuale, obţinerea schemelor relaţionale şi normalizarea acestora vor genera un model relaţional care va elimina anumite clase de anomalii ce pot să apară în proiectarea modelului de date.

Deficienţe ale modelului E/R În proiectarea unui model de date pot apărea diverse probleme datorită

unei interpretări eronate a sensului unei relaţii. Aceste probleme sunt denumite capcane de conectare.

Unele dintre aceste capcane pot să nu fie semnificative pentru modelul particular considerat, în timp ce altele cer restructurarea modelului. Există două clase importante de capcane: de întrerupere şi în evantai.

O capcană de întrerupere poate să apară acolo unde modelul sugerează existenţa unei relaţii între entităţi, dar nu există o cale între anumite apariţii ale entităţilor. Această capcană poate să apară acolo unde există o relaţie cu participare parţială (0 la cardinalitatea minimă), care face parte din calea dintre entităţile ce sunt legate.

O capcană în evantai poate să apară acolo unde modelul ia în considerare o relaţie între entităţi, dar calea dintre anumite apariţii ale entităţilor este ambiguă. Aceste capcane apar când două sau mai multe relaţii one_to_many provin din aceeaşi entitate.

Page 48: CURS BD Combinat

72 PROIECTAREA BAZELOR DE DATE

Fig. 2.1. Diagrama E/R. Practic, aceste capcane generează situaţiile în care, aşa cum a fost

proiectat modelul de date, el nu poate să răspundă la anumite interogări. De exemplu, pentru a afla pentru ce prezentare de modă a fost creată o anumită vestimentaţie, a fost necesară introducerea unei legături între entităţile PREZENTARE şi VESTIMENTATIE, care însă a generat redundanţă în modelul de date.

Modelul E/R extins Conceptele de bază ale modelării entitate-relaţie nu sunt suficiente pentru

a reprezenta cerinţele aplicaţiilor actuale, care sunt mult mai complexe. Au fost propuse, în acest sens, mai multe modele de date semantice. Modelul E/R susţinut cu concepte semantice adiţionale defineşte modelul E/R extins (EER).

FIRMA_PUB

PUBLICITATE

PREZENTARE

ORGANIZATOR PERS_CONTACT

LOCATIE

INFO_CONTACT

LOCALIZARE

SPONSOR ANGAJAT SEC

FIRMA SEC

CASA_MODA

CREATOR

VESTIMENTATIE

ACCESORIU

ANGAJAT_TEMP

MODEL

ISTORIC

SOC ASIG

AGENTIE

primeste

are

refera are

creeaza

lucreaza

participa

prezinta

face

asigura

paza

are

se_face

face

organizeaza

are

finanteaza

are

are

are

1

M(1)

1

M(1)

1

M(1)

M(1) M(1) 1

M(1) 1

M(1)

1

M(1) M(1) M(0)

1 M(1)

1

1

M(1)

1

1 M(1)

M(1)

1

M(1)

M(0)

1

M(1)

1

1

M(0) M(0)

prezinta

M(1)

M(1)

M(1)

M(0)

1 1

1

1 lucreaza_la

1 1(0) ISA

Page 49: CURS BD Combinat

Modelarea entitate-relaţie 73

Acesta include toate conceptele modelului original, împreună cu conceptele adiţionale de specializare, generalizare şi categorie. Aceste noi concepte au fost deja nominalizate în acest capitol.

Superclasa (superentitatea) este o entitate care include subclase (subentităţi) distincte, ce trebuie reprezentate în modelul de date. Subclasa are un rol distinct şi, evident, este membră a unei superclase. O subclasă, fiind o entitate, poate să posede propriile subclase. O entitate împreună cu subclasele ei, subclasele acestora şi aşa mai departe defineşte o ierarhie de tip (ierarhie de specializare). De exemplu, ANGAJAT_TEMP reprezintă o superclasă pentru entitatea MODEL.

Specializarea este procesul de maximizare a diferenţelor dintre membrii unei entităţi, prin identificarea caracteristicilor distinctive ale acestora. Specializarea constituie o abordare de sus în jos în definirea unei mulţimi de superclase şi a subclaselor lor. Pot exista diverse specializări ale aceleiaşi entităţi, bazate pe diferite caracteristici de diferenţiere.

Dacă subclasele unei specializări sunt disjuncte, atunci o entitate poate fi membră doar a unei subclase a acesteia (constrângere de disjuncţie).

O specializare cu participare totală specifică faptul că fiecare entitate din superclasă trebuie să fie membră a unei subclase din specializare (constrângere de participare).

De exemplu, specializarea contractelor de angajare poate fi cu participare totală dacă fiecare angajat din PERS_CONTACT este fie angajat cu contract permanent cu normă întreagă, fie cu contract temporar cu normă incompletă.

O specializare cu participare parţială specifică faptul că nu este necesar ca o entitate să aparţină vreunei subclase a acesteia. De exemplu, există salariaţi în PERS_CONTACT care nu aparţin niciunei subentităţi ale acesteia.

Generalizarea este procesul de minimizare a diferenţelor dintre entităţi, prin identificarea caracteristicilor comune ale acestora. Generalizarea reprezintă o abordare de jos în sus, care are ca rezultat identificarea unei superclase generalizate din subclasele iniţiale.

Orice relaţie superclasă/subclasă (inclusiv cele ale unei subclase partajate) dintr-o ierarhie de specializare/generalizare are o singură superclasă. Totuşi, anumite situaţii necesită modelarea unei relaţii superclasă/subclasă cu mai mult decât o superclasă distinctă. În acest caz, subclasa defineşte o categorie. Categoria este procesul de modelare a unei singure subclase, cu o relaţie care implică mai mult decât o singură superclasă distinctă.

2.4. Modelare orientată pe obiecte cu UML Un limbaj de modelare reprezintă o modalitate de a comunica despre un

sistem şi de a exprima diversele modele produse în cadrul procesului de analiză şi dezvoltare a sistemului. Limbajul furnizează o notaţie care permite reprezentarea unui design.

Page 50: CURS BD Combinat

74 PROIECTAREA BAZELOR DE DATE

Limbajul este format dintr-un set de concepte, principii şi reguli de utilizare a acestora, cu scopul de a reprezenta modelele produse în diferite etape de dezvoltare a sistemului. Fără un limbaj de modelare, este dificilă colaborarea şi comunicarea dintre membrii echipei pe parcursul proiectării sistemului.

Ca orice limbaj, un limbaj de modelare are o sintaxă şi o semantică, iar pentru semantica modelului trebuie aleasă sintaxa cea mai expresivă. De cele mai multe ori, un limbaj de modelare este un limbaj grafic (diagramatic).

Dacă pentru utilizatori, limbajele de modelare uşurează munca de realizare a sistemelor software, pentru realizatorii acestora sarcinile sunt multiple şi dificile. Pentru ca un limbaj de modelare să se impună, el trebuie să asigure o bună specificare a conceptelor sale şi a modului de reprezentare a acestora. În acest scop, limbajele trebuie să asigure suport pentru modelatori, în vederea rafinării treptate a soluţiei şi a captării semanticii procesului.

The Unified Modeling Language (UML) este, aşa cum semnifică şi numele, un limbaj vizual de modelare şi de comunicare despre sistem. UML nu este un limbaj de programare, deoarece nu dispune de întreg sprijinul semantic şi vizual pentru a defini un astfel de limbaj. înlocui limbajele de programare. UML este un limbaj pentru modelarea orientată pe obiecte, cu suport pentru modelare vizuală, funcţionând ca o modalitate de a comunica şi de a exprima cunoştinţe.

UML este un limbaj grafic de modelare pentru specificarea, vizualizarea, construcţia şi documentarea componentelor unui sistem software (pentru întreprinderi, telecomunicaţii, sisteme bancare şi financiare, transporturi etc.) sau pentru modelarea organizaţională a unor sisteme non-software (din justiţie, medicină, afaceri etc.).

UML nu este un limbaj de programare, dar modelele exprimate în UML pot fi implementate uşor în limbaje de programare orientate pe obiecte (C++, Java, C#) sau în baze de date relaţionale. Este posibilă nu numai generarea codului dintr-un model UML, dar şi ingineria inversă, constând în construirea dintr-un cod dat a unui model UML.

UML este un limbaj de modelare pentru documentare, deoarece permite realizarea tuturor documentelor necesare înţelegerii modelului şi diagramelor utilizate pe tot parcursul ciclului de viaţă al unui proces de realizare a unui sistem. Documentele componentelor sistemului conţin specificarea cerinţelor, arhitecturii şi proiectării sistemului; elaborarea codului sursă, planuri de dezvoltare şi de management al proiectului.

În concluzie, UML nu este un limbaj de programare vizual, dar este un model de limbaj de modelare vizual; nu este o metodologie, dar este o notaţie pentru aceasta; nu este un proces, dar oferă suport complet pentru construcţia şi dezvoltarea acestuia.

Este important de menţionat că UML este un limbaj de modelare, şi nu o metodă. Majoritatea metodelor conţin atât un limbaj de modelare, cât şi un proces. Limbajul de modelare furnizează, după cum am mai subliniat, doar notaţia pentru reprezentarea unui design. Procesul cuprinde, însă, paşii care trebuie să fie urmaţi pentru a realiza un design.

Page 51: CURS BD Combinat

Modelarea entitate-relaţie 75

UML cuprinde tehnici specifice mai multor metode de dezvoltare (proiectare) şi este suficient de logic, de expresiv pentru a putea fi utilizat împreună cu orice metodă sau proces de dezvoltare.

Ca orice limbaj, UML are sintaxa şi semantica sa. Cu ajutorul alfabetului şi al cuvintelor limbajului, se pot scrie propoziţii (fragmente din diagrame) despre subiectul de analizat. Propoziţiile se pot grupa în paragrafe (diagrame UML).

Paragrafele, la rândul lor, se pot grupa în secţiuni (moduri de vizualizare) şi, în final, secţiunile se pot organiza în documente. Documentele UML sunt modelele sistemului.

Sintaxa limbajului UML implică diagrame, în timp ce semantica lui se bazează pe paradigma orientării pe obiecte. Din punct de vedere al modelării orientate pe obiecte, entităţile (conceptele) se numesc clase, iar relaţiile dintre ele se numesc asocieri.

Diagrama este o reprezentare grafică a unei mulţimi de elemente, de obicei folosindu-se forme geometrice pentru a reprezenta entităţi şi linii pentru a reprezenta asocieri. În UML, diagrama este o proiecţie a sistemului, reprezentând o parte a sistemului sau chiar întregul sistem dintr-un anumit punct de vedere. Acelaşi element poate apărea în toate diagramele, în câteva diagrame sau în nicio diagramă.

UML conţine 9 tipuri de diagrame, fiecare reflectând una sau mai multe dintre cele 5 tipuri de vizualizări posibile asupra unui sistem software.

• Diagrama claselor descrie structura unui sistem în general. În componenţa ei intră clase, stereotipuri şi relaţiile dintre acestea.

• Diagrama obiectelor descrie structura unui sistem la un anumit moment. Acest tip de diagramă este o variantă a diagramei claselor care, în locul unei clase, prezintă mai multe instanţe ale ei, fiind formată din obiecte şi legături dintre ele.

• Diagrama cazurilor de utilizare descrie funcţionalitatea unui sistem, prezentând actorii externi, cazurile de utilizare identificate numai din punct de vedere al actorilor (comportamentul sistemului, aşa cum este perceput de utilizatorii lui), precum şi relaţiile dintre actori şi cazurile de utilizare. Un actor poate fi orice sau oricine interacţionează cu sistemul (trimite sau recepţionează mesaje de la sistem sau schimbă informaţii cu acesta). Actorul are un rol în cadrul unui sistem, nu este un utilizator individual al acestuia şi, din acest motiv, el este o entitate (o clasă), nu o instanţă. Un caz de utilizare este iniţiat mereu de un actor şi furnizează o valoare actorului.

• Diagrama componentelor (diagrama de implementare) descrie structura fizică a codului în termenii componentelor de cod şi relaţiilor dintre acestea.

• Diagrama de desfăşurare (de exploatare) indică arhitectura fizică pe care este implementat sistemul, calculatoarele, nodurile sistemului şi conexiunile dintre ele.

Page 52: CURS BD Combinat

76 PROIECTAREA BAZELOR DE DATE

• Diagrama secvenţelor este o diagramă de interacţiune, care prezintă colaborarea dinamică dintre un număr de obiecte, punând accentul pe secvenţele de mesaje trimise între acestea pe măsura scurgerii timpului.

• Diagrama de colaborare este tot o diagramă de interacţiune, dar care, pe lângă interacţiunea dintre obiecte (schimbul de mesaje), prezintă obiectele şi legăturile dintre ele.

• Diagrama de stare descrie ciclul de viaţă al unui element (al obiectelor, subsistemelor şi sistemelor), prin specificarea stărilor în care se găseşte elementul şi a evenimentelor care îi modifică starea.

• Diagrama de activitate prezintă activităţile şi responsabilităţile elementelor sistemului, fiind utilizată pentru modelarea funcţiilor sistemului. Ea are ca elemente constitutive stări de acţiune şi mesaje care vor fi trimise sau recepţionate ca parte a acţiunii realizate.

În UML, diagramele fac parte din două categorii. • Diagrame dinamice sau comportamentale – descriu comportamentul

şi interacţiunile dintre diverse entităţi ale sistemului informatic. Din această categorie, fac parte diagramele de secvenţă, colaborare, stare şi activitate.

• Diagrame statice sau structurale - descriu structura, responsabilităţile sistemului informatic, componentele executabile ale sistemului, locaţiile fizice de execuţie şi nodurile de stocare a datelor. Din această categorie, fac parte diagramele claselor, obiectelor, cazurilor de utilizare, componentelor şi diagramele de exploatare.

Pe lângă structura statică şi comportamentul dinamic, pentru caracterizarea completă a unui sistem este necesară şi funcţionalitatea acestuia, care poate fi analizată folosind diagramele cazurilor de utilizare.

Din punct de vedere al modelării sistemelor orientate pe obiecte din perspectiva UML, aspectele statice sunt: clasele şi relaţiile dintre clase, interfeţele, topologia hardware necesară execuţiei aplicaţiei.

Secţiunile UML sau modurile de vizualizare sunt grupuri de diagrame care se adresează unei anumite mulţimi de entităţi. Toate diagramele UML pot fi organizate în vizualizări. Fiecare vizualizare este descrisă folosind un număr de diagrame ce conţin informaţii referitoare la un anumit aspect particular al sistemului.

Există 5 tipuri importante de vizualizări asupra unui sistem software. • Modul de vizualizare structural (logic) al arhitecturii unui sistem

se referă la cerinţele funcţionale ale acestuia, adică prezintă serviciile furnizate de sistem utilizatorilor săi. Vizualizarea logică tratează din interior sistemul şi descrie atât structura internă a acestuia, formată din clase, obiecte şi relaţii, cât şi colaborările, legăturile care apar în urma schimbului de mesaje între obiecte, pentru a realiza funcţionalitatea dorită. Notaţia UML este dedicată, în mare parte, reprezentării

Page 53: CURS BD Combinat

Modelarea entitate-relaţie 77

arhitecturii logice (clase, asocieri, obiecte, legături, generalizări, polimorfism, pachete etc.)

• Modul de vizualizare a componentelor sistemului (implementare) se concentrează pe descrierea componentelor care implementează sistemul, dependenţele care există între ele, resursele alocate acestora, precum şi rezolvarea unor probleme legate de reutilizarea, portabilitatea codului şi informaţii administrative.

• Modul de vizualizare a cazurilor de utilizare surprinde funcţionalitatea sistemului, aşa cum este ea percepută de actorii externi care interacţionează cu sistemul, precum şi de utilizatorii acestuia, de diferiţi membri ai echipei realizatoare sau de către alte sisteme. În componenţa acestui mod intră diagramele cazurilor de utilizare pentru descrierea statică a aspectului funcţional şi ocazional. Se pot folosi şi diagrame de activitate pentru a încapsula latura dinamică a funcţionalităţii.

• Modul de vizualizare comportamental este util pentru gestionarea eficientă a resurselor, pentru execuţii paralele şi tratări asincrone ale unor evenimente din sistem, precum şi pentru rezolvarea unor probleme legate de comunicare şi sincronizare.

• Modul de vizualizare a desfăşurării (mediu) se referă la desfăşurarea fizică a sistemului, indicând ce calculatoare şi ce tipuri de noduri vor fi folosite pentru implementarea sistemului, cum sunt acestea conectate, precum şi ce procese se vor executa în fiecare nod.

UML oferă, pe lângă elementele de bază, şi unele facilităţi care permit organizarea şi extinderea diagramelor. Aceste facilităţi pot fi simple notaţii sau pot fi elemente de extindere a limbajului UML. Dintre facilităţile cele mai importante se remarcă pachetele, notele, stereotipurile şi proprietăţile.

• Pachetul reprezintă un mecanism de grupare a elementelor de modelare. În UML, un pachet defineşte un mecanism de organizare a elementelor în grupuri legate semantic.

• Nota cuprinde ipotezele şi deciziile aplicate în timpul analizei şi al proiectării. Notele sunt corespondentul comentariilor din limbajele de programare.

• Stereotipul este un concept introdus în UML, care permite extinderea elementelor de bază pentru a crea noi elemente. Un stereotip reprezintă un înţeles specific asociat unui element.

• Proprietatea este un element de extindere UML, care lărgeşte proprietăţile şi semantica unui element UML.

Modelarea unui sistem priveşte modelarea aspectelor sale funcţionale, statice şi dinamice. Pentru ca un sistem să aibă succes, în primul rând trebuie ca cerinţele sistemului să fie exprimate într-o manieră care să permită o uşoară înţelegere, indiferent de nivelul de pregătire informatică a celor implicaţi în

Page 54: CURS BD Combinat

78 PROIECTAREA BAZELOR DE DATE

proiect, iar în al doilea rând trebuie ca membrii echipei de dezvoltare să poată asimila cu uşurinţă modificările care apar pe parcurs în cerinţe.

Aceste condiţii sunt rezolvate în diagrama cazurilor de utilizare, care are rolul de a reprezenta în formă grafică funcţionalităţile pe care trebuie să le îndeplinească sistemul în faza sa finală. Pentru crearea modelului cazurilor de utilizare, trebuie identificaţi actorii, cazurile de utilizare, relaţiile dintre actori şi relaţiile dintre cazurile de utilizare. Realizarea acestor faze presupune discuţii între utilizatori şi analiştii de sistem.

Cazul de utilizare poate fi privit ca un instrument de stimulare a posibililor utilizatori în exprimarea propriilor puncte de vedere. Adeseori, utilizatorii ştiu mai multe decât pot să explice şi nu le este uşor să se pronunţe clar cum vor folosi sistemul. Cazurile de utilizare ajută la îndepărtarea acestui impediment.

Discuţiile iniţiale trebuie să ducă la descoperirea actorilor şi a cazurilor de utilizare care descriu cerinţele funcţionale în termeni generali şi care pot stabili frontierele domeniului studiat. Următoarele discuţii au ca scop înţelegerea, în detaliu, a domeniului studiat, ceea ce duce la evitarea introducerii unor cazuri de utilizare, care ar îngreuna procesul de analiză.

Un caz de utilizare este o descriere a unei funcţionalităţi pe care o oferă sistemul, o colecţie de scenarii referitoare la utilizarea unui sistem. Un scenariu descrie o succesiune de evenimente introduse de un actor, care poate fi o persoană, un dispozitiv hardware sau chiar trecerea timpului. Deci, actorii sunt entităţile care iniţiază o secvenţă de evenimente (un scenariu). Rezultatul secvenţei de evenimente trebuie să fie concretizat în ceva utilizabil de către actorul ce a iniţiat secvenţa sau de către alt actor.

Diagrama cazurilor de utilizare are ca elemente de modelare actorii, cazurile de utilizare, relaţiile dintre cazurile de utilizare.

Detaliile despre fiecare caz de utilizare pot fi date în documente text sau pot fi folosite tehnici noi, de modelare dinamică, de exemplu diagramele de activitate sau diagramele de interacţiune, pentru a specifica secvenţele de paşi ale cazului de utilizare.

Construirea unei diagrame a cazurilor de utilizare are drept obiective: • să capteze şi să descrie cerinţele funcţionale ale sistemului, cerinţe

rezultate în urma discuţiilor purtate de clienţi şi/sau utilizatori ai sistemului cu dezvoltatorii acestuia;

• să ofere o descriere clară şi consistentă a ceea ce va trebui să facă sistemul, adică folosirea modelului pentru comunicarea cerinţelor tuturor persoanelor implicate în construirea sistemului, şi să constituie un punct de plecare pentru alte activităţi (design, testare şi implementare);

• să constituie o bază pentru realizarea textelor de verificare, ce decid dacă funcţionalitatea finală concordă cu cerinţele iniţiale ale sistemului;

Page 55: CURS BD Combinat

Modelarea entitate-relaţie 79

• să permită transformarea cerinţelor funcţionale în viitoare clase şi operaţii.

Diagramele UML pot fi desenate şi administrate utilizând un utilitar CASE (Computer Edit Software Engineering). Aceste utilitare sunt deosebit de utile în cazul unor diagrame complexe. Totuşi, dacă diagrama este prea complicată, atunci este necesară partiţionarea ei în mai multe diagrame sau reprezentarea la un nivel superior de abstractizare.

Exemple de utilitare CASE care permit realizarea diagramelor UML sunt reprezentate de: Microsoft Office Visio, IBM Rational Rose Professional Data Modeler, Altova UModel, Borland Together, Visual Paradigm for UML, ArgoUML etc.

Interesul pentru suportul modelării bazelor de date cu ajutorul UML a condus la crearea unor profile specifice. Un profil constituie o propunere a unei comunităţi şi regrupează o mulţime de elemente UML care se aplică unui context particular şi care conservă metamodelul UML. IBM Rational Rose include un astfel de profil adaptat bazelor de date.

Există o diferenţă între un model (de exemplu, modelul conceptual de date) şi un formalism (în care este descris un model). Astfel, putem vorbi despre modelarea conceptuală a datelor urmând formalismul entitate-relaţie sau formalismul UML. Notaţia exprimă doar aspectul referitor la reprezentare.

Pe lângă formalismul entitate-relaţie, considerat standardul de facto pentru modelarea datelor, o opţiune alternativă este oferită de către UML. Acesta include primitive pentru modelarea datelor, iniţial concepute pentru reprezentarea structurii claselor unei aplicaţii orientate obiect, dar care pot fi folosite pentru specificarea modelului de date al domeniului unei aplicaţii. În particular, diagramele de clase UML pot fi utilizate ca alternativă la diagramele entitate-relaţie.

Diferenţa majoră dintre o diagramă de clase UML şi o diagramă entitate-relaţie este reprezentată de diferenţa dintre o clasă şi o entitate: o clasă este o generalizare a noţiunii de entitate, care permite proiectantului să specifice nu numai atribute, ci şi funcţii (numite metode) aplicabile instanţelor clasei. Astfel, această diferenţă face ca UML să fie mai general decât modelul entitate-relaţie, iar proiectantul poate exploata diagramele de clase UML pentru a realiza aceeaşi specificaţie pe care o poate obţine cu ajutorul modelului entitate-relaţie.

Page 56: CURS BD Combinat

80 PROIECTAREA BAZELOR DE DATE

Fig. 2.2. Diagrama de clase corespunzătoare unei restricţii a modelului. Diagramele de clase UML au mai multe caracteristici decât diagramele

entitate-relaţie, cum ar fi posibilitatea de a specifica reguli de derivare pentru atribute şi relaţii utilizând limbajul OCL (Object Constraint Language).

Pentru exemplificarea utilizării formalismului UML, vom considera o restricţie a modelului utilizat pe parcursul acestei lucrări şi vom construi diagrama de clase corespunzătoare. Construcţia diagramei a fost realizată cu ajutorul programului Microsoft Visio şi este prezentată în figura 2.2 . Din motive de spaţiu, a fost redus numărul de atribute precizate pentru fiecare clasă din cadrul diagramei.

Page 57: CURS BD Combinat

Modelarea entitate-relaţie 81

Prezentăm câteva observaţii referitoare la construcţia acestui model utilizând o diagramă de clase UML. Unele observaţii au caracter general, amintind anumite noţiuni UML necesare înţelegerii construcţiei modelului.

• Tabelul următor stabileşte echivalenţele dintre formalismele modelului entitate-relaţie şi al notaţiei UML:

Entitate-relaţie UML Tip entitate Clasă Asociere (relaţie) Asociere (relaţie) Entitate Obiect Cardinalitate Multiplicitate Model conceptual de date

Diagramă de clase

• Descrierea claselor în UML se divide în trei compartimente care conţin respectiv numele clasei, atributele acesteia şi signatura metodelor clasei. În cazul reprezentării unui model relaţional de date nu există metode, deci al treilea compartiment este vid.

• Cardinalităţile din modelul entitate-relaţie propus de Chen şi multiplicităţile din formalismul UML sunt poziţionate identic pe axa de reprezentare a relaţiei.

• Asocierile dispun de anumite caracteristici, dintre care se remarcă: nume, roluri, clase de asociere.

• Numele unei asocieri este dat de o formă verbală activă sau pasivă. Acest nume este plasat în mijlocul liniei reprezentând relaţia respectivă. De exemplu, asocierea organizeaza dintre clasele Organizator şi Prezentare este reprezentată în diagrama de clase prin acest nume plasat pe linia care conectează cele două clase.

• Numele asocierii poate fi însoţit de un triunghi îndreptat către clasa desemnată de forma verbală, cu scopul de a indica sensul de citire a relaţiei. De exemplu, în cazul asocierii creeaza se precizează că relaţia se citeşte dinspre clasa Creator către clasa Vestimentatie.

• Extremitatea unei asocieri poate indica un rol. Acesta descrie modul în care clasele sunt percepute prin intermediul relaţiei respective. Un rol este în general desemnat printr-o formă nominală sau verbală. De exemplu, asocierea lucreaza dintre clasele Casa_moda şi Creator este reprezentată atât prin nume, cât şi prin rolurile angajat şi firma.

• În UML, asocierile one to one (1:1) au multiplicitatea 0..1 sau 1 la fiecare extremitate; asocierile one to many (1:N) au multiplicitatea * sau 1..* la o extremitate şi 0..1 sau 1 la cealaltă extremitate; asocierile many to many (N:N) au multiplicitatea * sau 1..* la fiecare extremitate.

Page 58: CURS BD Combinat

82 PROIECTAREA BAZELOR DE DATE

• O asociere many to many cu atribute este reprezentată în UML printr-o clasă de asociere. Aceasta conţine atributele asocierii şi este conectată printr-o linie punctată la linia reprezentând relaţia. De exemplu, asocierii dintre clasele Sponsor şi Prezentare îi este ataşată clasa de asociere Finanteaza.

• Între clasele Angajat_temp şi Model există o asociere de generalizare, corespunzătoare relaţiei ISA („is a”). Generalizarea este reprezentată printr-o săgeată, al cărei vârf este un triunghi gol, dinspre subclasă către superclasă.

• Între clasele Vestimentatie şi Accesoriu există o relaţie de agregare compusă. Agregarea reprezintă în UML o asociere care nu este simetrică şi pentru care o extremitate are un rol predominant faţă de cealaltă. Această asociere priveşte un singur rol al său. Agregarea aparţine mai degrabă etapei de concepţie detaliată decât celei de modelare. Astfel, ea se va traduce la nivelul codului SQL prin declanşatori sau constrângeri.

• Există două forme de agregare: compusă şi partajată. Compunerea exprimă o relaţie de apartenenţă mai puternică, apărând atunci când relaţia este de tipul „compune” sau „face parte din”. Reprezentarea compunerii se face prin intermediul unui romb plin, poziţionat lângă clasa care reprezintă întregul. Multiplicitatea extremităţii agregat nu poate depăşi 1.

• Agregarea partajată presupune că un obiect poate face parte din mai multe agregate, iar întregul se poate modifica în timp.O astfel de relaţie se reprezintă prin intermediul unui romb gol, poziţionat lângă clasa care reprezintă întregul.

• Relaţiile de grade strict mai mari decât 2 sunt reprezentate în UML cu ajutorul unui romb (ca în figura 2.2) sau prin intermediul unei clase cu stereotip. Stereotipurile constituie un mecanism de extensibilitate al UML. Ele permit extinderea vocabularului UML astfel încât să poată fi definite noi elemente ale modelului, derivate din cele existente dar cu proprietăţi specifice domeniului problemei. Reprezentarea grafică a unui stereotip se face prin plasarea numelui său, încadrat între caracterele „<<” şi „>>” deasupra numelui unui alt element.

• În exemplul considerat, asocierea primeste este ternară, constituind totodată o clasă de asociere. Reprezentarea acestei relaţii de gradul 3 prin intermediul unei clase cu stereotip are forma indicată în figura 2.3.

Page 59: CURS BD Combinat

Modelarea entitate-relaţie 83

Fig. 2.3. Asociere UML de tipul 3 cu stereotip.

Page 60: CURS BD Combinat

Diagrame entitate-relaţie

Diagrama E/R – model neformalizat pentru reprezentarea unui

sistem din lumea reală. Este un model de date conceptual de nivel înalt dezvoltat de Chen (1976) pentru a facilita proiectarea bazelor de date.

Modelul de date conceptual este independent de: • tipul SGBD-ului; • platforma hardware utilizata. Modelul conceptual este constituit din concepte care descriu: • structura bazei de date; • tranzactii de regasire si reactualizare asociate.

Entitate: persoană, loc, concept, activitate, eveniment care este semnificativ pentru ceea ce modelăm. lucreaza_in conduce apartine_la atasat_la

Observaţii: • Entităţile devin tabele în modelele relaţionale. • În general, entităţile se scriu cu litere mari.

• Entităţile sunt substantive, dar nu orice substantiv este o entitate.

• Pentru fiecare entitate este obligatoriu să se dea o descriere detaliată.

• Nu pot exista, în aceeaşi diagramă, două entităţi cu acelaşi nume, sau o aceeaşi entitate cu nume diferite.

Cheia primară este un identificator unic în cadrul entităţii, făcând distincţie între valori diferite ale acesteia.

DEPARTAMENT

SALARIAT

SARCINA

PROIECT

Page 61: CURS BD Combinat

2

Cheia primară: • trebuie să fie unică şi cunoscută la orice moment; • trebuie să fie controlată de administratorul bazei; • trebuie să nu conţină informaţii descriptive, să fie simplă, fără

ambiguităţi; • să fie stabilă; • să fie familiară utilizatorului.

Relaţie (asociere): o comunicare între două sau mai multe entităţi. Existenţa unei relaţii este subordonată existenţei entităţilor pe care le leagă. Gradul (tipul) unei relatii este dat de numarul entitatilor participante la relatia respectiva.

Observaţii: • În modelul relaţional, relaţiile devin tabele speciale sau coloane

speciale care referă chei primare. • Relaţiile sunt verbe, dar nu orice verb este o relaţie. • Pentru fiecare relaţie este important să se dea o descriere

detaliată. • În aceeaşi diagramă pot exista relaţii diferite cu acelaşi nume. În

acest caz, le diferenţiază entităţile care sunt asociate prin relaţia respectivă.

• Pentru fiecare relaţie trebuie stabilită cardinalitatea (maximă şi minimă) relaţiei, adică numărul de tupluri ce aparţin relaţiei.

Se pot afla cardinalitatile cu verbele : poate (cardinalitate maximă) trebuie (cardinalitate minima) Exemplu:

Câţi salariaţi pot lucra într-un departament? Mulţi! În câte departamente poate lucra un salariat? In cel mult unul! Relaţia SALARIAT_lucreaza_in_DEPARTAMENT are cardinalitatea maximă many-one (n:1).

Exemplu: Câţi salariaţi trebuie să conducă un departament? Cel puţin unul! Câte departamente trebuie să conducă un salariat? Zero! Relaţia SALARIAT_conduce_DEPARTAMENT are cardinalitatea minimă one-zero (1:0).

Page 62: CURS BD Combinat

3

Atribut: proprietate descriptivă a unei entităţi sau a unei relaţii. Atributele pot fi simple, compuse, cu valori multiple, derivate.

Observaţii: • Trebuie făcută distincţia între tipul atributului (devine coloană în

modelele relaţionale) şi valoarea acestuia (devine valoare în coloane).

• Atributele sunt substantive, dar nu orice substantiv este atribut. • Fiecărui atribut trebuie să i se dea o descriere completă (exemple,

contraexemple, caracteristici). • Pentru fiecare atribut trebuie specificat numele, tipul fizic

(integer, float, char etc.), valori posibile, valori implicite, reguli de validare, tipuri compuse.

Pentru proiectarea diagramei entitate-relaţie au fost stabilite anumite reguli (nu sunt unice):

1. entităţile sunt reprezentate prin dreptunghiuri; 2. relaţiile dintre entităţi sunt reprezentate prin arce neorientate; 3. atributele care reprezintă chei primare trebuie subliniate sau

marcate prin simbolul „#“, plasat la sfârşitul numelui acestor atribute;

4. cardinalitatea minimă este indicată în paranteze, iar cardinalitatea maximă se scrie fără paranteze;

5. nu trebuie specificate toate atributele.

Diagrama E/R.

conduce lucreaza_in apartine_la

SALARIAT cod_salariat nume prenume sex salariu

PROIECT nr_proiect descriere buget_alocat

DEPARTAMENT cod_departament nume nr_cladire

SARCINA nr_proiect nr_sarcina data_inceperii stare

atasat_la

data_initiala functia

1

1

M(0)

1(0) M

1

M(0) M(0)

Page 63: CURS BD Combinat

4

Cazuri speciale de entităţi, relaţii, atribute şi modul lor de reprezentare în cadrul diagramei entitate-relaţie.

1. Entitate dependentă – nu poate exista în mod independent (SARCINA depinde de PROIECT). Cheia primară a unei entităţi dependente include cheia primară a sursei (nr_proiect) şi cel puţin o descriere a entităţii (nr_sarcina). Entitatea dependentă se desenează prin dreptunghiuri cu linii mai subţiri.

2. Moştenirea atributelor. Subentitate (subclasă) – submulţime a unei alte entităţi, numită superentitate (superclasă) (SALARIAT < –– > PROGRAMATOR). Subentitatea se desenează prin dreptunghiuri incluse în superentitate. Există o relaţie între o subentitate şi o superentitate, numită ISA, care are cardinalitatea maximă 1:1 şi minimă 1:0. Cheile primare, atributele şi relaţiile unei superentităţi sunt valabile pentru orice subentitate. Afirmaţia reciprocă este falsă.

3. Generalizare. Din entităţi similare care au mai multe atribute comune se pot crea superentităţi. Aceste superentităţi conţin atributele comune, iar atributele speciale sunt asignate la subentităţi. Pentru noile superentităţi se introduc chei primare artificiale.

4. Specializare. După valorile unor atribute clasificatoare se pot determina clase. Un grup de subentităţi reciproc exclusive defineşte o clasă. Clasele se aliniază în desen vertical.

5. Într-o diagramă E/R se pot defini relaţii recursive. 6. Unele relaţii sunt relative la două entităţi şi le numim de tip 2, iar

dacă relaţiile implică mai mult de două entităţi, le vom numi de tip 3. Trei relaţii de tip 2 sunt diferite de o relaţie de tip 3. Rupând o relaţie de tip 3 în trei relaţii de tip 2, pot apărea informaţii incorecte.

7. Trebuie excluse din model relaţiile indirecte deoarece ele pot conduce la redundanţă în baza de date.

8. Atributele derivabile trebuie eliminate şi introduse expresii prin care aceste atribute pot fi calculate.

9. Relaţie sau atribut? Dacă un atribut al unei entităţi reprezintă cheia primară a unei alte entităţi, atunci el referă o relaţie (cod_departament în tabelul SALARIAT).

10. Entitate sau relaţie? Se cercetează cheia primară. Dacă aceasta combină cheile primare a două entităţi, atunci este vorba de o relaţie. (cheia primară a relaţiei asociat_la combină cod_salariat cu nr_proiect, prin urmare, SALARIAT_asociat la_PROIECT va defini o relaţie şi nu o entitate).

Page 64: CURS BD Combinat

5

11. Un atribut indirect este inoportun. El nu descrie real relaţia sau entitatea. Prin urmare, atributele indirecte trebuie reasignate. De fapt, un atribut indirect este un caz special de relaţie indirectă care trebuie eliminată pentru că introduce redundanţă în date (numărul clădirii în care lucrează un salariat este un atribut al entităţii DEPARTAMENT şi nu este o caracteristică a entităţii SALARIAT).

12. Există atribute opţionale, a căror valoare este uneori necunoscută, alteori neaplicabilă. Aceste atribute trebuie introduse la subentităţi (comisionul pentru deplasare şi zona de lucru sunt atribute specifice unui agent teritorial şi trebuie introduse la subentitatea AGENT_TERITORIAL).

Algoritmul pentru proiectarea diagramei entitate-relaţie: 1. identificarea entităţilor din cadrul sistemului analizat; 2. identificarea relaţiilor dintre entităţi şi stabilirea cardinalităţii; 3. identificarea atributelor aferente entităţilor şi asocierilor dintre

entităţi; 4. stabilirea atributelor de identificare a entităţilor (stabilirea

cheilor).

Diagrama E/R.

conduce lucreaza_in

apartine_la

PROIECT nr_proiect descriere buget_alocat

SARCINA nr_proiect nr_sarcina data_inceperii stare

DEPARTAMENT cod_departament nume nr_cladire

AGENT_TERITORIAL zona comision

PROGRAMATOR limbaj nivel

SALARIAT cod_salariat nume job_cod

atasat_la

data_initiala functia 1

M(0) M(0)

1(0)

1(0)

ISA

1 1(0)

ISA

1

1(0)

M(0)

1

1

M(1)

1(0)

casatorit

Page 65: CURS BD Combinat

6

Modelul EER (modelul E/R extins) = Diagrama E/R + concepte aditionale (subclasă, superclasă, moştenire, specializare, generalizare). Gestiunea activităţilor de împrumut dintr-o bibliotecă

S-a presupus (restrictiv) că într-o zi un cititor nu poate împrumuta, de mai multe ori, aceeaşi carte. Modelul prezintă anomalii (de exemplu, cheia primară de la entitatea carte)! A fost gândit în această manieră cu scop pur didactic. Entităţile şi relaţiile care intervin în acest model sunt următoarele:

1. CARTE (entitate independentă) – orice carte care se găseşte în inventarul bibliotecii. Cheia primară este atributul codel.

2. CITITOR (entitate independentă) – orice cititor care poate împrumuta cărţi. Cheia primară este atributul codec.

3. DOMENIU (entitate independenta) – domeniul căruia îi aparţine o carte. Cheia primară este atributul coded.

4. IMPRUMUTA – relaţie având cardinalitatea m:m care leagă entităţile CITITOR şi CARTE.

5. APARTINE – relaţie care leagă atributele CARTE şi DOMENIU. Relaţia are cardinalitatea maximă m:1, iar cardinalitatea minimă 1:1.

CITITOR codec# nume dep

CARTE codel# titlu autor pret nrex

DOMENIU coded# intdom

imprumuta

apartine

M(1) M(0)

M(0) 1

Page 66: CURS BD Combinat

7

Gestiunea activităţilor de editare dintr-o editură Se analizeaza activitatea dintr-o editură referitoare la culegerea textelor, realizarea elementelor grafice, machetarea unor publicaţii.

1

Gestiunea activităţilor unei firme de construcţii

Baza de date construită prin acest model, furnizează informaţii legate de obiective de execuţie, investitori, executanţi, şantiere, contracte etc. necesare unui manager al unei firme de construcţii

SALARIAT cod_salariat# nume job tip

GRAFICIAN tip

TEHNOREDACTOR tip_editor

REDACTOR_SEF experienta

FRAME nr_publicatie# nr_capitol# nr_frame#

CAPITOL nr_publicatie# nr_capitol#

PUBLICATIE nr_publicatie# stil limba

1

1(0)

ISA

1

1(0)

ISA

1 1(0)

ISA

M(1) M(0)

scrie

M(1)

1

cuprinde

1 M(0) coordoneaza

include

1 M(0)

realizează

M(0)

1

Page 67: CURS BD Combinat

8

Tabelele din cursurile Oracle Education. Tabelele emp, dept, salgrade modelează gestiunea salariaţilor unei firme. Tabelul emp(empno#, ename, job, mgr, hiredate, sal, com, deptno) conţine informaţii despre salariaţii unei firme. Pentru fiecare salariat sunt definite următoarele atribute: empno: codul salariatului; ename: numele salariatului; job: funcţia; mgr: codul şefului; hiredate: data angajării; sal: salariul; com: comisionul; deptno: codul departamentului în care lucrează. Tabelul dept (deptno#, dname, loc) conţine informaţii despre departamentele în care lucrează salariaţii. Atributele sale reprezintă: deptno: codul departamentului; dname: numele departamentului; loc: localitatea unde funcţionează departamentul. Tabelul salgrade(grade#, losal, hisal) conţine informaţii despre grilele de salarizare. Atributele tabelului au următoarea semnificaţie: grade: codul grilei de salarizare; losal: limita inferioară a grilei de salarizare; hisal: limita superioară a grilei de salarizare.

M(1)

CONTRACTANT cod_contractant# adresa telefon cont banca

SUBANTREPENOR nume nume_adm functie_adm

LUCRARE cod_obiectiv# cod_lucrare# adresa

SANTIER nr_santier# specialitate sef

tip_contractant

PERS_FIZICA nume prenume bi

PERS_JURIDICA tip_juridic nume functie

ISA

ISA

ISA 1 1(0)

1

M(0)

executa

executa

1 M(1)

OBIECTIV_ INVESTITIE cod_obiectiv# denumire adresa

M(1)

necesita

1

M(1) 1

investeste_in

ISA 1 1(0)

atasat_la

1

1

CONTRACT nr_contract# tip_contract data_avans 1

incheie

INVESTITOR tip_investitor

Page 68: CURS BD Combinat

9

Ordonarea informaţiilor cu privire la descoperirile de monede antice din Romania

petrecut_in gasita_in stantata_cu publicata inclusa_in pastrata_la STANŢA (nr_stanţă, împărat emitent, valoare nominală, an emitere, monetăria, legenda de pe avers, legenda de pe revers) == > atribute ale entităţii STANTA Completaţi cardinalitatea!

Evidenţa şcolilor de şoferi din Romania

Completaţi relaţiile (lucreaza_la, conduce, sustine, asista, instruieste) dintre entităţi şi specificaţi cardinalitatea!

PUNCT EVENIMENT

STANTA MONEDA

TEZAUR MUZEU

ARTICOL

SCOALA cod_scoala#

CLIENT cod_client#

INSTRUCTOR cod_instructor#

MASINA cod_masina#

EXAMEN cod_examen#

EXAMINATOR cod_examinator#

Page 69: CURS BD Combinat

10

Campionatele de fotbal ale diferitelor ţări

M(1) sustine M(1) 2 joaca M(1) M(1) apartine_de 1 M(1) atasata_la 1

ECHIPA Cod_echipa# Nume Oras

SPONSOR Cod_sponsor# Nume

MECI Tara# Nr_etapa# Cod_meci#

ETAPA Tara Nr_etapa

CAMPIONAT Tara#

Page 70: CURS BD Combinat

11

Modelul relaţional Modelul relaţional a fost conceput şi dezvoltat de E.F. Codd. El este

un model formal de organizare conceptuală a datelor, destinat reprezentării legăturilor dintre date, bazat pe teoria matematică a relaţiilor. Modelul relaţional este alcătuit numai din relaţii şi prin urmare, orice interogare asupra bazei de date este tot o relaţie.

Calităţi: • este simplu; • riguros din punct de vedere matematic; • nu este orientat spre sistemul de calcul.

Modalităţi pentru definirea unui SGBD relaţional: • prezentarea datelor în tabele supuse anumitor operaţii de tip

proiecţie, selecţie, reuniune, compunere, intersecţie etc. • un sistem de baze de date ce suportă un limbaj de tip SQL –

Structured Query Language; • un sistem de baze de date care respectă principiile modelului

relaţional introdus de E.F. Codd.

Caracteristicile unui model relaţional: • structura relaţională a datelor; • operatorii modelului relaţional; • regulile de integritate care guvernează folosirea cheilor în model.

Aceste trei elemente corespund celor trei componente ale ingineriei software: informaţie, proces, integritate.

Structura datelor Definirea noţiunilor de domeniu, relaţie, schemă relaţională, valoare

null şi tabel vizualizare (view). Conceptele utilizate pentru a descrie formal, uzual sau fizic

elementele de bază ale organizării datelor sunt date în următorul tabel:

Formal Uzual Fizic relaţie tuplu atribut domeniu

tablou linie coloană tip de dată

fişier înregistrare câmp tip de dată

Page 71: CURS BD Combinat

12

Domeniu – mulţime de valori care poate fi definită fie enumerând elementele componente, fie definind o proprietate distinctivă a domeniului valorilor.

Fie D1, D2, ..., Dn domenii finite, nu neapărat disjuncte. Produsul cartezian D1 × D2 × ... × Dn al domeniilor D1, D2, ..., Dn este definit de mulţimea tuplurilor (V1, V2, ..., Vn), unde V1 ∈ D1, V2 ∈ D2, ..., Vn ∈ Dn. Numărul n defineşte aritatea tuplului.

O relaţie R pe mulţimile D1, D2, ..., Dn este o submulţime a produsului cartezian D1 × D2 × ... × Dn, deci este o mulţime de tupluri. Caracteristicile unei relaţii comentat curs!

Caracteristicile unei relatii: • are o denumire unica; • fiecare celula contine o valoare atomica; • fiecare atribut are nume unic; • toate valorile unui atribut apartin aceluiasi domeniu; • ordinea atributelor nu are importanta; • nu exista dubluri ale tuplurilor; • teoretic, ordinea tuplurilor nu are importanta. Definirea unei relaţii se referă la mulţimi care variază în timp. Pentru a

caracteriza o relaţie este necesară existenţa un element invariant în timp: structura relaţiei (schema relaţională). Mulţimea numelor atributelor corespunzătoare unei relaţii R defineşte schema relaţională a relaţiei respective. Vom nota schema relaţională prin R(A1, A2, ..., An). Exemplu!

Putem reprezenta o relaţie printr-un tabel bidimensional în care fiecare linie corespunde unui tuplu şi fiecare coloană corespunde unui domeniu din produsul cartezian. O coloană corespunde de fapt unui atribut. Numărul atributelor defineşte gradul (aritatea) relaţiei, iar numărul de tupluri din relaţie defineşte cardinalitatea relaţiei.

Exemplu (crearea unui tabel în SQL): CREATE TABLE salariat ( cod_salariat SMALLINT, nume VARCHAR(25), prenume VARCHAR(20), sex CHAR(1), salariu INTEGER, sot SMALLINT, job_cod VARCHAR(6), cod_departament SMALLINT );

Page 72: CURS BD Combinat

13

Când se inserează tupluri într-o relaţie, de multe ori un atribut este necunoscut sau neaplicabil. Pentru a reprezenta acest atribut a fost introdusă o valoare convenţională în relaţie, şi anume valoarea null.

Tabelul vizualizare (view, filtru, relaţie virtuală, vedere) constituie un filtru relativ la unul sau mai multe tabele, care conţine numai informaţia necesară unei anumite abordări sau aplicaţii.

Vizualizarea este virtuală deoarece datele pe care le conţine nu sunt în realitate memorate într-o bază de date. Este memorată numai definiţia vizualizării. Vizualizarea nu este definită explicit, ca relaţiile de bază, prin mulţimea tuplurilor componente, ci implicit, pe baza altor relaţii prin intermediul unor expresii relaţionale. Stabilirea efectivă a tuplurilor care compun vizualizarea se realizează prin evaluarea expresiei atunci când utilizatorul se referă la acest tabel.

Exemplu (crearea unei vizualizări în SQL): CREATE VIEW programator(nume,departament) AS SELECT nume,cod_departament FROM salariat WHERE job_cod=’programator’;

Reguli de integritate aserţiuni pe care datele conţinute în baza

de date trebuie să le satisfacă. Trebuie făcută distincţia între: • regulile structurale inerente modelării datelor; • regulile de funcţionare specifice unei aplicaţii particulare.

Există trei tipuri de constrângeri structurale (de cheie, de referinţă, de entitate) ce constituie mulţimea minimală de reguli de integritate pe care trebuie să le respecte un SGBD relaţional. Restricţiile de integritate minimale sunt definite în raport cu noţiunea de cheie a unei relaţii.

O mulţime minimală de atribute ale căror valori identifică unic un tuplu într-o relaţie reprezintă o cheie pentru relaţia respectivă. Fiecare relaţie are cel puţin o cheie. Una dintre cheile candidat va fi aleasă pentru a identifica efectiv tupluri şi ea va primi numele de cheie primară. Cheia primară nu poate fi reactualizată. Atributele care reprezintă cheia primară sunt fie subliniate, fie urmate de semnul #.

O cheie identifică linii şi este diferită de un index care localizează liniile. O cheie secundară este folosită ca index pentru a accesa tupluri. Un grup de atribute din cadrul unei relaţii care conţine o cheie a relaţiei poartă numele de supercheie.

Page 73: CURS BD Combinat

14

Fie schemele relaţionale R1(P1, S1) şi R2(S1, S2), unde P1 este cheie primară pentru R1, S1 este cheie secundară pentru R1, iar S1 este cheie primară pentru R2. În acest caz, vom spune că S1 este cheie externă (cheie străină) pentru R1.

Modelul relaţional respectă trei reguli de integritate structurală. Regula 1 – unicitatea cheii. Cheia primară trebuie să fie unică şi

minimală. Regula 2 – integritatea entităţii. Atributele cheii primare trebuie

să fie diferite de valoarea null. Regula 3 – integritatea referirii. O cheie externă trebuie să fie ori

null în întregime, ori să corespundă unei valori a cheii primare asociate.

Proiectarea modelului relaţional (exemple curs!)

Transformarea entităţilor Entităţile independente devin tabele independente. Cheia

primară nu conţine chei externe. Entităţile dependente devin tabele dependente. Cheia primară a

entităţilor dependente conţine cheia primară a entităţii de care depinde (cheie externă) plus unul sau mai multe atribute adiţionale.

Subentităţile devin subtabele. Cheia externă se referă la supertabel, iar cheia primară este această cheie externă (cheia primară a subentităţii PROGRAMATOR este cod_salariat care este o cheie externă).

Transformarea relaţiilor Relaţiile 1:1 şi 1:n devin chei externe. Relaţia conduce devine

coloană în tabelul DEPARTAMENT, iar relaţia lucreaza_in devine coloană în tabelul SALARIAT. Simbolul „ד indică plasamentul cheii externe, iar simbolul „ד exprimă faptul că această cheie externă este conţinută în cheia primară. Relaţia 1:1 plasează cheia externă în tabelul cu mai puţine linii.

Relaţia m:n devine un tabel special, numit tabel asociativ, care are două chei externe pentru cele două tabele asociate. Cheia primară este compunerea acestor două chei externe plus eventuale coloane adiţionale. Tabelul se desenează punctat.

Page 74: CURS BD Combinat

15

Relaţiile de tip trei devin tabele asociative. Cheia primară este compunerea a trei chei externe plus eventuale coloane adiţionale.

Transformarea atributelor Un atribut singular devine o coloană. Atributele multiple devin tabele dependendente ce conţin cheia

primară a entităţii şi atributul multiplu. Cheia primară este o cheie externă, plus una sau mai multe coloane adiţionale.

Entităţile devin tabele, iar atributele lor devin coloane în aceste tabele. Ce devin atributele relaţiilor? Pentru relaţii 1:1 şi 1:n, atributele relaţiilor vor aparţine tabelului care conţine cheia externă, iar pentru relaţii m:n şi de tipul trei, atributele vor fi plasate în tabelele asociative.

conduce lucreaza_in apartine_la atasat_la cod_salariat# nr_proiect#

Cele patru tipuri de tabele (independente, dependente, subtabele şi asociative) se deosebesc prin structura cheii primare.

SALARIAT cod_salariat#

DEPARTAMENT cod_departament#

PROIECT nr_proiect#

SARCINA nr_proiect# nr_sarcina#

SALARIAT cod_salariat#

PROIECT nr_proiect#

SALARIAT cod_salariat#

TELEFON cod_salariat# nr_telefon#

Page 75: CURS BD Combinat

16

Tabel Reprezintă Cheie primară Independent entitate independentă nu conţine chei externe Subtabel subentitate o cheie externă

Dependent entitate dependentă o cheie externă şi una sau mai multe coloane adiţionale atribute multiple

Asociativ relaţie m:n două sau mai multe chei externe şi (opţional) coloane adiţionale relaţii de tip 3

Diagrama conceptuală pentru proiectarea modelului relaţional

comentat a fost construită din diagrama E/R prin adăugarea tabelelor asociative şi prin marcarea cheilor externe.

Schemele relaţionale corespunzătoare acestei diagrame conceptuale

sunt următoarele: – SALARIAT(cod_salariat#, nume, prenume, sex, job_cod, cod_sot,

forma_plata, nr_depart);

PROIECT nr_proiect# descriere buget_alocat

SARCINA nr_proiect# nr_sarcina# data_inceperii stare DEPARTAMENT

cod_departament# nume nr_cladire

AGENT_TERITORIAL zona comision

PROGRAMATOR limbaj nivel

SALARIAT cod_salariat# salariu nume sex

job_cod

conduce lucreaza_in

apartine_la

ATASAT_LA cod_salariat# nr_proiect# functie

TELFON cod_salariat# nr_telefon#

casatorit

Page 76: CURS BD Combinat

17

– DEPARTAMENT(cod_departament#, nume, numar_cladire, cod_sal);

– ATASAT_LA(cod_salariat#, nr_proiect#, functia); – PROIECT(nr_proiect#, descriere, buget_alocat); – SARCINA(nr_proiect#, nr_sarcina, data_inceperii, stare); – AGENT_TERITORIAL(cod_salariat#, zona, comision); – PROGRAMATOR(cod_salariat#, limbaj, nivel); – TELEFON(cod_salariat#, nr_telefon#).

Gestiunea activităţilor unei firme de construcţii

CONTRACTANT(cod_contractant#, adresa, telefon, cont, banca, tip_contractant); SUBANTREPRENOR(cod_contractant#, nume, nr_reg_comert, nume_adm, functie_adm); INVESTITOR(cod_contractant#, tip_investitor); PERS_FIZICA(cod_contractant#, nume, prenume, bi); PERS_JURIDICA(cod_contractant#, tip_juridic, nume, reprez_legal, functie); CONTRACT(nr_contract#, tip_contract, data_incheiere, garantie, val_investitie, durate_executie, cont, banca, perioada, avans, data_avans, cod_contractant); SANTIER(nr_santier#, specialitate, sef); OBIECTIV_INVESTITIE(cod_obiectiv#, denumire, adresa, adc, nr_cert_urb, nr_aut_constr, nr_contract, cod_contractant); LUCRARE(cod_lucrare#, cod_obiectiv#, tip_lucrare, nume, data_inc, data_sf, nr_santier, cod_contractant);

Page 77: CURS BD Combinat

18

SUBANTREPENOR nume nume_adm funcţie_adm

LUCRARE cod_lucrare# cod_obiectiv#

ŞANTIER nr_şantier# specialitate şef

CONTRACTANT

tip_contractant

adresa telefon cont banca

cod_contractant#

OBIECTIV_INVESTITIE cod_obiectiv# denumire adresa

CONTRACT nr_contract# tip_contract data_avans

INVESTITOR tip_investitor

PERS_FIZICA

nume prenume bi

PERS_JURIDICA

tip_juridic nume functie

incheie

investeste_in

atasat_la

necesita

executa executa

Page 78: CURS BD Combinat

19

Gestiunea activităţilor de editare dintr-o editură

SALARIAT(cod_salariat#, nume, prenume, vechime, salariu, job); GRAFICIAN(cod_salariat#, tip); TEHNOREDACTOR(cod_salariat#, tip_platforma, tip_editor, viteza); REDACTOR_SEF(cod_salariat#, experienta); LIMBA(cod_salariat#, limba_cunos#); TELEFON(cod_salariat#, nr_telefon#); REALIZEAZA(cod_salariat#, nr_frame#, nr_publicatie#, nr_capitol#, data_inc, data_lim); FRAME(nr_frame#, nr_publicatie#, nr_capitol#, tip, dim, format); CAPITOL(nr_publicatie#, nr_capitol#, dimensiune, cod_salariat); PUBLICATIE(nr_publicatie#, stil, beneficiar, autor, cod_salariat, cost, titlu, limba).

SALARIAT

cod_salariat# nume

GRAFICIAN tip

TEHNOREDACTOR tip_editor

REDACTOR_SEF experienta

REALIZEAZA cod_salariat# nr_publicatie# nr_capitol# nr_frame#

FRAME nr_publicatie# nr_capitol# nr_frame# tip

CAPITOL nr_publicatie# nr_capitol# dimensiune

PUBLICATIE nr_publicatie# stil

TELEFON cod_salariat# nr_telefon#

LIMBA cod_salariat# limba_cun#

job

cuprinde coordoneaza

scrie

include

Page 79: CURS BD Combinat

20

Algebra relaţională Limbajul de definire a datelor (LDD) precizează entităţile, relaţiile

dintre ele, atributele, structura atributelor, cheile, constrângerile, prin urmare defineşte structura obiectelor bazei de date (schema bazei).

Limbajul de prelucrare a datelor (LMD) dintr-o bază de date relaţionale cuprinde aspecte referitoare la introducerea, eliminarea, modificarea şi căutarea datelor.

• Introducerea datelor – permite adăugarea de tupluri la o relaţie. Tuplurile pot fi introduse de utilizator sau pot fi obţinute din alte relaţii existente în baza de date.

• Eliminarea datelor – permite ştergerea tuplurilor ce satisfac condiţii date.

• Modificarea datelor – permite reactualizarea tuplurilor ce satisfac condiţii date cu noi valori ale atributelor sau cu rezultate ale unor operaţii aritmetice efectuate asupra unor valori existente.

• Căutarea datelor – permite găsirea tuplurilor sau a unor părţi ale tuplurilor ce satisfac condiţii date.

Modelul relaţional oferă două mulţimi de operatori pe relaţii: • algebra relaţională (filtrele se obţin aplicând operatori specializaţi

asupra uneia sau mai multor relaţii din cadrul bazei relaţionale); • calculul relaţional (filtrele se obţin cu ajutorul unor formule

logice pe care tuplurile rezultatului trebuie să le satisfacă). Algebra relaţională a fost introdusă de E.F. Codd ca o mulţime de

operaţii formale acţionând asupra unor relaţii şi având ca rezultat alte relaţii. Baza teoretică pentru limbajele de interogare relaţionale o constituie operatorii introduşi de Codd pentru prelucrarea relaţiilor.

Operatorii modelului relaţional definesc operaţiile care se pot efectua asupra relaţiilor în scopul realizării funcţiilor de prelucrare asupra BD.

Operatorii sunt numai pentru citire (nu actualizeaza operanzi)!!! Scopul fundamental al algebrei relationale este de a permite scrierea

expresiilor relationale. Expresiile servesc ca o reprezentare de nivel superior, simbolică, a intenţiilor utilizatorului şi pot fi supuse unei diversităţi de reguli de transformare (optimizare).

Relaţiile sunt închise faţă de algebra relaţională (operanzii şi

Page 80: CURS BD Combinat

21

rezultatele sunt relaţii ieşirea unei operaţii poate deveni intrare pentru alta) posibilitatea imbricării expresiilor în algebra relaţională).

Operatorii algebrei relaţionale sunt: • operatori tradiţionali pe mulţimi (UNION, INTERSECT,

PRODUCT, DIFFERENCE); • operatori relaţionali speciali (PROJECT, SELECT, JOIN,

DIVISION). Calculul relaţional reprezintă o adaptare a calculului predicatelor la

domeniul bazelor de date relaţionale. Ideea de bază este de a identifica o relaţie cu un predicat. Pe baza unor predicate iniţiale, prin aplicarea unor operatori ai calculului cu predicate (conjuncţia, disjuncţia, negaţia, cuantificatorul existenţial şi cel universal) se pot defini noi relaţii.

Calculul relaţional poate să fie orientat pe tupluri sau orientat pe domenii.

Echivalenţa dintre algebra relaţională şi calculul relaţional a fost demonstrată de J.D.Ullman. Această echivalenţă arată că orice relaţie posibil de definit în algebra relaţională poate fi definită şi în cadrul calcului relaţional, şi reciproc.

Operatorii (unari sau binari) algebrei relaţionale realizează următoarele funcţii: • SELECT (selecţie) – extrage tupluri ce satisfac o condiţie specificată; • PROJECT (proiecţie) – extrage atributele specificate; • DIFFERENCE (diferenţă) – extrage tupluri care apar într-o relaţie, dar

nu apar în cealaltă; • PRODUCT (produs cartezian) – generează toate perechile posibile de

tupluri, primul element al perechii fiind luat din prima relaţie, iar cel de-al doilea element din cealaltă relaţie;

• UNION (reuniune) – reuneşte două relaţii; • INTERSECT (intersecţie) – extrage tupluri care apar în ambele relaţii; • DIVISION (diviziune) – extrage valorile atributelor dintr-o relaţie, care

apar în toate valorile atributelor din cealaltă relaţie; • JOIN (compunere) – extrage tupluri din mai multe relaţii corelate: • NATURAL JOIN (compunere naturală) – combină tupluri din două

relaţii, cu condiţia ca atributele comune să aibă valori identice; • SEMI-JOIN (semi-compunere) – selectează tupluri ce aparţin unei

singure relaţii, care sunt corelate cu tupluri din cea de a doua relaţie;

Page 81: CURS BD Combinat

22

• Θ-JOIN (Θ-compunere) – combină tupluri din două relaţii (nu neaparat corelate), cu condiţia ca valorile atributelor specificate să satisfacă o anumită condiţie;

• OUTER JOIN (compunere externă) – combină tupluri din două relaţii, astfel încât condiţiile de corelare să fie satisfăcute. Tuplurile din orice relaţie care nu satisfac aceste condiţii sunt completate cu valori null.

Pentru operatorii UNION, INTERSECT şi DIFFERENCE, se presupune că sunt aplicaţi numai la relaţii având aceeaşi aritate, iar ordinea (nu numele) atributelor este aceeaşi.

Operatorul PROJECT Proiecţia este o operaţie unară care elimină anumite atribute ale unei

relaţii producând o submulţime „pe verticală“ a acesteia. Suprimarea unor atribute poate avea ca efect apariţia unor tupluri duplicate, care trebuie eliminate.

Prin proiecţie se construieşte dintr-o relaţie R, o nouă relaţie: a) ştergând din R atributele care nu sunt menţionate în parametrii

proiecţiei; b) eliminând dublurile care apar după ştergere. Pentru a reprezenta operatorul proiecţie sunt utilizate diferite notaţii: ΠA1, ..., Am (R) PROJECT (R, A1, ..., Am) R[A1, ..., Am] unde A1, A2, ..., Am sunt parametrii proiecţiei relativ la relaţia R. Exemplu. Să se obţină o listă ce conţine numele, prenumele şi sexul

angajaţilor. 1. Proiecţie în algebra relaţională: Rezultat = PROJECT(SALARIAT, nume, prenume, sex) 2. Proiecţie cu dubluri în SQL: SELECT nume, prenume, sex FROM salariat;

3. Proiecţie fără dubluri în SQL: SELECT DISTINCT nume, prenume, sex FROM salariat;

Page 82: CURS BD Combinat

23

Operatorul SELECT Selecţia (restrictia) este o operaţie unară care produce o submulţime

pe „orizontală“ a unei relaţii R. Această submulţime se obţine prin extragerea tuplurilor din R care satisfac o condiţie specificată.

Sunt utilizate diferite notaţii: σcondiţie(R) R[condiţie] SELECT(R, condiţie) RESTRICT(R, condiţie). Exemplu. Să se obţină informaţii complete despre angajaţii de sex

masculin. 1. Selecţie în algebra relaţională: Rezultat = SELECT(SALARIAT, sex = ‘m’) 2. Selecţie în SQL: SELECT * FROM salariat WHERE sex = ’m’;

Operatorul UNION Reuniunea a două relaţii R şi S este mulţimea tuplurilor aparţinând

fie lui R, fie lui S, fie ambelor relaţii. Sunt utilizate notaţiile: R ∪ S UNION(R, S) OR(R, S) APPEND(R, S). Exemplu. Să se obţină lista cu numele persoanelor fizice şi a

subantreprenorilor. SELECT nume FROM subantreprenor UNION SELECT nume FROM pers_fizica;

Page 83: CURS BD Combinat

24

Operatorul DIFFERENCE Diferenţa a două relaţii R şi S este mulţimea tuplurilor care aparţin

lui R, dar nu aparţin lui S. Diferenţa este o operaţie binară necomutativă care permite obţinerea tuplurilor ce apar numai într-o relaţie.

Sunt utilizate diferite notaţii: R – S DIFFERENCE(R, S) REMOVE(R, S) MINUS(R, S). Exemplu. Să se obţină lista cu numărul contractului, tipul

contractului, valoarea investiţiei şi durata lucrării pentru contractele de subantrepriză pentru care valoarea investiţiei nu depăşeşte 60000$.

1. Diferenţă în algebra relaţională: R=PROJECT(SELECT(CONTRACT, tip_contract=T), nr_contract, tip_contract, val_investitie, durata_lucrare); S=PROJECT(SELECT(CONTRACT, val_investitie > 60000), nr_contract, tip_contract, val_investitie, durata_lucrare); Rezultat = DIFFERENCE(R, S) 2. Diferenţa în SQL: SELECT nr_contract,tip_contract, val_investitie,durata_lucrare FROM contract WHERE tip_contract MINUS SELECT nr_contract,tip_contract, val_investitie,durata_lucrare FROM contract WHERE val_investitie>60000;

Evident diferenţa se poate referi la tabele diferite! Implementaţi cererea prin care se listează toate oraşele în care se află o filială, dar nici o proprietate.

Operatorul INTERSECT Intersecţia a două relaţii R şi S este mulţimea tuplurilor care aparţin

şi lui R şi lui S. Operatorul INTERSECT este un operator binar, comutativ, derivat:

Page 84: CURS BD Combinat

25

R ∩ S = R – (R – S)

R ∩ S = S – (S – R). Sunt utilizate diferite notaţii: INTERSECT(R, S) R ∩ S AND(R, S). În anumite dialecte SQL există operator special (INTERSECT), care

realizează această operaţie. Operatorii INTERSECT şi DIFFERENCE pot fi simulaţi în SQL (în cadrul comenzii SELECT) cu ajutorul opţiunilor EXISTS, NOT EXISTS, IN, != ANY.

Exemplu. Utilizând tabelele agent_teritorial şi programator să se obţină lista codurilor salariaţilor care sunt programatori, dar care lucrează şi ca agenţi teritoriali.

1. Intersecţie în algebra relaţională: R = PROJECT(AGENT_TERITORIAL, cod_salariat); S = PROJECT(PROGRAMATOR, cod_salariat), Rezultat = INTERSECT(R, S).

2. Intersecţie în SQL: SELECT cod_salariat FROM agent_teritorial INTERSECT SELECT cod_salariat FROM programator;

3. Simularea intersecţiei în SQL: SELECT cod_salariat

FROM programator p WHERE EXISTS (SELECT cod_salariat FROM agent_teritorial a WHERE p.cod_salariat=a.cod_salariat);

Operatorul PRODUCT Fie R şi S relaţii de aritate m, respectiv n. Produsul cartezian al lui R

cu S este mulţimea tuplurilor de aritate m + n unde primele m componente formează un tuplu în R, iar ultimele n componente formează un tuplu în S.

Sunt utilizate diferite notaţii:

Page 85: CURS BD Combinat

26

R × S PRODUCT(R, S) TIMES(R, S). Exemplu. Să se obţină lista tuturor posibilităţilor de investiţie în

diverse obiective de către o firmă care este persoană juridică. 1. Produs cartezian în algebra relaţională:

R = PROJECT(PERS_JURIDICA, nume, cod_contractant); S = PROJECT(OBIECTIV_INVESTITIE, denumire); Rezultat = PRODUCT(R, S).

2. Produs cartezian în SQL: SELECT cod_contractant, nume, denumire FROM obiectiv_investitie, pers_juridica;

Operatorul DIVISION Diviziunea este o operaţie binară care defineşte o relaţie ce conţine

valorile atributelor dintr-o relaţie care apar în toate valorile atributelor din cealaltă relaţie.

Sunt utilizate diferite notaţii: DIVIDE(R, S) DIVISION(R, S)

R ÷ S. Diviziunea conţine acele tupluri de dimensiune n – m la care, adăugând

orice tuplu din S, se obţine un tuplu din R. Operatorul diviziune poate fi exprimat formal astfel: R(n) ÷ S(m) = {t(n-m) ∀ s ∈ S, (t, s) ∈ R} unde n > m şi S ≠ ∅.

Operatorul DIVISION este legat de cuantificatorul universal (∀) care nu există în SQL. Cuantificatorul universal poate fi însă simulat cu ajutorul cuantificatorului existenţial (∃) utilizând relaţia:

∀x P(x) ≡ ¬ ∃ x ¬ P(x). Prin urmare, operatorul DIVISION poate fi exprimat în SQL prin succesiunea a doi operatori NOT EXISTS.

Exemplu. Să se obţină codurile salariaţilor ataşaţi tuturor proiectelor pentru care s-a alocat un buget egal cu 1000.

1. Diviziune în algebra relaţională:

Page 86: CURS BD Combinat

27

R = PROJECT(ATASAT_LA, cod_salariat, nr_proiect); S = PROJECT(SELECT(PROIECT, buget = 1000), nr_proiect); Rezultat = DIVISION(R, S).

2. Diviziune în SQL: SELECT UNIQUE cod_salariat FROM atasat_la sx WHERE NOT EXISTS

(SELECT * FROM proiect pp

WHERE proiect.buget=’1000’ AND NOT EXISTS (SELECT * FROM atasat_la bb WHERE pp.nr_proiect=bb.nr_proiect AND bb.cod_salariat=sx.cod_salariat));

3. Simularea diviziunii cu ajutorul funcţiei COUNT: SELECT cod_salariat FROM atasat_la WHERE nr_proiect IN (SELECT nr_proiect FROM proiect WHERE buget=1000) GROUP BY cod_salariat HAVING COUNT(nr_proiect)=

(SELECT COUNT(*) FROM proiect WHERE buget=1000);

Operatorul JOIN Operatorul de compunere (uniune) permite regăsirea informaţiei din

mai multe relaţii corelate. Operatorul combină produsul cartezian, selecţia şi proiecţia.

Operatorul NATURAL JOIN Operatorul de compunere naturală (NATURAL JOIN) combină

tupluri din două relaţii R şi S, cu condiţia ca atributele comune să aibă valori identice.

Algoritmul care realizează compunerea naturală este următorul: 1. se calculează produsul cartezian R × S;

Page 87: CURS BD Combinat

28

2. pentru fiecare atribut comun A care defineşte o coloană în R şi o coloană în S, se selectează din R × S tuplurile ale căror valori coincid în coloanele R.A şi S.A (atributul R.A reprezintă numele coloanei din R × S corespunzătoare coloanei A din R);

3. pentru fiecare astfel de atribut A se proiectează coloana S.A, iar coloana R.A se va numi A.

Operatorul NATURAL JOIN poate fi exprimat formal astfel: JOIN(R, S) = Πi1,...,im σ(R.A1 = S.A1)∧ ... ∧(R.Ak = S.Ak)(R × S),

unde A1, ..., Ak sunt atributele comune lui R şi S, iar i1, ..., im reprezintă lista componentelor din R × S (păstrând ordinea iniţială) din care au fost eliminate componentele S.A1, ..., S.Ak.

Exemplu. Să se obţină informaţii complete despre angajaţi şi departamentele în care lucrează.

1. Operatorul de compunere naturală în algebra relaţională: Rezultat = JOIN(SALARIAT, DEPARTAMENT).

2. Operatorul de compunere naturală în SQL: SELECT * FROM salariat, departament WHERE nr_depart = cod_departament;

Operatorul θ-JOIN

Operatorul θ-JOIN combină tupluri din două relaţii (nu neapărat corelate) cu condiţia ca valorile atributelor specificate să satisfacă o anumită condiţie specificată explicit în cadrul operaţiei.

Operatorul θ-JOIN este un operator derivat, fiind o combinaţie de produs scalar şi selecţie:

JOIN(R, S, condiţie) = σcondiţie (R × S) Exemplu. Să se afişeze pentru fiecare salariat, codul acestuia şi grila

sa de salarizare. SELECT empno, level FROM salgrade, emp WHERE sal BETWEEN losal AND hisal;

Exemplu. Să se obţină informaţii despre contractanţi (codul şi banca) şi obiectivele de investiţie asociate acestora (denumire, număr certificat de urbanizare) cu condiţia ca obiectivele să nu fie la aceeaşi adresă ca şi contractanţii.

Page 88: CURS BD Combinat

29

1. Operatorul θ-JOIN în algebra relaţională: R = PROJECT(CONTRACTANT, cod_contractant, banca); S = PROJECT(OBIECTIV_INVESTITIE, denumire, nr_cert_urb); Rezultat = JOIN(R, S, OBIECTIV_INVESTITIE.adresa <> CONTRACTANT.adresa).

2. Opratorul θ-JOIN în SQL: SELECT cod_contractant,banca, nr_cert_urb, denumire FROM contractant a,obiectiv_investitie b WHERE b.adresa <> a.adresa;

Operatorul SEMI-JOIN Operatorul SEMI-JOIN conservă atributele unei singure relaţii

participante la compunere şi este utilizat când nu sunt necesare toate atributele compunerii. Operatorul este asimetric.

Tupluri ale relaţiei R care participă în compunerea (naturală sau θ-JOIN) dintre relaţiile R şi S.

SEMI-JOIN este un operator derivat, fiind o combinaţie de proiecţie şi compunere naturală sau proiecţie şi θ-JOIN:

SEMIJOIN(R, S) = ΠM (JOIN(R, S)) SEMIJOIN(R, S, condiţie) = ΠM (JOIN(R, S, condiţie)),

unde am notat prin M atributele relaţiei R. Exemplu. Să se obţină informaţii referitoare la persoanele fizice

(nume, buletin) care investesc în obiective cu caracter recreativ. 1. Operatorul SEMI-JOIN în algebra relaţională: R = SELECT(OBIECTIV_INVESTITIE, denumire = ’cabana’ OR denumire = ’casa de vacanta’) S = JOIN(PERS_FIZICA, R) Rezultat = PROJECT(S, nume, buletin). 2. Operatorul SEMI-JOIN în SQL:

SELECT nume,bi FROM pers_fizica a,obiectiv_investitie b WHERE a.cod_contractant = b.cod_contractant AND (denumire=’cabana’)OR (denumire= ’casa

de vacanta’);

Page 89: CURS BD Combinat

30

Operatorul OUTER JOIN Operaţia de compunere externă combină tupluri din două relaţii

pentru care sunt satisfăcute condiţiile de corelare. În cazul aplicării operatorului JOIN se pot pierde tupluri, atunci când există un tuplu în una din relaţii pentru care nu există nici un tuplu în cealaltă relaţie, astfel încât să fie satisfăcută relaţia de corelare.

Operatorul elimină acest inconvenient prin atribuirea valorii null valorilor atributelor care există într-un tuplu din una dintre relaţiile de intrare, dar care nu există şi în cea de-a doua relaţie.

Practic, se realizează compunerea a două relaţii R şi S la care se adaugă tupluri din R şi S, care nu sunt conţinute în compunere, completate cu valori null pentru atributele care lipsesc.

Compunerea externă poate fi: LEFT, RIGHT, FULL. De exemplu, OUTER JOIN LEFT reprezintă compunerea în care tuplurile din R, care nu au valori similare în coloanele comune cu relaţia S, sunt de asemenea incluse în relaţia rezultat.

Exemplu. Să se obţină informaţii referitoare la persoanele fizice care sunt investitori (chiar dacă nu au investit în obiective industriale) şi la obiectivele de investiţie industriale (chiar şi cele care nu sunt construite de persoane fizice).

R = SELECT(OBIECTIV_INVESTITIE, denumire = 'industrial') Rezultat = OUTERJOIN(PERS_FIZICA, R). Operatorii algebrei relaţionale pot fi reprezentaţi grafic cu ajutorul

unor simboluri speciale. curs! Operaţii adiţionale: complement, despicare, închidere tranzitivă.

Funcţii asociate: MIN, MAX, COUNT, AVG, SUM, VAR, STD etc.

Page 90: CURS BD Combinat

31

Evaluarea şi optimizarea interogărilor Procesarea interogărilor O expresie a algebrei relaţionale este constituită din relaţii legate

prin operaţii din algebra relaţională. O expresie se poate reprezenta grafic cu ajutorul unui arbore, numit arbore algebric, în care nodurile corespund operatorilor din cadrul expresiei respective.

Evaluarea unei expresii presupune efectuarea prelucrărilor indicate de operatorii din expresie în ordinea apariţiilor sau în ordinea fixată prin paranteze. Rezultatul evaluării unei expresii este o relaţie derivată din relaţiile menţionate ca operanzi în cadrul expresiei.

Două expresii sunt echivalente, dacă în urma evaluării lor se obţine ca rezultat aceeaşi relaţie.

Exemple referitoare la moduri echivalente de exprimare a unei cereri

(vor fi rezolvate la curs!). 1. Informaţii despre salariaţii care nu contribuie la machetarea nici

unei publicaţii, dar au retribuţia mai mare decât o valoare dată. 2. Codul şi numele subantreprenorilor care au realizat lucrări

specializate la obiective case de vacanţă sau cabane. 3. Codurile şi telefoanele investitorilor, valoarea si durata de execuţie

a investitiilor a caror valoare este între două limite specificate. 4. Perioada de desfăşurare şi preţul ofertelor care încep după 1

ianuarie 2003 şi sunt: • sejururi la munte; • excursii în care autocarele sunt conduse de şoferi angajaţi după 1

mai 1987 şi supravegheate de ghizi ce cunosc limba engleză care au făcut specializare în Suedia.

În majoritatea sistemelor de gestiune, şi în special în cele relaţionale, interfaţa cu utilizatorul este de tip neprocedural. Utilizatorul defineşte datele pe care doreşte să le vizualizeze fără a da algoritmii de acces. Sistemul trebuie să convertească cererea utilizatorului:

• într-o cerere optimală; • în proceduri de acces optimal la datele fizice. Garantarea absolută a performanţelor optime pentru procesorul

limbajului relaţional este imposibilă. Corectă ar fi utilizarea cuvântului „ameliorare“ în locul cuvântului „optimizare“.

Page 91: CURS BD Combinat

32

Evaluarea unei interogări se efectuează în trei etape. Analiza cererii presupune studierea sintactică şi semantică a cererii

pentru a verifica corectitudinea sa şi a simplifica criteriul de căutare.

Ordonanţarea presupune descompunerea cererii într-o mulţime de operaţii elementare şi determinarea unei ordini optimale a acestor operaţii. Operaţiile sunt, în general, cele ale algebrei relaţionale. La sfârşitul etapei se obţine un plan de execuţie pentru cerere.

Execuţia presupune efectuarea (paralel şi/sau secvenţială) operaţiilor elementare furnizate de planul de execuţie pentru a obţine rezultatul cererii.

Presupunem că utilizatorul transmite sistemului de gestiune o cerere

exprimată prin ordine SQL. Pentru a răspunde cererii, SGBD-ul trebuie să înţeleagă cererea utilizatorului. Cererea trebuie să fie corectă sintactic, datele trebuie să fie disponibile utilizatorului şi trebuie localizate analizând diferite drumuri de acces la ele. Aceste funcţii sunt realizate de SGBD cu ajutorul a două module funcţionale care comunică permanent:

• analizorul cererilor, care asigură verificarea sintactică şi semantică a cererii, localizarea datelor implicate în cerere (găsirea adresei blocurilor ce conţin datele), furnizarea planului de execuţie.

• administratorul datelor (executorul), care execută efectiv cererea (primeşte planurile de execuţie furnizate de modulul de optimizare şi le execută). Execuţia presupune căutarea blocurilor ce conţin datele şi transferul blocurilor în memoria cache.

Ideea generală: cerere arbore algebric (nu este unic) plan de executie optimizare

Un plan de execuţie implică o secvenţă de paşi pentru evaluarea cererii (în mod obişnuit, fiecare pas din planul de execuţie corespunde unei operaţii relaţionale) precum şi metoda care va fi folosită pentru evaluarea operaţiei. De obicei, pentru o operaţie relaţională dată, există mai multe metode ce pot fi folosite pentru evaluarea acesteia.

Două planuri de execuţie diferite care au întotdeauna acelaşi rezultat se numesc echivalente. Planuri de execuţie echivalente pot avea diferite costuri. Scopul optimizării cererilor este de a găsi, printre diversele planuri de execuţie echivalente, pe acela de cost minim. Într-un sistem centralizat, costul evaluării unei cereri este suma a două componente, costul I/O (transferuri de date) şi costul CPU (verificare de condiţii, operaţii join etc.).

Page 92: CURS BD Combinat

33

Ordinea de execuţie a operaţiilor O interogare constă dintr-un număr de operaţii. Ordinea în care se

efectuează operaţiile are un rol important în evaluarea costului necesar realizării interogării.

Există două modalităţi de abordare pentru a determina ordinea de execuţie a operaţiilor:

• algebric; • bazat pe estimarea costului. Ambele folosesc o mulţime de reguli care permit transformarea unui

plan de execuţie (reprezentat ca o expresie scrisă în termenii algebrei relaţionale) în altul, echivalent.

Optimizarea cererilor bazată pe algebra relaţională se realizează în două etape:

• se exprimă cererile sub forma unor expresii algebrice relaţionale; • se aplică acestor expresii transformări algebrice care conduc la

expresii echivalente, dar care vor fi executate mai eficient. Procesul de transformare a cererilor se realizează conform unei

strategii de optimizare care poate să fie: • independentă de modul de memorare a datelor (strategie generală); • dependentă de modul de memorare (strategie specifică unui anumit

SGBD). Proprietăţile operatorilor algebrei relaţionale

Proprietatea 1. Comutativitatea operaţiilor de join şi produs cartezian: JOIN(R1, R2) = JOIN(R2, R1)

R1 × R2 = R2 × R1

Proprietatea 2. Asociativitatea operaţiilor de join şi produs cartezian: JOIN(JOIN(R1, R2), R3) = JOIN(R1, JOIN(R2, R3))

(R1 × R2) × R3 = R1 × (R2 × R3)

Proprietatea 3. Compunerea proiecţiilor: ΠA1,...,Am (ΠB1,...,Bn (R)) = ΠA1,...,Am (R),

unde {A1, A2,...,Am } ⊆ {B1, B2,...,Bn}.

Proprietatea 4. Compunerea selecţiilor: σcond1 (σcond2 (R)) = σcond1∧cond2 (R) = σcond2 (σcond1 (R)),

unde am notat prin cond condiţia după care se face selecţia.

Page 93: CURS BD Combinat

34

Proprietatea 5. Comutarea selecţiei cu proiecţia: ΠA1,...,Am (σcond (R)) = σcond (ΠA1,...,Am (R)),

unde condiţia după care se face selecţia implică numai atributele A1,...,Am. Dacă condiţia implică şi atributele B1,...,Bn, care nu aparţin mulţimii

{A1,...,Am}, atunci: ΠA1,...,Am (σcond (R)) = ΠA1,...,Am (σcond (ΠA1,...,Am,B1,...,Bn (R)))

Proprietatea 6. Comutarea selecţiei cu produsul cartezian: Dacă toate atributele menţionate în condiţia după care se face selecţia

sunt atribute ale relaţiei R1, atunci: σcond (R1 × R2) = σcond (R1) × R2

Dacă condiţia este de forma cond1∧cond2 şi dacă cond1 implică numai atribute din R1, iar cond2 implică numai atribute din R2, atunci

σcond (R1 × R2) = σcond1 (R1) × σcond2 (R2) Dacă cond1 implică numai atribute din R1, iar cond2 implică atribute

atât din R1 cât şi din R2, atunci: σcond (R1 × R2) = σcond2 (σcond1 (R1) × R2)

Proprietatea 7. Comutarea selecţiei cu reuniunea: σcond (R1 ∪ R2) = σcond (R1) ∪ σcond (R2)

Proprietatea 8. Comutarea selecţiei cu diferenţa: σcond (R1 – R2) = σcond (R1) – σcond (R2)

Proprietatea 9. Comutarea proiecţiei cu reuniunea: ΠA1,...,Am (R1 ∪ R2) = ΠA1,...,Am (R1) ∪ ΠA1,...,Am (R2)

Proprietatea 10. Comutarea proiecţiei cu produsul cartezian: Dacă A1,...,Am este o listă de atribute ce apar în schemele relaţionale R1

şi R2 şi dacă lista este formată din atribute aparţinând lui R1 (notate prin B1,...,Bn) şi din atribute aparţinând lui R2 (notate prin C1,...,Ck) atunci:

ΠA1,...,Am (R1 × R2) = ΠB1,...,Bn (R1) × ΠC1,...,Ck (R2)

Proprietatea 11. Compunerea proiecţiei cu operaţia join: Dacă A1,...,Am este o listă de atribute ce apar în schemele relaţionale R1

şi R2 şi dacă lista este formată din atribute aparţinând lui R1 (notate prin B1,...,Bn) şi din atribute aparţinând lui R2 (notate prin C1,...,Ck) atunci: ΠA1,...,Am (JOIN(R1,R2,D)) = ΠA1,...,Am (JOIN(ΠD,B1,...,Bn(R1), ΠD,C1,...,Ck(R2),D),

unde am notat prin JOIN(R1, R2, D) operaţia de compunere naturală între R1 şi R2 după atributul comun D.

Page 94: CURS BD Combinat

35

Proprietatea 12. Compunerea selecţiei cu operaţia join: σcond (JOIN (R1, R2, D)) = σcond (JOIN (ΠD,A (R1), ΠD,A (R2), D)),

unde A reprezintă atributele care apar în condiţia după care se face selecţia.

Reguli de optimizare frecvent folosite: Regula de optimizare 1. Selecţiile se execută cât mai devreme

posibil. Motivaţia acestei reguli este că selecţiile reduc substanţial dimensiunea relaţiilor. Regula de transformare 4 poate fi folosită pentru a separa două sau mai multe selecţii în selecţii individuale care pot fi distribuite join-ului sau produsului cartezian folosind comutarea selecţiei cu join-ul.

Regula de optimizare 2. Produsurile carteziene se înlocuiesc cu join-uri, ori de câte ori este posibil. Un produs cartezian între două relaţii este de obicei mult mai scump (ca şi cost) decât un join între cele două relaţii, deoarece primul generează concatenarea tuplurilor în mod exhaustiv şi poate genera un rezultat foarte mare. Această transformare se poate realiza folosind legătura dintre produs cartezian, join şi selecţie.

Regula de optimizare 3. Dacă sunt mai multe join-uri atunci cel care se execută primul este cel mai restrictiv. Un join este mai restrictiv decât altul dacă produce o relaţie mai mică. Se poate determina care join este mai restrictiv pe baza factorului de selectivitate sau cu ajutorul informaţiilor statistice. Algebric, acest lucru se poate realiza folosind regula de transformare 2.

Regula de optimizare 4. Proiecţiile se execută la început pentru a îndepărta atributele nefolositoare. Dacă un atribut al unei relaţii nu este folosit în operaţiile ulterioare atunci trebuie îndepărtat. În felul acesta se va folosi o relaţie mai mică în operaţiile ulterioare. Aceasta se poate realiza folosind comutarea proiecţiei cu join-ul.

Exemple curs!!!

Page 95: CURS BD Combinat

36

Regulile lui Codd Caracteristici ale modelului relaţional:

• nu există tupluri identice; • ordinea liniilor şi a coloanelor este arbitrară; • articolele unui domeniu sunt omogene; • fiecare coloană defineşte un domeniu distinct şi nu se poate repeta în

cadrul aceleiaşi relaţii; • toate valorile unui domeniu corespunzătoare tuturor cazurilor nu mai

pot fi descompuse în alte valori (sunt atomice). Avantajele modelului relaţional:

• fundamentare matematică riguroasă; • independenţă fizică a datelor; • posibilitatea filtrărilor; • existenţa unor structuri de date simple; • realizarea unei redundanţe minime; • supleţe în comunicarea cu utilizatorul neinformatician.

Ca limite ale modelului relaţional putem menţiona:

• rămâne totuşi redundanţă, • ocupă spaţiu, • apar fenomene de inconsistenţă, • nu există mecanisme pentru tratarea optimă a cererilor recursive, • nu lucrează cu obiecte complexe, • nu există mijloace perfecţionate pentru exprimarea constrângerilor de

integritate, • nu realizează gestiunea totala a datelor distribuite, • nu realizează gestiunea cunoştinţelor.

În anul 1985, E.F. Codd a publicat un set de 13 reguli în raport cu

care un sistem de gestiune a bazelor de date poate fi apreciat ca relaţional. Nici un sistem de gestiune a bazelor de date pus în vânzare pe piaţa comercială nu respectă absolut toate regulile definite de Codd, dar acest lucru nu împiedică etichetarea acestor sisteme drept relaţionale.

Page 96: CURS BD Combinat

37

Nu trebuie apreciat un SGBD ca fiind relaţional sau nu, ci măsura în care acesta este relaţional, deci numărul regulilor lui Codd pe care le respectă.

Regula 1 – regula gestionării datelor. Un SGBD relaţional trebuie să fie capabil să gestioneze o bază de date numai prin posibilităţile sale relaţionale.

Regula 2 – regula reprezentării informaţiei. Într-o bază de date relaţională, informaţia este reprezentată la nivel logic sub forma unor tabele ce poartă numele de relaţii.

Regula 3 – regula accesului garantat la date. Fiecare valoare dintr-o bază de date relaţională trebuie să poată fi adresată în mod logic printr-o combinaţie formată din numele relaţiei, valoarea cheii primare şi numele atributului.

Regula 4 – regula reprezentării informaţiei necunoscute. Un sistem relaţional trebuie să permită utilizatorului definirea unui tip de date numit „null“ pentru reprezentarea unei informaţii necunoscute la momentul respectiv.

Regula 5 – regula dicţionarelor de date. Asupra descrierii bazelor de date (informaţii relative la relaţii, vizualizări, indecşi etc.) trebuie să se poată aplica aceleaşi operaţii ca şi asupra datelor din baza de date.

Regula 6 – regula limbajului de interogare. Trebuie să existe cel puţin un limbaj pentru prelucrarea bazei de date.

Regula 7 – regula de actualizare a vizualizării. Un SGBD trebuie să poată determina dacă o vizualizare poate fi actualizată şi să stocheze rezultatul interogării într-un dicţionar de tipul unui catalog de sistem.

Regula 8 – regula limbajului de nivel înalt. Regulile de prelucrare asupra unei relaţii luată ca întreg sunt valabile atât pentru operaţiile de regăsire a datelor, cât şi asupra operaţiilor de inserare, actualizare şi ştergere a datelor.

Regula 9 – regula independenţei fizice a datelor: Programele de aplicaţie şi activităţile utilizatorilor nu depind de modul de depunere a datelor sau de modul de acces la date.

Regula 10 – regula independenţei logice a datelor. Programele de aplicaţie trebuie să fie transparente la modificările de orice tip efectuate asupra datelor.

Regula 11 – regula independenţei datelor din punct de vedere al integrităţii. Regulile de integritate trebuie să fie definite într-un sublimbaj relaţional, nu în programul de aplicaţie.

Page 97: CURS BD Combinat

38

Regula 12 – regula independenţei datelor din punct de vedere al distribuirii. Distribuirea datelor pe mai multe calculatoare dintr-o reţea de comunicaţii de date, nu trebuie să afecteze programele de aplicaţie.

Regula 13 – regula versiunii procedurale a unui SGBD. Orice componentă procedurală a unui SGBD trebuie să respecte aceleaşi restricţii de integritate ca şi componenta relaţională.

Deoarece regulile lui Codd sunt prea severe pentru a fi respectate de un SGBD operaţional, s-au formulat criterii minimale de definire a unui sistem de gestiune relaţional.

Un SGBD este minimal relaţional dacă: • toate datele din cadrul bazei sunt reprezentate prin valori în tabele; • nu există pointeri observabili de către utilizator;

• sistemul suportă operatorii relaţionali de proiecţie, selecţie şi compunere naturală, fără limitări impuse din considerente interne.

Un SGBD este complet relaţional dacă este minimal relaţional şi satisface în plus condiţiile:

• sistemul suportă restricţiile de integritate de bază (unicitatea cheii primare, constrângerile referenţiale, integritatea entităţii).

• sistemul suportă toate operaţiile de bază ale algebrei relaţionale.

NORMALIZAREA RELAŢIILOR În procesul modelării unei baze de date relaţionale, o etapă importantă

o reprezintă normalizarea relaţiilor conceptuale (Codd, 1972), adică obţinerea de relaţii „moleculare“fără a pierde nimic din informaţie pentru a elimina:

• redundanţa; • anomaliile reactualizării informaţiilor. Tehnica normalizării permite obţinerea unei scheme conceptuale

rafinate printr-un proces de ameliorare progresivă a unei scheme conceptuale iniţiale a bazei de date relaţionale. După fiecare etapă de ameliorare, relaţiile bazei de date ating un anumit grad de perfecţiune, deci se află într-o anumită formă normală. Trecerea unei relaţii dintr-o formă normală în alta, presupune eliminarea unei anumit tip de dependenţe nedorite, care sunt transformate în dependenţe admisibile, adică dependenţe care nu provoacă anomalii.

Page 98: CURS BD Combinat

39

Procesul de ameliorare a schemei conceptuale trebuie: • să garanteze conservarea datelor, adică în schema conceptuală

finală trebuie să figureze toate datele din cadrul schemei iniţiale; • să garanteze conservarea dependenţelor dintre date, adică în

schema finală fiecare dependenţă trebuie să aibă determinantul şi determinatul în schema aceleiaşi relaţii;

• să reprezinte o descompunere minimală a relaţiilor iniţiale, adică nici una din relaţiile care compun schema finală nu trebuie să fie conţinută într-o altă relaţie din această schemă.

Există două metode pentru a modela baze de date relaţionale fără anomalii sau pierderi de informaţie.

• Schema descompunerii pleacă de la o schemă relaţională universală ce conţine toate atributele BD. Schema se descompune prin proiecţii succesive în subrelaţii. Descompunerea se opreşte când continuarea ei ar duce la pierderi de informaţie. Algoritmii de descompunere se bazează, în general, pe descrierea formală a dependenţei dintre atribute.

• Schema sintezei pleacă de la o mulţime de atribute independente. Utilizând proprietăţi de semantică şi legături între atribute se pot compune noi relaţii, astfel încât, acestea să nu sufere de anumite anomalii. Algoritmii se bazează, în general, pe teoria grafurilor pentru a reprezenta legătura între atribute.

Dependenţe funcţionale O relaţie universală este o relaţie ce grupează toate atributele care

modelează sistemul real cercetat. Fie E, mulţimea dependenţelor considerate de proiectantul bazei pentru o schemă relaţională sau pentru o relaţie universală. Plecând de la o mulţime de proprietăţi formale ale dependenţelor, proprietăţi considerate drept reguli de deducţie (axiome), poate fi obţinută mulţimea maximală de dependenţe asociate lui E. Această mulţime defineşte închiderea lui E.

Fie E mulţimea dependenţelor unei relaţii şi p1, p2, ..., pr, r ≥ 1, proprietăţi formale ale acestor dependenţe. Dacă există o mulţime E′, astfel încât orice dependenţă a mulţimii E este derivabilă din E′ prin aplicarea proprietăţilor p1, p2, ..., pr, atunci mulţimea E′ defineşte acoperirea lui E pentru proprietăţile p1, p2, ..., pr.

E′ este o acoperire minimală pentru E, dacă nu există nici o submulţime proprie, nevidă a lui E′ care să fie o acoperire pentru E.

Page 99: CURS BD Combinat

40

Evident, E şi E′ au închideri identice, deci dispun de acelaşi potenţial informaţional!

Fie R(A1, A2, ..., An) o schemă relaţională şi fie X, Y submulţimi de atribute ale lui R. X determină funcţional Y sau Y depinde funcţional (FD) de X, dacă pentru orice relaţie r (valoare curentă a lui R) nu există două tupluri care să aibă aceleaşi valori pentru atributele lui X şi să aibă valori diferite pentru cel puţin un atribut din Y. Cu alte cuvinte, o valoare a lui X, determină unic o valoare a lui Y.

Notaţia utilizată pentru desemnarea dependenţei funcţionale este X → Y. X este numit determinant, iar Y este numit determinat (sau dependent). Dependenţa funcţională X → Y este trivială dacă Y ⊆ X.

Comparând toate submulţimile de atribute ale unei relaţii şi determinând legăturile dintre ele, se pot obţine toate dependenţele funcţionale pe care o relaţie le satisface. Această abordare nu este eficientă, consumând mult timp.

Există posibilitatea ca, ştiind anumite dependenţe funcţionale şi utilizând reguli de deducţie, să fie obţinute toate dependenţele funcţionale.

Fie X, Y, Z, W mulţimi de atribute ale unei scheme relaţionale R şi fie următoarele axiome:

Ax1 – reflexivitate. X → X. Mai general, dacă Y ⊆ X, atunci X → Y. Ax2 – creşterea determinantului. Pot fi considerate următoarele formulări echivalente pentru această axiomă.

1. Dacă X → Y şi X ⊆ Z, atunci Z → Y. 2. Dacă X → Y şi W ⊆ Z, atunci X ∪ Z → Y ∪ W. 3. Dacă X → Y atunci X ∪ Z → Y ∪ Z. 4. Dacă X → Y atunci X ∪ Z → Y.

Ax3 – tranzitivitate. Dacă X → Y şi Y → Z, atunci X → Z. O mulţime de axiome este completă dacă şi numai dacă plecând de

la o mulţime de dependenţe E se pot obţine toate dependenţele închiderii lui E, utilizând axiomele mulţimii.

O mulţime de axiome este închisă dacă şi numai dacă plecând de la o mulţime de dependenţe E, nu poate fi dedusă cu ajutorul axiomelor o dependenţă care nu aparţine închiderii lui E. (nu obţin altele!)

Ullman a demonstrat că axiomele Ax1 – Ax3, numite axiomele lui Amstrong, reprezintă o mulţime închisă şi completă de axiome. Consecinţa

Page 100: CURS BD Combinat

41

acestui rezultat este că închiderea lui E reprezintă mulţimea dependenţelor deduse din E, prin aplicarea axiomelor lui Amstrong!!!

Nu toate dependenţele funcţionale sunt folositoare pentru modelarea relaţională. O dependenţă funcţională X → Y se numeşte dependenţă funcţională totală (FT), dacă şi numai dacă nu există nici o submulţime proprie X′ ⊂ X, astfel încât X′ → Y. Dacă există o submulţime proprie X′ ⊂ X, astfel încât X′ → Y, atunci dependenţa funcţională X → Y este parţială. În axioma Ax2, dependenţa Z → Y este o dependenţă funcţională parţială.

În cazul dependenţei funcţionale totale, axiomele lui Amstrong se reduc la o axiomă unică şi anume pseudo-tranzitivitatea:

dacă X → Y şi W ∪ Y → Z, atunci W ∪ X → Z. Această axiomă este o regulă de deducţie completă pentru total

dependenţe: • pseudo-tranzitivitatea implică tranzitivitatea (W = ∅); • reflexivitatea nu poate fi utilizată pentru a obţine dependenţe

totale; • reflexivitatea şi pseudo-tranzitivitatea implică creşterea. Dacă F este o mulţime de dependenţe funcţionale totale, atunci

închiderea pseudo-tranzitivă F+ a acestei mulţimi este reuniunea mulţimilor dependenţelor funcţionale totale care pot fi obţinute din F folosind axioma de pseudo-tranzitivitate.

Două mulţimi de dependenţe funcţionale totale sunt echivalente dacă au închideri pseudo-tranzitive identice. Pentru a modela scheme relaţionale se consideră mulţimi minimale de dependenţe funcţionale totale, capabile să genereze toate închiderile pseudo-tranzitive. Aceste mulţimi definesc acoperiri minimale.

O mulţime de dependenţe funcţionale totale F* asociată unei mulţimi de atribute A defineşte o acoperire minimală dacă satisface următoarele proprietăţi:

• nici o dependenţă funcţională din F* nu este redundantă; • toate dependenţele funcţionale totale între submulţimi ale lui A

sunt în închiderea pseudo-tranzitivă a lui F*. Orice mulţime de dependenţe totale are cel puţin o acoperire minimală.

Alegerea acoperirii minimale este punctul de start în modelarea schemelor relaţionale.

Page 101: CURS BD Combinat

42

Dependenţele funcţionale între atributele bazei pot fi reprezentate grafic. Fie A = {A1, A2, ..., An} o mulţime de atribute şi fie o mulţime de dependenţe funcţionale {Xi → Aj}, unde Xi este o submulţime a lui A.

Graful dependenţelor funcţionale este un graf direcţionat bipartit, definit astfel:

1. pentru fiecare atribut Aj există un singur nod având eticheta Aj; 2. pentru fiecare dependenţă funcţională de forma Ai → Aj, există un

arc de la Ai la Aj; 3. pentru fiecare dependenţă funcţională de forma Xi → Aj, unde

mulţimea Xi este definită de Xi = {Ai1, ..., Aip} cu p > 1, există un nod auxiliar etichetat prin Xi şi o mulţime de arce plecând de la Ai1, ..., Aip pentru a obţine pe Xi şi printr-un arc adiţional de la Xi la Aj. Nodurile Xi se reprezintă prin dreptunghiuri.

Exemplu: 1. Graful dependenţelor funcţionale pentru schema relaţională CONSUMATOR_DE_VIN(W#, localitate, varsta, calitate, regiune, tara, D#, nume, data, cantitate) şi acoperirea minimală. localitate W# calitate varsta regiune tara data cantitate D# nume localitate W# calitate varsta

Page 102: CURS BD Combinat

43

regiune tara data cantitate D# nume

2. Graful dependenţelor funcţionale pentru schema relaţională OBIECTIV_INVESTITIE. Dependentele sunt deduse din regulile impuse de beneficiar! aria_construita denumire nr_certificat_urbanizare cod_obiectiv# adresa nr_aut_construtie nr_contract cod_contractant

Necesitatea normalizării Anomaliile care apar în lucrul cu baza de date se produc datorită

dependenţelor care există între datele din cadrul relaţiilor bazei de date. Dependenţele sunt plasate greşit în tabele!!! Avion

A# nume capacitate localitate 1 AIRBUS 250 PARIS 2 AIRBUS 250 PARIS 3 AIRBUS 250 LONDRA 4 CAR 100 PARIS 5 B707 150 LONDRA 6 B707 150 LONDRA

Constrângere: toate avioanele cu acelaşi nume au aceeaşi capacitate. Datorită dependenţei introduse pot exista: anomalii la inserare,

modificare sau ştergere, redundanţă în date, probleme de reconexiune.

Page 103: CURS BD Combinat

44

1. Redundanţă logică. Cuplul (AIRBUS, 250) apare de trei ori. 2. Anomalie la inserţie. S-a cumpărat un B727 cu 150 locuri. El

poate fi inserat în relaţia AVION doar dacă se defineşte o nouă valoare pentru cheia primară.

3. Anomalie la ştergere. Dacă este ştearsă înregistrarea pentru care A# este 4, atunci se pierde informaţia că un avion CAR are capacitatea 100.

4. Anomalie la modificare. Dacă se modifică capacitatea lui B707 de la 150 la 170, atunci costul modificării este mare pentru a modifica toate înregistrările, iar dacă se modifică doar o înregistrare atunci constrângerea nu va mai fi verificată.

5. Problema reconexiunii. Considerăm schemele relaţionale: AVION1 = PROJECT(AVION, A#, nume) AVION22 = PROJECT(AVION, nume, capacitate, localitate) AVION3 = JOIN(AVION1, AVION2). Se observă că schema AVION3 este diferită de AVION. Apare un tuplu nou: (3, AIRBUS, 250, PARIS).

Anomaliile au apărut datorită dependenţei funcţionale (constrângerii)

introduse anterior!!! Normalizarea are drept scop: • suprimarea redundanţei logice, • evitarea anomaliilor la reactualizare, • rezolvarea problemei reconexiunii. Există o teorie matematică a normalizării al cărei autor este E.F.

Codd. Soluţia: construirea unor tabele standard (forme normale). Normalizarea este procesul reversibil de transformare a unei relaţii, în

relaţii de structură mai simplă. Procesul este reversibil în sensul că nici o informaţie nu este pierdută în timpul transformării. O relaţie este într-o formă normală particulară dacă ea satisface o mulţime specificată de constrângeri.

Procesul normalizării se realizează plecând de la o relaţie universală ce conţine toate atributele sistemului de modelat, plus o mulţime de anomalii. Orice formă normală se obţine aplicând o schemă de descompunere. Există două tipuri de descompuneri.

• Descompuneri ce conservă dependenţele. Această descompunere presupune desfacerea relaţiei R în proiecţiile R1, R2, ..., Rk, astfel încât dependenţele lui R sunt echivalente (au

Page 104: CURS BD Combinat

45

închideri pseudo-tranzitive identice) cu reuniunea dependenţelor lui R1, R2, ..., Rk.

• Descompuneri fără pierderi de informaţie (L-join). Această descompunere presupune desfacerea relaţiei R într-o mulţime de proiecţii R1, R2, ..., Rj, astfel încât pentru orice realizare a lui R este adevărată relaţia:

R = JOIN(ΠB1 (R), ΠB2 (R), ...,ΠBj (R))

unde, pentru 1 ≤ k ≤ j, Bk reprezintă mulţimea atributelor corespunzătoare proiecţiei Rk (Rk = ΠBk (R)). Prin urmare, relaţia iniţială poate fi reconstruită considerând compunerea naturală a relaţiilor obţinute prin descompunere. Formele normale sunt obţinute prin descompuneri fără pierderi de informaţie.

O descompunere fără pierdere de informaţie, utilizată în procesul normalizării, este dată de regula Casey-Delobel:

Fie R(A) o schemă relaţională şi fie α, β, γ o partiţie a lui A. Presupunem că α determină funcţional pe β. Atunci:

R(A) = JOIN(Πα∪β(R), Πα∪γ(R)).

α∪β mulţimea atributelor care intervin în dependenţele funcţionale; α∪γ reprezintă reuniunea determinantului cu restul atributelor lui A.

Pentru exemplul analizat anterior: α = {nume}, β = {capacitate}, γ = {A#, localitate}. Aplicând Casey-Delobel se obţin schemele: AVION1(nume#, capacitate) AVION2)A#, nume, localitate).

Relatia universala

FN1 FN2

FN3 BCNF

FN4 FN5

Page 105: CURS BD Combinat

46

Se observă că anomaliile comentate au dispărut! AVION1

Nume Capacitate AIRBUS 150 CAR 100 B707 150

AVION2

A# Nume Localitate 1 AIRBUS PARIS 2 AIRBUS PARIS 3 AIRBUS LONDRA 4 CAR PARIS 5 B707 LONDRA 6 B707 LONDRA

Forma normală (FN1) O relaţie este în prima formă normală dacă fiecărui atribut care o

compune îi corespunde o valoare indivizibilă (atomică). Exemplu: variante pentru a implementa FN1 pentru tabelul MASINA:

Persoana Vehicul Eu R25 - W14 - R21 Tu 205 El R5 - 305 noi BX - 305 - R12 - R25

Varianta 1

Persoana Vehicul Eu R25 Eu W14 Eu R21 Tu 205 El R5 El 305 Noi BX Noi 305 Noi R12 Noi R25

Page 106: CURS BD Combinat

47

Varianta 2

Persoana Prima Doi Trei Patru Eu R25 W14 R21 Tu 205 El R5 305 Noi BX 305 R12 R25

Varianta 3 (4 tabele) Masina 31 (similar se definesc Masina_32, Masina_33, Masina_34)..

Persoana Vehicul Eu R25 Tu 205 El R5 Noi BX

Masina_34

Persoana Vehicul Noi R25

Forma normală 2 (FN2) O relaţie R este în a doua formă normală dacă şi numai dacă: • relaţia R este în FN1; • fiecare atribut care nu este cheie (nu participă la cheia primară)

este dependent de întreaga cheie primară.

atasat_la

Cod_salariat# Job_cod Nr_proiect# Functia Suma S1 Programator P1 Supervizor 60 S1 Programator P2 Cercetator 25 S1 Programator P3 Auxiliar 10 S3 Vanzator P3 Supervizor 60 S5 Inginer P3 Supervizor 60

atasat_2a

Cod_salariat# Nr_proiect# Functia Suma S1 P1 Supervizor 60 S1 P2 Cercetator 25 S1 P3 Auxiliar 10 S3 P3 Supervizor 60

Page 107: CURS BD Combinat

48

S5 P3 Supervizor 60

atasat_2b

Cod_salariat# Job_cod S1 Programator S3 Vanzator S5 Inginer

A doua condiţie exprimă necesitatea total dependenţei de cheia primară. Această formă normală interzice manifestarea unor dependenţe funcţionale parţiale în cadrul relaţiei R!!!

Pentru a obţine o relaţie FN2 se poate aplica regula Casey-Delobel. Fie relaţia R(K1, K2, X, Y), unde K1 şi K2 definesc cheia primară, iar X şi Y sunt mulţimi de atribute, astfel încât K1 → X. Din cauza dependenţei funcţionale K1 → X care arată că R nu este în FN2, se înlocuieşte R (fără pierdere de informaţie) prin două proiecţii R1(K1, K2, Y) şi R2(K1, X). K1 K2 X Y

Exemplu. Presupunem că un şantier poate executa mai multe lucrări

de bază şi că o lucrare poate fi executată de mai multe şantiere. LUCRARE(cod_obiectiv#, cod_lucrare#, nume); SANTIER(nr_santier#, specialitate, sef); EXECUTA(cod_obiectiv#, cod_lucrare#, nr_santier#, descriere, functie, conducator, data_inceput, data_sfarsit). Pentru relaţia EXECUTA sunt evidente dependenţele: {cod_obiectiv#, cod_lucrare#} → {data_inceput, data_sfarsit},

{cod_obiectiv#, cod_lucrare#, nr_santier#} → {descriere, functie, conducator}.

Page 108: CURS BD Combinat

49

Relaţia EXECUTA este în FN1, dar nu este în FN2 deoarece atributele data_inceput şi data_sfarsit nu depind de numărul şantierului, deci nu depind de întreaga cheie primară. Pentru a obţine o relaţie în FN2 se aplică regula Casey Delobel şi relaţia EXECUTA se desface în:

EXECUTA_1(cod_obiectiv#, cod_lucrare#, nr_santier#, descriere, functie, conducator) EXECUTA_2(cod_obiectiv#, cod_lucrare#, data_inceput, data_sfarsit). Forma normală 3 (FN3) Intuitiv, o relaţie R este în a treia formă normală dacă şi numai dacă: • relaţia R este în FN2; • fiecare atribut care nu este cheie (nu participă la o cheie) depinde

direct de cheia primară. Fie R o relaţie, X o submulţime de atribute ale lui R şi A un atribut al

relaţiei R. A este dependent tranzitiv de X dacă există Y astfel încât X → Y şi Y → A (A nu aparţine lui Y şi Y nu determină pe X). X nu este dependent funcţional de Y sau A!

De exemplu, dacă K1, K2, K3 → A1 şi dacă K1, K2, A1 → A2, atunci K1, K2, K3 → K1, K2, A1 şi K1, K2, A1 → A2. Prin urmare, A2 este dependent tranzitiv de K1, K2, K3.

Formal, o relaţie R este în a treia formă normală dacă şi numai dacă: • relaţia R este în FN2; • fiecare atribut care nu este cheie (nu participă la o cheie) nu este

dependent tranzitiv de nici o cheie a lui R. O relaţie este în FN3 dacă şi numai dacă fiecare atribut (coloană)

care nu este cheie, depinde de cheie, de întreaga cheie şi numai de cheie. Pentru a obţine o relaţie FN3 se poate aplica regula Casey-Delobel. Fie relaţia R(K, X1, X2, X3), unde atributul X2 depinde tranzitiv de K,

iar K este cheia primară a lui R. Presupunem că K → X1 → X2. Din cauza dependenţei funcţionale X1 → X2 care arată că R nu este în FN3, se înlocuieşte R (fără pierdere de informaţie) prin două proiecţii R1(K, X1, X3) şi R2(X1, X2).

K X1 X2 X3

Page 109: CURS BD Combinat

50

Exemplu: Tabelul atasat_2a nu este in FN3. De ce? atasat_3a

Cod_salariat# Nr_proiect# Functia S1 P1 Supervizor S1 P2 Cercetator S1 P3 Auxiliar S3 P3 Supervizor S5 P3 Supervizor

atasat_3b

Functia Suma Supervizor 60 Cercetator 25 Auxiliar 10

Exemplu. În tabelul EXECUTA1(cod_obiectiv#, cod_lucrare#, nr_santier#, descriere, functie, conducator) continuă să existe redundanţă în date.

Atributul conducator depinde indirect de cheia primară prin intermediul atributului functie. Între atributele relaţiei există dependenţele:

{cod_obiectiv#, cod_lucrare#, nr_santier#} → {descriere},

{cod_obiectiv#, cod_lucrare#, nr_santier#} → {functie} → {conducator}. Pentru a aduce relaţia EXECUTA_1 în FN3 se aplică regula Casey-

Delobel. Relaţia se desface, prin eliminarea dependenţelor funcţionale tranzitive, în proiecţiile: EXECUTA11(cod_obiectiv#, cod_lucrare#, nr_santier#, descriere, functie) EXECUTA12(functie, conducator).

Schema de sinteză pentru obţinerea lui FN3 Algoritmul de sinteză construieşte o acoperire minimală F a

dependenţelor funcţionale totale. Se elimină atributele şi dependenţele funcţionale redundante. Mulţimea F este partiţionată în grupuri Fi, astfel încât în fiecare grup Fi sunt dependenţe funcţionale care au acelaşi membru stâng şi nu există două grupuri având acelaşi membru stâng. Fiecare grup Fi produce o schemă FN3. Algoritmul realizează o descompunere ce conservă dependenţele.

Algoritm SNF3 (aducerea unei relaţii în FN3 prin utilizarea unei scheme de sinteză):

Page 110: CURS BD Combinat

51

1. Se determină F o acoperire minimală a lui E (mulţimea dependenţelor funcţionale).

2. Se descompune mulţimea F în grupuri notate Fi, astfel încât în cadrul fiecărui grup să existe dependenţe funcţionale având aceeaşi parte stângă.

3. Se determină perechile de chei echivalente (X, Y) în raport cu F (două mulţimi de atribute X, Y sunt chei echivalente dacă în mulţimea de dependenţe E există atât dependenţa X Y, cât şi dependenta Y X).

4. Pentru fiecare pereche de chei echivalente: se identifică grupurile Fi şi Fj care conţin dependenţele funcţionale cu partea stângă X şi respectiv Y; se formează un nou grup de dependenţe Fi j, care va conţine dependenţele funcţionale având membrul stâng (X, Y); se elimină grupurile Fi şi Fj, iar locul lor va fi luat de grupul Fi j.

5. Se determină o acoperire minimală a lui F, care va include toate dependenţele X → Y, unde X şi Y sunt chei echivalente (celelalte dependenţe sunt redundante).

6. Se construiesc relaţii FN3 (câte o relaţie pentru fiecare grup de dependenţe funcţionale).

Se observă că algoritmul solicită • determinarea unei acoperiri minimale (algoritmii EAR şi EDF); • determinarea închiderii (A + ) unei mulţimi de atribute A în raport

cu mulţimea de dependenţe funcţionale E (algoritm AIDF). Determinarea acoperirii minimale presupune eliminarea atributelor şi

dependenţelor redundante. Acoperirea minimală nu este unică şi depinde de ordinea în care sunt eliminate aceste atribute şi dependenţe redundante.

Algoritm EAR (elimină atributele redundante din determinantul dependenţelor funcţionale)

Pentru fiecare dependenţă funcţională din E şi pentru fiecare atribut din partea stângă a unei dependenţe funcţionale:

Pas1. Se elimină atributul considerat. Pas2. Se calculează închiderea părţii stângi reduse. Pas3. Dacă închiderea conţine toate atributele din determinantul

dependenţei, atunci atributul eliminat la pasul 1 este redundant şi rămâne eliminat. În caz contrar, atributul nu este redundant şi se reintroduce în partea stângă a dependenţei funcţionale.

Page 111: CURS BD Combinat

52

Algoritm EDF (elimină dependenţele funcţionale redundante din E) Pentru fiecare dependenţă funcţională X Y din E: Pas1. Se elimină dependenţa din E. Pas2. Se calculează închiderea X + , în raport cu mulţimea redusă de

dependenţe. Pas3. Dacă Y este inclus în X + , atunci dependenţa X Y este

redundantă şi rămâne eliminată. În caz contrar, se reintroduce în E.

Algoritm AIDF (determină închiderea lui A) Pas1. Se caută dacă există în E dependenţe X Y pentru care

determinantul X este o submulţime a lui A, iar determinatul Y nu este inclus în A.

Pas2. Pentru fiecare astfel de dependenţă funcţională se adaugă mulţimii A atributele care constituie determinatul dependenţei.

Pas3. Dacă nu mai există dependenţe funcţionale de tipul de la pasul 1, atunci A + = A.

Exemplu: Fie dependenţele funcţionale: f1: F N; f2: F P; f3: P, F, N U; F4: P C; f5: P T; f6: C T; f7: N F.

Pas1 (suprimarea atributelor redundante). Atributul A i este redundant în dependenţa funcţională A1, A 2 , …A i , …A n Z, dacă dependenţa funcţională A1, A 2 , …A 1−i , A 1+i …A n Z poate fi generată plecând de la mulţimea iniţială de dependenţe (E) şi de la axiomele considerate. f1: F N; f3: P, F, N U sau N, P, F U; Aplicând axioma de pseudotranzitivitate se obţine:

F, P, F U P, F U

Pas2 (suprimarea dependenţelor funcţionale redundante). Dependenţa funcţională f este redundantă în E dacă E + = (E - f) + , unde E + reprezintă închiderea lui E. Se observă că f5 este redundantă (poate fi obţinută din f4 şi f6). La sfârşitul etapei se obţine:

f1: F N; f2: F P; f3: P, F U; P este redundant =>F-->U

Page 112: CURS BD Combinat

53

f4: P C; f6: C T; f7: N F.

Pas3 (gruparea dependenţelor având acelaşi membru stâng). F1 = {f1, f2, f3}; F2 = {f4}; F3 = {f6}; F4 = {f7}

Pas4 (regruparea mulţimilor F i si F j dacă există dependenţe de forma X Y şi Y X, unde X reprezinta partea stanga a dependenţei lui F i şi Y este partea stângă a dependenţei lui F j .

Din F1 şi F4 se obţine: G1 = {f1, f2, f3, f7}; G2 = {f4}; G3 = {f6}.

Pas5 (generarea relaţiilor FN3). R1(F#, N, P, U); R2(P#, C); R3(C#, T). De remarcat: R1 nu este in BCNF! De ce? Exista dependenta N -->F.

Exerciţiu: Presupunem că o parte din activităţiile de pe un aeroport sunt

caracterizate de atributele: A -- număr zbor; B -- tip avion; C -- aeroport plecare; D -- aeroport sosire; E -- linia aeriană; F -- ora plecării; G -- capacitate; H -- număr locuri rezervate; I -- data; J -- tarif; K -- prestaţii la bord. Între aceste atribute există legături exprimate prin dependenţele: A BEFG ACDI H CD J CDF K B G CF ABE AC D ABD C EG B

Page 113: CURS BD Combinat

54

Aplicând algoritmul de sinteză se obţin relaţiile: R1(B#, G) R2(E#, G#, B) R3(A#, B, E, F) R4(C#, D#, J) R5(A#, C#, I#, H) R6(A, C, D, F, K) în care cheile primare pot să fie oricare dintre: AD sau AC sau CF. Încercaţi să justificaţi acest rezultat!!!

Forma normală Boyce-Codd (BCNF) Determinantul este un atribut sau o mulţime de atribute

neredundante, care constituie un identificator unic pentru alt atribut sau altă mulţime de atribute ale unei relaţii date.

Intuitiv, o relaţie R este în forma normală Boyce-Codd dacă şi numai dacă fiecare determinant este o cheie candidat.

Formal, o relaţie R este în forma normală Boyce-Codd dacă şi numai dacă pentru orice dependenţă funcţională totală X → A, X este o cheie (candidat) a lui R.

Regula Casey Delobel pentru R(K1#, K2#, X) presupunând că există dependenţa: X K2. R1(K1#, X) şi R2(X#, K2) K1 K2 X

Exemplu: ADRESA(cod_parsoana#, telefon#, adresa)

cod_persoana adresa

Page 114: CURS BD Combinat

55

telefon

În dependenţa adresa telefon se observă că determinantul nu este o cheie candidat. Relaţia ADRESA se desface în:

ADRESA_1(cod_persoana#, adresa); ADRESA_2(adresa#, telefon). Relaţiile sunt în BCNF, se conservă datele, dar nu se conservă

dependenţele (s-a pierdut cod_persoana, telefon adresa). Exemplu: Relaţia INVESTESTE_IN leagă entităţile INVESTITOR şi

OBIECTIV_INVESTITIE. Ea are schema relaţională: INVESTESTE_IN(cod_contractant#, cod_obiectiv#, nr_contract,

cota_parte). Între atributele relaţiei există dependenţele: {cod_contractant#, cod_obiectiv#} → {nr_contract, cota_parte}, {nr_contract} → {cod_obiectiv}. Se aplică regula Casey-Delobel şi se aduce relaţia în BCNF. INVESTESTE_IN_1(cod_obiectiv, nr_contract#); INVESTESTE_IN_2(cod_contractant#, nr_contract, cota_parte).

Pentru ca o relaţie să fie adusă în BCNF nu trebuie în mod obligatoriu să fie în FN3. Se pot aduce în BCNF şi relaţii aflate în FN1 sau FN2. Acest lucru este posibil întrucât dependenţele funcţionale parţiale şi cele tranzitive sunt tot dependenţe noncheie, adică dependenţe ai căror determinanţi nu sunt chei candidat. Presupunem că R este o relaţie ce conţine atributele A.

Algoritm TFBCNF (aducerea unei relaţii R din FN1 în BCNF) 1. Dacă relaţia conţine cel mult două atribute, atunci R este în

BCNF şi algoritmul s-a terminat. 2. Dacă relaţia conţine mai mult de două atribute, se consideră toate

perechile (X, Y) de atribute distincte din A. 3. Se determină A1

+, închiderea mulţimii A1 = A – {X, Y}. 4. Dacă pentru orice pereche (X, Y), X ∉ A1

+ atunci relaţia R este în BCNF şi algoritmul s-a terminat.

5. În caz contrar (pentru cel puţin o pereche (X, Y), X aparţine lui A1

+), relaţia R nu este în BCNF.

Page 115: CURS BD Combinat

56

6. Se reduce progresiv schema relaţiei şi se reia algoritmul, exploatând relaţia redusă. Orice relaţie obţinută prin reducerea lui R şi care este în BCNF se consideră ca făcând parte din descompunerea lui R în procesul aducerii sale în BCNF.

Forma normală 4 (FN4) FN4 elimină redundanţele datorate relaţiilor m:n, adică datorate

dependenţei multiple. Intuitiv, o relaţie R este în a patra formă normală dacă şi numai dacă

relaţia este în BCNF şi nu conţine relaţii m:n independente. Fie R o relaţie definită pe o mulţime de atribute A = {A1, A2, ..., An}

şi fie X, Y, Z ⊂ A. Se spune că X multidetermină pe Z sau că Z este multidependent de X :

• dacă pentru fiecare valoare a lui Z în R există numai o valoare pentru perechea (X, Y);

• dacă valoarea lui Z depinde numai de valoarea lui X. Acest tip de dependenţă, numită şi multivaloare sau multidependenţă

(MVD) se notează prin X →→ Z. Intuitiv, multidependenţa reprezintă situaţia în care valoarea

unui atribut (sau a unei mulţimi de atribute) determină o mulţime de valori a altui atribut (sau mulţimi de atribute)!!!

Multidependenţa X →→ Y poate fi gândită ca o regulă de deducţie: dacă tuplurile <x, y, z> şi <x, y′, z′> sunt în relaţie la un moment r, atunci la momentul r sunt în relaţie şi tuplurile <x, y, z′> şi <x, y′, z>. x y z x y ' z ' x y z ' x y ' z

Orice dependenţă funcţională este o multidependenţă. Afirmaţia inversă nu este adevărată. Dacă X → Y (FD), atunci pentru oricare două

Page 116: CURS BD Combinat

57

tupluri <x, y, z> şi <x, y′, z′>, se obţine y = y′. Prin urmare în relaţie apar tuplurile <x, y′, z> şi <x, y, z′> şi deci X →→ Y (MVD).

Fie W, V, X, Y şi Z submulţimi de atribute ale unei scheme relaţionale R. Fiind dată o mulţime T de multidependenţe există o mulţime completă de axiome (Ax1–Ax8) care permit obţinerea tuturor multidependenţelor ce se pot deduce din mulţimea T:

Ax1. Dacă Y ⊂ X, atunci X → Y. Ax2. Dacă X → Y, atunci X ∪ Z → Y ∪ Z. Ax3. Dacă X → Y şi Y → Z, atunci X → Z. Ax4. Dacă X →→ Y, atunci X →→ R – {X ∪ Y}. Ax5. Dacă X →→ Y şi V ⊂ W, atunci W ∪ X →→ V ∪ Y. Ax6. Dacă X →→ Y şi Y →→ Z, atunci X →→ (Z – Y). Ax7. Dacă X → Y, atunci X →→ Y. Ax8. Dacă X →→ Y, Z → W, W ⊂ Y şi Y ∩ Z = ∅, atunci X → W. O multidependenţă elementară este o multidependenţă care are

părţi stângi şi drepte minimale (nu există X′ ⊂ X şi Y′ ⊂ Y a.i. X′ →→ Y′). Formal, relaţia R este în a patra formă normală dacă şi numai dacă: • R este în BCNF; • orice dependenţă multivaloare este o dependenţă funcţională. O relaţie BCNF este în FN4 dacă pentru orice multidependenţă

elementară de forma X →→ Y, X este o supercheie a lui R. Aducerea relaţiilor în FN4 presupune eliminarea dependenţelor multivaloare atunci când sunt mai mult de una în cadrul unei relaţii.

Regula de descompunere în relaţii FN4. Fie R(X, Y, Z) o schemă relaţională care nu este în FN4 şi fie X →→ Y o multidependenţă elementară care nu este de forma „CHEIE →→ atribut“. Această relaţie este descompusă prin proiecţie în două relaţii:

R = JOIN(ΠX∪Y(R), ΠX∪Z(R)). Aplicând recursiv această regulă, se obţin relaţii FN4. Exemplu. Fie relaţia INVESTITIE(cod_contractant#, denumire,

telefon) şi presupunem că un investitor poate avea mai multe numere de telefon şi că poate investi în mai multe obiective. Între atributele relaţiei există multidependenţele:

cod_contractant# →→ denumire; cod_contractant# →→ telefon.

Page 117: CURS BD Combinat

58

Relaţia INVESTITIE este în BCNF. Pentru a aduce relaţia în FN4 o vom descompune prin proiecţie în două relaţii:

INVESTITIE_1(cod_contractant#, denumire), INVESTITIE_2(cod_contractant#, telefon). INVESTITIE = JOIN(INVESTITIE_1, INVESTITIE_2).

Forma normală 5 (FN5) FN5 îşi propune eliminarea redundanţelor care apar în relaţii m:n

dependente. În general, aceste relaţii nu pot fi descompuse. S-a arătat că o relaţie de tip 3 este diferită de trei relaţii de tip 2. Există totuşi o excepţie, şi anume, dacă relaţia este ciclică

Intuitiv, o relaţie R este în forma normală 5 dacă şi numai dacă: 1. relaţia este în FN4; 2. nu conţine dependenţe ciclice. Dependenţa funcţională şi multidependenţa permit descompunerea

prin proiecţie, fără pierdere de informaţie, a unei relaţii în două relaţii. Regulile de descompunere (FN1 – FN4) nu dau toate descompunerile posibile prin proiecţie ale unei relaţii. Există relaţii care nu pot fi descompuse în două relaţii dar pot fi descompuse în trei, patru sau mai multe relaţii fără a pierde informaţii. Pentru a obţine descompuneri L-join în trei sau mai multe relaţii, s-a introdus conceptul de join-dependenţă sau dependenţă la compunere (JD).

Fie {R1, R2, ..., Rp} o mulţime de scheme relaţionale care nu sunt disjuncte şi a căror reuniune este R.

R satisface join-dependenţa *{R1, R2, ..., Rp} dacă la fiecare moment al lui R are loc egalitatea:

R = JOIN(Πα1(R), Πα2(R), ..., Παp(R)) unde αk reprezintă mulţimea atributelor corespunzătoare lui Rk(1 ≤ k ≤ p).

Join-dependenţa *{R1, R2, ..., Rp} are loc în R, dacă R1, R2, ..., Rp este o descompunere L-join a lui R. Pentru p = 2 se regăseşte multidependenţa. O join-dependenţă *{R1, R2, ..., Rp} în care una dintre Ri este chiar R, defineşte o join-dependenţă trivială.

Join-dependenţa generalizează multidependenţa. Într-adevăr, multidependenţa X →→ Y în relaţia R(X, Y, Z) (deci şi X →→ Z), corespunde join-dependenţei *{X ∪ Y, X ∪ Z}. Invers, join-dependenţa *{R1, R2} corespunde multidependenţei R1 ∩ R2 →→ R1 – (R1 ∩ R2).

Page 118: CURS BD Combinat

59

Formal, o relaţie R este în FN5 dacă şi numai dacă orice join-dependenţă *{R1, R2, ..., Rp} care are loc în R fie este trivială, fie conţine o supercheie a lui R (adică, o anumită componentă Ri este o supercheie a lui R). Cu alte cuvinte, o relaţie R este în FN5 dacă orice join-dependenţă definită pe R este implicată de cheile candidat ale lui R.

Între mulţimile de atribute X, Y şi Z din cadrul relaţiei R există o join-dependenţă dacă există multidependenţe între fiecare dintre perechile de mulţimi (X, Y), (Y, Z) şi (X, Z).

Aducerea în FN5 prin eliminarea join dependenţelor! Exemplu. Fie schema R(furnizor, cod_consumabil, cantitate, pret). Reguli: • un furnizor produce mai multe consumabile; • nu toţi furnizorii produc aceleaşi consumabile; • preţul unui consumabil de la un furnizor este variabil şi nu

depinde de cantitate.

Furnizor Cod_consumabil Cantitate Pret F1 1 500 100 F2 1 100 80 F2 1 500 100 F2 2 500 100

Relaţia este în FN4, dar există redundanţă în date. Relaţia se

descompune prin proiecţie în: R1(furnizor#, cod_consumabil#) R2(furnizor#, cantitate, pret) R3(cod_consumabil#, cantitate, pret). S-au eliminat redundanţele: (F2,1) pentru R1; (F2, 500, 100) pentru R2; (1, 500, 100) pentru R3. Se observă că: JOIN(R1, R2) ≠ R; JOIN(R1, R3) ≠ R; JOIN(R3, R2) ≠ R; JOIN(R1, R2, R3) = JOIN(R1, JOIN(R2, R3)) = R

Page 119: CURS BD Combinat

60

Există join dependenţa: *{R1(furnizor, cod_consumabil), R2(furnizor, cantitate, pret), R3(cod_consumabil, cantitate, pret)}

Exemplu. Fie schema relaţională:

EXECUTANT(nr_santier#, cod_obiectiv#, cod_lucrare#, data_inceput, data_sfarsit). Un şantier poate executa mai multe lucrări referitoare la acelaşi obiectiv sau poate executa o lucrare pentru un obiectiv în intervale de timp distincte. Se presupune că mai multe şantiere pot executa aceeaşi lucrare, în acelaşi interval de timp sau în intervale de timp distincte.

Relaţia, datorită dependenţelor formulate anterior, nu este în FN5. Ea se poate desface prin proiecţie în trei relaţii:

EX1(nr_santier#, cod_obiectiv#, cod_lucrare#); EX2(nr_santier#, data_inceput, data_sfarsit); EX3(cod_obiectiv#, cod_lucrare#, data_inceput, data_sfarsit). Sunt evidente relaţiile: EXECUTANT ≠ JOIN(EX1, EX2), EXECUTANT ≠ JOIN(EX1, EX3), EXECUTANT ≠ JOIN(EX2, EX3), EXECUTANT = JOIN(JOIN(EX1, EX2), EX3).

Concluzii: 1. FN1 → FN2 elimină redundanţele datorate dependenţei netotale

a atributelor care nu participă la o cheie, faţă de cheile lui R. Se suprimă dependenţele funcţionale care nu sunt totale.

2. FN2 → FN3 elimină redundanţele datorate dependenţei tranzitive. Se suprimă dependenţele funcţionale tranzitive.

3. FN3 → BCNF elimină redundanţele datorate dependenţei funcţionale. Se suprimă dependenţele în care partea stângă nu este o supercheie.

4. BCNF → FN4 elimină redundanţele datorate multidependenţei. Se suprimă toate multidependenţele care nu sunt şi dependenţe funcţionale.

Page 120: CURS BD Combinat

61

5. FN4 → FN5 elimină redundanţele datorate dependentei. ciclice. Se suprimă toate join-dependenţele care nu sunt implicate de o cheie.

6. BCNF, FN4 şi FN5 corespund la regula că orice determinant este o cheie, dar de fiecare dată dependenţa cu care se defineşte determinantul este alta şi anume dependenţa funcţională, multidependenţa sau join-dependenţa).

7. Descompunerea unei relaţii FN2 în FN3 conservă datele şi dependenţele, pe când descompunerea unei relaţii FN3 în BCNF şi, respectiv, a unei relaţii BCNF în FN4 conservă doar datele.

Cateva observaţii şi concluzii referitoare la PROIECTAREA BAZELOR DE DATE

Proiectarea conceptuală a bazei de date -- construirea reprezentării conceptuale a bazei de date, care include identificarea tipurilor importante de entităţi, relaţii, atribute.

1) identificarea tipurilor de entităţi (E); 2) identificarea tipurilor de relaţii (R); 3) identificarea şi asocierea atributelor (A) cu tipurile de E sau R; 4) determinarea domeniilor atributelor; 5) determinarea atributelor chei candidat şi chei primare; 6) specializarea şi generalizarea tipurilor de entităţi; 7) desenarea diagramei E/R; 8) revizuirea modelului de date conceptual local, împreună cu

utilizatorul, pentru a garanta că modelul este o reprezentare corectă a punctului de vedere al utilizatorului asupra sistemului real analizat.

Proiectarea logică a bazei de date -- transpunerea reprezentării conceptuale în structura logică a BD, care include proiectarea relaţiilor.

1) transpunerea modelului conceptual local în modelul de date logic local:

Page 121: CURS BD Combinat

62

− eliminarea relaţiilor M:N (înlocuirea prin relaţii de tip 1:M sau prin tabele asociative);

− eliminarea relaţiilor complexe (înlocuirea prin relaţii de tip 1:M);

− eliminarea relaţiilor recursive (înlocuirea prin relaţii dependente);

− eliminarea atributelor multiple (înlocuirea prin relaţii dependente;

− reexaminarea relaţiilor 1:1 (sunt într-adevăr 2 relaţii distincte?); − eliminarea relaţiilor redundante. 2) extragerea relaţiilor din modelul de date logic local pentru a

reprezenta entităţile şi relaţiile (legăturile); 3) normalizarea relaţiilor; 4) validarea modelului conform tranzacţiilor utilizatorului pentru a

garanta că acesta acceptă şi rezolvă operaţiile cerute de către model (se verifică faptul că modelul furnizează toate informaţiile cerute de fiecare tranzacţie şi se reprezintă schematic calea urmată de fiecare tranzacţie, direct în diagrama E/R);

5) desenarea diagramei conceptuale; 6) definirea constrîngerilor de integritate; 7) revizuirea modelului de date conceptual local, împreună cu

utilizatorii; 8) construirea şi validarea modelului de date logic global prin

combinarea modelelor locale: – îmbinarea modelelor locale (revizuirea E, R, A, CP, CE,

constrîngeri, revizuirea denumirilor, căutarea entităţilor şi relaţiilor care lipsesc, reactualizarea documentaţiei);

– normalizarea modelului; – validarea modelului conform tranzacţiilor utilizatorului; – verificarea în vederea dezvoltării ulterioare; – desenarea diagramei conceptuale finale; – revizuirea modelului de date conceptual global, împreună cu

utilizatorii.

Modalităţi pentru asigurarea integrităţii refenţiale!!! Se specifică constrângeri de existenţă care definesc condiţiile în care

o cheie candidat sau o cheie externă poate fi inserată, ştearsă sau reactualizată.

Page 122: CURS BD Combinat

63

Exemplu: DOMENIU_contine_CARTE (1:M) 1) Inserare în relaţia "copil" (carte) - se verifică dacă domeniul cărţii

inserate este null sau corespunde unui domeniu existent. 2) Ştergerea în relaţia "copil" (fără probleme). 3) Reactualizarea în relaţia "copil" (similar cazului 1). 4) Inserarea în relaţia "părinte" (domeniu) se face fără probleme. 5) Reactualizarea cheii primare în relaţia "părinte" (dacă există o

apariţie în tabelul "copil" care face referinţă la vechea valoare a cheii, atunci se pierde integritatea refenţială). Se pot aplica strategii pentru a asigura integritatea refenţială (vezi 6).

6) Ştergerea unei apariţii din relaţia "părinte" (se pierde integritatea referenţială dacă se şterge un domeniu de carte, dar există cel puţin o carte din domeniul respectiv). Există 5 strategii care pot fi luate în considerare.

− NO ACTION (nici o acţiune)- nu se poate şterge un domeniu dacă există o carte în domeniul respectiv;

− CASCADE - se şterge domeniul şi automat se şterg toate cărţile din domeniu ş.a.m.d.;

− SET NULL - se şterge domeniul, iar toate cărţiile din domeniul respectiv vor avea codul domeniului setat null;

− SET DEFAULT - setare la o valoare prestabilită; − NO CHECK - când este şters un domeniu de carte, nu se face

nimic pentru a garanta că integritatea refenţială este menţinută (nici o verificare).

Proiectarea fizică a bazei de date -- implementarea fizică a structurii logice într-o capacitate de stocare secundară corespunzătoare SGBD-ului ţintă. Se descriu structurile de stocare şi metodele de acces utilizate pentru realizarea unui acces eficient la date.

1) Transformarea relaţiilor extrase din modelul de date logic global într-o formă care să poată fi implementată în SGBD-ul relaţional ţintă (LDD).

2) Proiectarea (definirea) constrângerilor sistemului real modelat în SGBD-ul ţintă (CONSTRAINT, declanşatori).

3) Proiectarea reprezentării fizice - determinarea organizării fişierelor şi a metodelor de acces (indecşi) care vor fi utilizate pentru a stoca relaţiile de bază (modul în care relaţiile şi tuplurile vor fi păstrate în cadrul capacităţii de stocare secundare).

Page 123: CURS BD Combinat

64

4) Introducerea unei redundanţe controlate (denormalizarea). 5) Estimarea necesarului de spaţiu pe disc cerut de baza de date. 6) Proiectarea mecanismelor de securitate: − proiectarea vizualizărilor (VIEW); − proiectarea regulilor de acces la relaţiile de bază şi la vizualizări

(privilegii, role-uri). 7) Monitorizarea neîntreruptă şi reglarea sistemului operaţional

pentru obţinerea unor performanţe maxime (micşorarea configuraţiei hardware, timpi de răspuns mai scăzuţi, transfer eficient etc.).

Comentăm pasul 4 referitor la considerarea introducerii unei redundanţe controlate (denormalizare). NU există reguli fixe!!! Pasul 4 presupune: • considerarea datelor derivate (calculate); • considerarea dublării atributelor şi grupării relaţiilor.

Considerarea datelor derivate De exemplu, în relaţia PROPRIETATE_DE INCHIRIAT apare drept

câmp, codul persoanei care a tranzacţionat închirierea. Prin urmare, s-ar putea calcula pentru fiecare angajat, câte proprietăţi a închiriat SAU se poate introduce în tabelul PERSONAL, un câmp calculat (derivat) ce conţine numărul proprietăţilor închiriate de acesta.

Considerarea dublării atributelor şi grupării relaţiilor Dublarea atributelor sau gruparea relaţiilor are ca scop reducerea

numărului de join-uri necesare pentru efectuarea unei interogări. FILIALA (nr_fil#, strada, zona, oras, codpostal, tel, fax) Relaţia nu este în FN3 deoarece codpostal determină funcţional

atributele zona şi oras. Aplic FN3 şi se obţine: FIL(nr_fil#, strada, codpostal, tel, fax COD_P(zona, oras, codpostal#) Nu este convenabil, deoarece rareori vom accesa adresa filialei, fără

informaţii referitoare la zona şi oraş. Prin urmare, preferăm FN2. Vom analiza câteva situaţii concrete de denormalizare.

• combinarea relaţiilor de tip 1:1 • dublarea atributelor care nu sunt chei în relaţii 1:M

Page 124: CURS BD Combinat

65

SELECT p.*, ptr.nume FROM proprietate_de_inchiriat p, proprietar ptr WHERE p.nrptr=ptr.nrptr AND nrfil='S3';

Atributul nrptr este codul proprietarului. Dacă se va dubla atributul nume din relaţia proprietate_de_inchiriat, atunci interogarea devine: SELECT p.* FROM proprietate_de_inchiriat p WHERE nrfil='S3';

Avantaje sau dejavantaje ?!? Depinde de problemele care pot apărea.

• tabele de referinţă (tabele de căutare) Acestea conţin, de obicei, un cod şi o descriere. De exemplu se poate

defini un tabel căutare "părinte" pentru tipul de proprietate şi modifica tabelul proprietate_de_inchiriat ("copil") astfel:

TIP_PROPRIETATE(tip, descriere) PROPRIETATE_DE_INCHIRIAT(nrpte, strada, zona, oras, coppostal, tipul, nrcamere, chirie, nrptr, nrfiliala, nrpersonal) Avantaje: – dacă este modificată descrierea, atunci se va modifica o singură

dată, în tabelul de căutare; – se reduce dimensiunea relaţiei "copil";

• dublarea atributelor cheii externe într-o relaţie de tip 1:M pentru simplificarea join-urilor

Să se enumere proprietarii de proprietăţi de închiriat dintr-o filială. SELECT ptr.nume FROM proprietate_de_inchiriat p, proprietar ptr WHERE p.nrptr=ptr.nrptr AND p.nrfil='S3';

Dacă se dublează cheia externă nrfiliala în relaţia PROPRIETAR, adică se introduce o relaţie directă între FILIALA şi PERSONAL, atunci cererea devine:

SELECT p.nume FROM proprietar p WHERE nrfil='S3';

ATENŢIE! Sunt necesare constrângeri suplimentare asupra cheilor externe. De exemplu, dacă un proprietar ar închiria prin mai multe filiale (atribut multiplu), atunci modificările nu mai sunt valabile.

De remarcat că singurul motiv pentru care relaţia proprietate_de_inchiriat conţine atributul nrfiliala constă în faptul că este

Page 125: CURS BD Combinat

66

posibil ca o proprietate să nu aibă alocat un membru de personal, mai ales la început, când este preluată iniţial de către agenţie.

• Dublarea atributelor în relaţiile de tip M:N, pentru reducerea join-urilor.

Presupunem că relaţia M:N dintre chirias şi proprietate_de_inchiriat a fost descompusă prin introducerea relaţiei intermediare VIZITARE.

Care sunt chiriaşii care au vizitat proprietăţi, dar mai au de făcut comentarii asupra uneia dintre ele? Personalul de la agenţie are nevoie de atributul strada atunci când vorbeşte cu chiriaşii. SELECT p.strada, c.*, v.data FROM chirias c, vizitare v, proprietate_de_inchiriat p WHERE v.nrpte = p.nrpte AND c.nrch = v.nrch AND comentarii IS NULL;

Atributul nrpte este codul proprietăţii, iar nrch este codul chiriaşului.

Dacă se introduce atributul strada în relaţia VIZITARE, atunci cererea devine: SELECT v.strada, c.*, v.data FROM chirias c, vizitare v WHERE c.nrch = v.nrch AND comentarii IS NULL;

Comentăm pasul 3! Proiectarea reprezentării fizice Scopul este de a stoca datele în mod eficient. Pentru măsurarea

eficienţei poate fi analizată: • capacitatea de stocare pe disc; • timpul de răspuns; • transferul de tranzacţii (numărul de tranzacţii care pot fi efectuate

într-un anumit interval de timp). Pentru îmbunătăţirea performanţelor trebuie ca proiectantul să

cunoască cum interacţionează cele 4 componente hardware (memoria principală, CPU, discul I/O, reţeaua) şi modul cum acestea afectează performanţele sistemului.

Principiile de bază ale distribuirii datelor pe unităţile de disc: • fişierele sistemului de operare să fie separate de cele ale BD; • fişierele principale ale BD să fie separate de fişierele de indexare; • fişierul jurnalului de recuperare să fie separat de restul BD. În această etapă se face şi analizarea tranzacţiilor, adică cunoaşterea

funcţionalităţii acestora şi analizarea celor mai importante dintre acestea.

Page 126: CURS BD Combinat

67

Pentru fiecare tranzacţie trebuie detrminat: • frecvenţa estimată cu care va fi rulată; • relaţiile şi atributele accesate; • tipul de acces (inserare, interogare, ştergere sau rectualizare); • atributele care apar în predicate (condiţii); • atributele care apar în join-uri; • constrângerile de timp impuse tranzacţiilor.

Limbaje pentru prelucrarea datelor relaţionale Unul dintre cele mai mari merite ale modelului relaţional este că prin

intermediul multiplelor sale limbaje de interogare (neprocedurale) permite utilizatorului, chiar şi neinformatician, să indice rezultatul care îl interesează, fără a preciza modul în care este obţinut acest rezultat.

O relaţie poate fi definită ca o mulţime, sau ca un predicat. Conform dualităţii definiţiei unei relaţii, limbajele de prelucrare a datelor relaţionale pot fi grupate în:

• limbaje algebrice - bazate pe teoria mulţimilor (SEQUEL, SQL); • limbaje predicative - fondate pe calculul predicatelor. Limbajele predicative pot fi: • orientate pe tupluri (QUEL, ALPHA); • orientate pe domenii (pot fi non-grafice (ILL, FQL) sau grafice). Limbajele grafice pot fi: • cu variabile domeniu explicite (QBE); • fără variabile domeniu explicite (LAGRIF, CUPID, VGQF). SQL este limbajul standard de descriere a datelor şi acces la

informaţiile din baza de date. SQL nu este un limbaj unic (cu excepţia standardului care este puţin utilizat), existând peste o 100 de dialecte. Au fost concepute şi dezvoltate diferite versiuni ale standardului SQL de către

Page 127: CURS BD Combinat

68

ANSI, IBM, Microsoft, Borland, etc. Din păcate, lipsa unui standard unic SQL are drept consecinţe creşterea costurilor programelor de gestiune a bazelor de date şi îngreunarea întreţinerii arhitecturilor client/server.

Un grup de specialişti în baze de date s-au reunit sub numele SAG (SQL Access Group) cu scopul de a construi un limbaj SQL comun şi de a realiza pentru fiecare dialect un program de conversie din dialect în SQL, şi invers.

Rezultatul a fost că în: • 1992, Microsoft a lansat ODBC (Open Database Connectivity)

care este o mulţime de primitive bazate pe activitatea lui SAG; • 1994 Borland a lansat IDAPI (Integrated Database Application

Programming Interface) care este o bibliotecă de funcţii SQL ce se pot integra într-un program gazdă.

Limbaje algebrice În abordarea algebrică, o relaţie este considerată ca o mulţime de

tupluri, iar o bază de date este considerată ca o mulţime de relaţii pe care sunt definiţi operatorii algebrici.

Există două tipuri de operatori algebrici: mulţime (intersecţie, reuniune, diferenţă, produs cartezian) şi relaţionali (proiecţie, selecţie, diviziune, compunere). Operatorii selecţie, proiecţie, produs cartezian, reuniune şi diferenţă sunt ireductibili şi sunt consideraţi drept operatori de bază, iar operatorii intersecţie, diviziune şi compunere pot fi deduşi din operatorii anteriori şi sunt consideraţi operatori derivaţi.

Operatorii limbajului algebric permit exprimarea unor cereri nerecursive. Dacă cererea este recursivă este necesar un operator special şi anume închiderea tranzitivă a unei relaţii.

SEQUEL (Structured English as a Query Language) este un limbaj algebric definit pentru prototipul relaţional SYSTEM–R. Operaţia fundamentală a limbajului este SELECT, care are forma generală clasică.

Operatorii clasici UNION, INTERSECTION, DIFFERENCE şi INCLUSION sunt implementaţi în limbaj. SEQUEL este singurul limbaj relaţional care are integrată închiderea tranzitivă. Limbajul permite reactualizări asupra bazelor (UPDATE, INSERT, DELETE) şi calculul unor funcţii elementare (COUNT, SUM, AVG, MAX, MIN). Conceptul de partiţionare a fost de asemenea introdus în SEQUEL şi realizat cu ajutorul clauzelor GROUP BY şi HAVING.

O extensie comercială a acestui limbaj, adoptată de aproape toate SGBD şi considerată drept standard în prelucrarea datelor relaţionale, este SQL.

Page 128: CURS BD Combinat

69

Limbaje predicative Limbajele predicative se bazează pe calculul predicatelor. Cererile

sunt exprimate sub forma unor mulţimi de tupluri sau valori pentru care se specifică, sub forma unor predicate, proprietăţile pe care trebuie să le îndeplinească.

QUEL este un limbaj predicativ orientat pe tupluri, utilizat de sistemul INGRES. Limbajul QUEL poate fi utilizat independent sau inclus în limbajul de programare C. Limbajul este caracterizat de:

• declararea unei variabile tuplu pentru fiecare relaţie (prin RANGE),

• absenţa cuantificatorilor în expresii, • utilizarea unor operatori speciali pe mulţimi, • integrarea operaţiilor aritmetice.

Exemplu. Să se listeze numele cititorilor care au împrumutat cărţi scrise de

Cioran. RANGE OF a IS carte RANGE OF b IS cititor RANGE OF v IS imprumuta RETRIEVE b.nume WHERE (b.codec = v.codec) AND (v.codel = a.codel) AND (a.autor = ’Cioran’)

Limbajul acceptă comenzi de inserare (APPEND), reactualizare (REPLACE), suprimare (DELETE), precum şi funcţii de calcul (MAX, MIN, SUM, COUNT, AVG). Cuantificatorul existenţial este reprezentat implicit prin declaraţia RANGE, iar cuantificatorul universal este simulat cu ajutorul funcţiei COUNT.

Exemplu. Să se listeze numele cititorilor care au împrumutat toate cărţile din

bibliotecă scrise de Cioran. RANGE OF a IS carte RANGE OF b IS cititor RANGE OF v IS imprumuta RETRIEVE b.nume WHERE COUNT (v.codel WHERE (b.codec=v.codec)

Page 129: CURS BD Combinat

70

AND (a.codel=v.codel) AND (a.autor=’Cioran’)) = COUNT (a.codel WHERE (a.autor=’Cioran’))

QBE (Query By Example) este un limbaj predicativ orientat pe domenii. Limbajul dispune de primitive de programare grafică a cererilor de date şi a fost conceput pentru utilizatorii neiniţiaţi. Utilizatorii, pentru a manipula datele, completează o mulţime de câmpuri predefinite pe un ecran special.

Exemplu. Să se obţină titlurile cărţilor scrise de Cioran, din care există în

bibliotecă mai mult de 10 exemplare.

Carte Codel Titlu Autor Pret Nrex Coded

P.X 'Cioran' >10

Dacă utilizatorul doreşte şi tipărirea, atunci indică rezultatul care îl interesează sub forma unei variabile domeniu (notată în acest exemplu prin X) prefixată de P (print).

Dacă condiţia care apare în interogare este complexă sau se doreşte simplificarea scrierii unei cereri, se poate utiliza o casetă specială (box condition) în care se introduce condiţia.

În limbaj sunt admise funcţiile COUNT, MAX, MIN, AVG, SUM, iar pentru eliminarea dublurilor a fost introdus operatorul UNIQUE.

Exemplu. Să se obţină pentru fiecare autor, preţul celei mai scumpe cărţi şi

numărul exemplarelor scrise de acesta, care să găsesc în bibliotecă (tabelul sortat!!!).

Carte Codel Titlu Autor Pret Nrex Coded GROUP BY MAX SUM

În QBE există posibilitatea de a crea o nouă relaţie care poate fi o schemă virtuală care reflectă modificările din relaţiile de bază sau o imagine în care modificările nu sunt stocate.

Exemplu. Codurile cărţilor scrise de Popa sau care au titlul „Geometrie“.

Page 130: CURS BD Combinat

71

Algebric: R1 = SELECT(carte, autor = 'Popa') R2 = SELECT(carte, titlu = Geometrie') R3 = R1 ∪ R2 Rezultat = PROJECT (R3, codel)

SEQUEL: SELECT codel FROM carte WHERE autor = ’Popa’ OR titlu = ’Geometrie’

QBE: Carte Codel Titlu Autor Pret Nrex Coded

P.X 'Popa' P.Y 'Geometrie'

Exemplu. Numele cititorilor care au împrumutat cel putin o carte scrisa de

Cioran. Algebric:

R1 = PROJECT(cititor, codec, nume) R2 = SELECT(carte, autor = 'Cioran') R3 = PROJECT(R2, codel) R4 = PROJECT(imprumuta, codel, codec) R5 = JOIN(R4, R3, codel) R6 = JOIN(R5, R1, codec) Rezultat = PROJECT(R6, nume)

QBE: Cititor Codec Nume Dep

Y P.X

Imprumuta Codel Codec Dataim Datares Dataef Z Y

Carte Codel Titlu Autor Pret Nrex Coded

Z 'Cioran' SEQUEL:

SELECT nume FROM cititor WHERE codec IS IN

Page 131: CURS BD Combinat

72

SELECT codec FROM imprumuta WHERE codel IS IN SELECT codel FROM carte WHERE autor = ’Cioran’

Utilizarea limbajelor de prelucrare a datelor relaţionale în contextul limbajelor de programare

Două abordări: • integrarea, • extensia. Integrarea LMD-ului într-un limbaj de programare. Se consideră limbajul de prelucrare independent de limbajul de

programare şi există construcţii speciale care permit utilizarea acestuia în limbajul gazdă. De exemplu, comenzile SQL pot fi integrate în limbajul PL/1. Ele sunt prefixate de caracterul $ pentru a le distinge de comenzile PL/1. Pentru a realiza integrarea, este necesară fie o precompilare a cererilor, fie o interpretare la execuţie. Precompilatoarele actuale acoperă majoritatea limbajelor semnificative existente. Alegerea unui precompilator particular depinde de domeniul aplicaţiei.

Extensia limbajului de programare cu un LMD Se consideră un limbaj de programare şi se realizează extensii ale

acestuia cu clauze specifice limbajelor de prelucrare a datelor. Un exemplu tipic este extensia PASCAL/R care permite definirea unui

nou tip de date, şi anume tipul RELATION. De exemplu, relaţia carte este definită:

TYPE car = RECORD codel: TEXTE; titlu: TEXTE; autor: TEXTE; nrex: INTEGER; pret: INTEGER; coded: TEXTE END; abc = RELATION OF car; VAR carte: abc;

Page 132: CURS BD Combinat

73

Exemplu. Să se obţină o relaţie având numele rezultat, ce conţine toate cărţile

scrise de Cioran care au preţul mai mare de 150000. VAR rezultat: abc;

… BEGIN

rezultat:=[]; FOR EACH x IN carte DO IF(x.autor = ’Cioran’) AND (x.pret >= 150000) THEN rezultat:=rezultat + [x]

END;

Relaţia rezultat poate fi construită şi direct prin atribuirea: rezultat := [EACH (x) IN carte: (x.autor = ’Cioran’) AND (x.pret >= 150000)];

Page 133: CURS BD Combinat

1

PROIECTAREA BAZELOR DE DATE RELAŢIONALE

3.1. Preliminarii

Modelul relaţional a fost conceput şi dezvoltat de E.F. Codd. El este

un model formal de organizare conceptuală a datelor, destinat reprezentării legăturilor dintre date, bazat pe teoria matematică a relaţiilor. Este modelul cel mai accesibil pentru utilizatorul bazei de date deoarece structura sa fizică este aceeaşi cu cea a datelor care trebuie prelucrate. În general, datele se prezintă sub forma unor tabele (relaţii) în care liniile constituie înregistrări, iar coloanele sunt atribute ce caracterizează aceste înregistrări.

Obiectivele modelului relaţional, considerate de către E.F. Codd, sunt următoarele:

• să permită un grad înalt de independenţă a datelor; • să furnizeze baze solide pentru tratarea semanticii, coerenţei şi

problemelor de redundanţă a datelor; • să permită dezvoltarea limbajelor de prelucrare a datelor. Spre deosebire de modelul ierarhic şi reţea unde apar două elemente,

şi anume tipul entităţii şi relaţiile dintre două entităţi, modelul relaţional este alcătuit numai din relaţii şi prin urmare, orice interogare asupra bazei de date este tot o relaţie. Modelul relaţional a fost definit cu o deosebită rigoare matematică, furnizând un mijloc performant de studiu al proprietăţilor logice ale unui sistem de baze de date. Referitor la partea de prelucrare a datelor, modelul relaţional este orientat spre mulţimi, în timp ce modelele ierarhic şi reţea sunt orientate spre fişiere.

Pentru modelele ierarhic şi reţea, programatorul trebuie să proiecteze programe care să acceseze baza de date, înregistrare cu înregistrare, utilizând legături fizice între înregistrări. Modelul relaţional a permis introducerea unor limbaje neprocedurale de prelucrare a datelor. Modelul relaţional nu este orientat spre sistemul de calcul, deci modelul nu include regulile, structurile şi operaţiile referitoare la implementarea fizică a unui sistem de baze de date. De fapt, unul dintre obiectivele modelului este acela de a face o distincţie între aspectele fizice şi logice ale unei baze de date (independenţa datelor).

Page 134: CURS BD Combinat

2

Modelul relaţional, deşi are unele imperfecţiuni, a fost adoptat în ultimele decenii de majoritatea programatorilor din domeniu, tocmai datorită acestor trei calităţi: este simplu, riguros din punct de vedere matematic şi nu este orientat spre sistemul de calcul.

Definirea unui SGBD relaţional impune analizarea caracteristicilor pe care trebuie să le prezinte un model de date pentru a fi considerat relaţional. Există diferite modalităţi pentru a defini acest concept:

• prezentarea datelor în tabele supuse anumitor operaţii de tip proiecţie, selecţie, reuniune, compunere, intersecţie etc. (definiţie simplă);

• un sistem de baze de date ce suportă un limbaj de tip SQL – Structured Query Language (definiţie practică);

• un sistem de baze de date care respectă principiile modelului relaţional introdus de E.F. Codd (definiţia folosită cel mai frecvent).

E.F. Codd a publicat un set de 13 reguli, numite reguli de fidelitate, în raport cu care un SGBD poate fi apreciat ca relaţional. Ulterior, cele 13 reguli de fidelitate ale lui Codd au fost extinse la un număr de 100. Trebuie remarcat că nu există un SGBD care respectă toate regulile definite de Codd. Nu trebuie să apreciem un SGBD ca fiind relaţional sau nu, ci măsura în care acesta este relaţional, deci numărul regulilor de fidelitate pe care le respectă.

3.2. Caracterisicile modelului relaţional Dintre principalele caracteristici ale modelului relaţional se remarcă: • nu există tupluri identice; • ordinea liniilor şi a coloanelor este arbitrară; • articolele unui domeniu sunt omogene; • fiecare coloană defineşte un domeniu distinct şi nu se poate repeta

în cadrul aceleiaşi relaţii; • toate valorile unui domeniu corespunzătoare tuturor cazurilor nu

mai pot fi descompuse în alte valori (sunt atomice). Comparativ cu celelalte modele de date, modelul relaţional are

avantaje remarcabile dintre care se remarcă: • fundamentarea matematică riguroasă, • independenţa fizică a datelor, • posibilitatea filtrărilor,

Page 135: CURS BD Combinat

3

• existenţa unor structuri de date simple, • minimizarea redundanţei, • supleţea în comunicarea cu utilizatorul neinformatician etc. Ca limite ale modelului relaţional pot fi menţionate: • rămâne totuşi redundanţă, • ocupă spaţiu, • apar fenomene de inconsistenţă, • nu există mecanisme pentru tratarea optimă a cererilor recursive, • nu lucrează cu obiecte complexe, • nu există mijloace perfecţionate pentru exprimarea constrângerilor

de integritate, • nu realizează gestiunea cunoştinţelor etc. Un model relaţional este caracterizat de trei elemente: • structura relaţională a datelor (caracteristica structurală), • operatorii modelului relaţional (caracteristica de asigurare a

prelucrării), • regulile de integritate care guvernează folosirea cheilor în model

(caracteristica de asigurare a integrităţii). Aceste trei elemente corespund celor trei componente ale ingineriei

software: informaţie, proces, integritate.

3.2.1. Structura datelor Conceptelor descrise formal drept relaţie, tuplu sau atribut, le

corespund uzual denumirile tabel, linie sau coloană, iar fizic fişier, înregistrare sau câmp.

Un domeniu este o mulţime de valori care se poate defini fie enumerând elementele componente, fie specificând o proprietate distinctivă a valorilor. Domeniului îi corespunde, atât uzual cât şi fizic, conceptul de tip de date.

Un tip de date este o mulţime de valori, şi anume mulţimea tuturor valorilor care satisfac o anumită constrângere a tipului. Un tip de date poate fi definit de către sistem sau de către utilizator. De asemenea, fiecare tip are asociat un set de operatori care pot fi aplicaţi valorilor tipului respectiv. Tipurile constrâng operaţiile prin faptul că este necesar ca operanzii unei operaţii să fie de tipurile definite pentru operaţia respectivă.

Page 136: CURS BD Combinat

4

Tipurile pot fi oricât de simple sau de complexe. Se pot distinge tipuri de date ale căror valori sunt numere, şiruri, date calendaristice, înregistrări audio sau video, hărţi, puncte geometrice etc.

Orice tip de date este scalar (atomic, încapsulat) sau nescalar. Tipul nescalar are componente vizibile utilizatorului şi direct accesibile.

Trebuie făcută distincţia între un tip şi reprezentarea sa fizică, deoarece tipurile sunt legate de model, iar reprezentarea fizică este un aspect legat de implementare.

Fie D1, D2, ..., Dn domenii finite, nu neapărat disjuncte. Produsul cartezian D1 × D2 × ... × Dn al domeniilor D1, D2, ..., Dn este definit de mulţimea tuplurilor (V1, V2, ..., Vn), unde V1 ∈ D1, V2 ∈ D2, ..., Vn ∈ Dn. Numărul n defineşte aritatea tuplului.

O relaţie R pe mulţimile D1, D2, ..., Dn este o submulţime a produsului cartezian D1 × D2 × ... × Dn, deci este o mulţime de tupluri. Există un alt mod de a defini relaţia, şi anume ca o mulţime finită de funcţii. Asociem fiecărui domeniu Di un atribut Ai şi definim relaţia R = {f1, f2, ..., fm}, unde fi : {A1, A2, ..., An} → D1 ∪ D2 ∪ ... ∪ Dn şi fi(Aj) ∈ Dj pentru orice valori ale lui i şi j. În această definiţie nu mai este restricţionată ordinea.

Definirea unei relaţii ca o mulţime de tupluri sau ca o mulţime de funcţii se referă la mulţimi care variază în timp (se adaugă, se şterg sau se modifică elemente). Pentru a caracteriza o relaţie este necesară existenţa unui element invariant în timp, iar acest invariant este dat de structura relaţiei (schema relaţională). Mulţimea numelor atributelor corespunzătoare unei relaţii R defineşte schema relaţională a relaţiei respective. Vom nota schema relaţională prin R(A1, A2, ..., An).

De exemplu, pentru modelul de date analizat în această lucrare, VESTIMENTATIE(cod_vestimentatie, cod_designer, cod_model, cod_prezentare, denumire, valoare, descriere) reprezintă o schemă relaţională.

Putem reprezenta o relaţie printr-un tabel bidimensional în care fiecare linie corespunde unui tuplu şi fiecare coloană corespunde unui domeniu din produsul cartezian. O coloană corespunde unui atribut. Numărul atributelor defineşte gradul relaţiei, iar numărul de tupluri din relaţie defineşte cardinalitatea relaţiei.

Bazele de date relaţionale sunt percepute de către utilizatori ca o mulţime de tabele. Tabelul reprezintă structura logică dintr-un sistem relaţional, nu structura fizică. La nivel fizic, sistemul poate stoca datele în diferite moduri, folosind fişiere secvenţiale, indexări, înlănţuiri de pointeri etc., cu condiţia să poată realiza corespondenţa dintre reprezentarea stocată şi tabelele de la nivelul logic.

Page 137: CURS BD Combinat

5

Bazele de date relaţionale respectă principiul informaţiei (principiul reprezentării uniforme), care afirmă că întregul conţinut informaţional al bazei este reprezentat într-un mod unic, şi anume, ca valori explicite ale celulelor unui tabel. Această modalitate de reprezentare este singura disponibilă, la nivel logic, într-un sistem relaţional.

Când se inserează tupluri într-o relaţie, de multe ori valoarea unui atribut este necunoscută sau nu este aplicabilă tuplului respectiv. Pentru a reprezenta valoarea acestui atribut a fost introdusă o valoare convenţională în relaţie, şi anume null. De fapt, null nu reprezintă o valoare, ci absenţa uneia. Un null nu este acelaşi lucru cu o valoare numerică egală cu zero sau cu un şir de caractere vid. Zerourile şi spaţiile libere (şirul vid) sunt valori, pe când null semnifică absenţa unei valori. Prin urmare, null trebuie tratat în mod diferit faţă de alte valori şi trebuie înţeles că termenul „valoare nulă“ este depreciativ.

Evident, este necesară o aritmetică şi o logică (polivalentă) nouă (fig.3.1) care să cuprindă acest element. De exemplu, ce valoare are „10 > null“ ? Răspunsul este null. În general, rezultatul operaţiilor aritmetice sau logice este null când unul din operanzi este null. Prin urmare, „null = null“ are valoarea null, iar ¬ null este null.

Întroducerea null-urilor în modelul relaţional constituie o problemă controversată, deşi Codd tratează null ca parte integrantă a modelului. Alţii consideră această abordare greşită şi prematură. Trebuie remarcat că nu toate sistemele relaţionale acceptă null-urile.

AND T F Null OR T F Null

T T F Null T T T T

F F F F F T F Null

Null Null F Null Null T Null Null

Fig. 3.1. Tabele de adevăr pentru operatorii AND şi OR

Tabelul vizualizare (view, filtru, relaţie virtuală, vedere) constituie un filtru asupra tabelului iniţial, care conţine numai informaţia necesară unei anumite abordări sau aplicaţii. De fapt, vizualizarea este o expresie relaţională căreia i se atribuie un nume.

Page 138: CURS BD Combinat

6

Dacă baza de date conţine tabele reale depuse pe disc, o vizualizare este virtuală deoarece datele pe care le conţine nu sunt în realitate memorate într-o bază de date. Este memorată numai definiţia vizualizării. Vizualizarea nu este definită explicit, ca relaţiile de bază, prin mulţimea tuplurilor componente, ci implicit, pe baza altor relaţii obţinute prin intermediul unor expresii relaţionale. Stabilirea efectivă a tuplurilor care compun vizualizarea se realizează prin evaluarea expresiei atunci când utilizatorul se referă la acest tabel.

Utilizarea vizualizărilor este avantajoasă, deoarece: • asigură securitatea tabelului iniţial (care este protejat de ştergeri,

modificări etc.) prin capacitatea de a ascunde datele; • permit vizualizarea simultană a aceloraşi date de către diverşi

utilizatori; • sunt concise, punând la dispoziţie capacităţi „macro“; • asigură independenţa logică faţă de date (imunitatea programelor

de aplicaţie faţă de modificările din structura logică a bazei de date).

Există totuşi limitări în utilizarea acestor tabele, în special legate de problema reactualizării. De exemplu, coloanele calculate nu pot fi reactualizate. De asemenea, inserarea, reactualizarea şi ştergerea nu sunt, în general, recomandate şi sunt permise numai cu anumite restricţii care sunt specifice fiecărui SGBD. De exemplu, Oracle9i rezolvă problema dificilă a reactualizării vizualizărilor, în anumite situaţii, utilizând o clasă specială de declanşatoare (TRIGGER de tip INSTEAD OF).

3.2.2. Reguli de integritate Regulile de integritate sunt aserţiuni pe care datele conţinute în baza

de date trebuie să le satisfacă. Trebuie făcută distincţia între regulile structurale care sunt inerente modelării datelor şi regulile de funcţionare (comportament) care sunt specifice unei aplicaţii particulare.

Există trei tipuri de constrângeri structurale (de cheie, de referinţă, de entitate) ce constituie mulţimea minimală de reguli de integritate pe care trebuie să le respecte un SGBD relaţional. Restricţiile de integritate minimale sunt definite în raport cu noţiunea de cheie a unei relaţii.

O mulţime minimală de atribute ale căror valori identifică unic un tuplu într-o relaţie reprezintă o cheie pentru relaţia respectivă.

Page 139: CURS BD Combinat

7

Prin urmare, o cheie a unei relaţii R este o mulţime K de atribute, astfel încât:

(1) pentru orice două tupluri t1, t2 ale lui R ⇒ t1(K) ≠ t2(K); (2) nu există nicio submulţime proprie a lui K având proprietatea (1).

Fiecare relaţie are cel puţin o cheie. Dacă există diferite chei posibile, ele se numesc chei candidat. Una dintre cheile candidat va fi aleasă pentru a identifica efectiv tupluri şi ea va primi numele de cheie primară. Cheia primară nu poate fi reactualizată. Restul cheilor candidat vor purta numele de chei alternative sau secundare. Atributele care reprezintă cheia primară pot fi subliniate sau urmate de semnul „#“.

O cheie identifică linii şi este diferită de un index care localizează liniile. O cheie secundară este folosită ca index pentru a accesa tupluri. Un grup de atribute din cadrul unei relaţii care conţine o cheie a relaţiei poartă numele de supercheie.

Fie schemele relaţionale R1(P1, S1) şi R2(S1, S2), unde P1 este cheie primară pentru R1, S1 este cheie secundară pentru R1, iar S1 este cheie primară pentru R2. În acest caz, vom spune că S1 este cheie externă (cheie străină) pentru relaţia R1.

De exemplu, cod_casa_moda este cheie externă pentru relaţia CREATOR şi este cheie primară pentru relaţia CASA_MODA. Cheia primară poate conţine cheia externă. De exemplu, relaţia ACCESORIU are cheia primară formată din atributele cod_accesoriu şi cod_vestimentatie, iar atributul cod_vestimentatie fiind cheie primară în relaţia VESTIMENTATIE, devine cheie externă în relaţia ACCESORIU.

Modelul relaţional respectă trei reguli de integritate structurală. Regula 1 – unicitatea cheii. Cheia primară trebuie să fie unică şi

minimală. Regula 2 – integritatea entităţii. Atributele cheii primare trebuie să

fie diferite de null. Regula 3 – integritatea referirii. O cheie externă trebuie să fie ori

null în întregime, ori să corespundă unei valori a cheii primare asociate.

Uneori constrângerile de integritate sunt implementate procedural, folosind o clasă de proceduri (declanşatori) precompilate, stocate împreună cu baza de date şi invocate automat ori de câte ori are loc un anumit eveniment. Aceste proceduri nu reprezintă o modalitate recomandată de implementare a constrângerilor de integritate deoarece, fiind proceduri, sunt

Page 140: CURS BD Combinat

8

mai dificil de optimizat de către sistem şi, de asemenea, sunt executate doar atunci când apare evenimentul specificat (declanşator). Declanşatorii trebuie utilizaţi cu precauţie, sau deloc, dacă există o modalitate alternativă de rezolvare a problemei respective. Ei pot crea probleme practice datorită fenomenului „declanşatori în cascadă“ (lanţ de declanşatori). De asemenea, dacă acelaşi eveniment determină pornirea mai multor declanşatori diferiţi, atunci ordinea în care pornesc poate fi importantă sau poate fi chiar nedefinită. Există posibilitatea ca un declanşator să se declanşeze singur, recursiv. Dacă sunt disponibile, soluţiile declarative sunt de preferat celor procedurale.

3.2.3. Operatorii modelului relaţional Operatorii modelului relaţional definesc operaţiile care se pot efectua

asupra relaţiilor în scopul realizării funcţiilor de prelucrare asupra bazei de date. Modelul relaţional oferă două mulţimi de operatori pe relaţii, şi anume: algebra relaţională şi calculul relaţional. La rândul său, calculul relaţional este de două tipuri: orientat pe tupluri sau orientat pe domenii.

Operatorii algebrei relaţionale sunt fie operatori tradiţionali pe mulţimi (UNION, INTERSECT, PRODUCT, DIFFERENCE), fie operatori relaţionali speciali (PROJECT, SELECT, JOIN, DIVISION). Aceşti operatori vor fi analizaţi în secţiunea 3.4.

Calculul relaţional reprezintă o adaptare a calculului predicatelor la domeniul bazelor de date relaţionale. Ideea de bază este de a identifica o relaţie cu un predicat. Pe baza unor predicate iniţiale, prin aplicarea unor operatori ai calculului cu predicate (conjuncţia, disjuncţia, negaţia, cuantificatorul existenţial şi cel universal) se pot defini noi relaţii. Variabilele care apar în construcţiile calculului relaţional orientat pe domenii sunt variabile definite asupra domeniilor, iar cele care apar în construcţiile calculului relaţional orientat pe tupluri sunt variabile definite asupra relaţiilor, adică valorile acestora reprezintă tupluri.

Echivalenţa dintre algebra relaţională şi calculul relaţional a fost demonstrată de J.D.Ullman. Această echivalenţă arată că orice relaţie posibil de definit în algebra relaţională poate fi definită şi în cadrul calcului relaţional, şi reciproc.

Page 141: CURS BD Combinat

9

3.3. Proiectarea modelului relaţional Problema proiectării bazelor de date poate fi enunţată în următoarea

manieră: fiind dat un volum de informaţii care trebuie reprezentat într-o bază de date, cum se poate alege o structură logică adecvată pentru acesta?

Proiectarea bazelor de date este mai mult o artă, decât o ştiinţă. Există câteva principii ştiinţifice care pot fi invocate pentru a rezolva problema, dar există multe aspecte legate de proiectare pe care aceste principii nu le abordează şi evident, nu le rezolvă. Teoreticienii şi practicienii au propus metodologii de proiectare mai mult sau mai puţin riguroase, dar găsirea proiectării logice optime rămâne o problemă complexă şi dificilă. Pot exista criterii obiective care să favorizeze o abordare în raport cu celelalte. În capitolul 2 s-a prezentat o abordare (proiectarea modelului E/R) care are meritul că este frecvent utilizată în practică.

În practică, se încearcă obţinerea unei scheme conceptuale corecte, adică realizarea proiectării logice abstracte independent de hardware, de sistemul de operare, de SGBD, de limbaj, de utilizator etc. Este importantă atât obţinerea structurilor de date corecte, cât şi realizarea integrităţii datelor. De asemenea, trebuie ca designul să fie robust, în sensul că nu va fi invalidat prin ivirea unor noi cerinţe ale aplicaţiei, care nu au fost prevăzute în momentul proiectării iniţiale.

Pentru rafinarea proiectării modelului de date, pentru obţinerea schemei conceptuale a bazei de date relaţionale, se pleacă de la o formă de modelare semantică specială a datelor, mai precis de la diagrama E/R.

Ideea generală este de a reprezenta entităţile şi legăturile dintre acestea sub forma unor tabele speciale (relaţii). Vor fi prezentate 9 reguli care arată maniera în care se transformă entităţile, relaţiile şi atributele acestora, în vederea obţinerii schemei conceptuale.

Ca formalism, în diagrama conceptuală, simbolul „ד indică plasamentul cheii externe. Dacă simbolul este subliniat („ד), se exprimă şi faptul că respectiva cheie externă este conţinută în cheia primară.

Page 142: CURS BD Combinat

10

3.3.1. Transformarea entităţilor

Entităţile independente devin tabele independente. Cheia primară nu conţine chei externe. De exemplu, entitatea independentă PREZENTARE generează un tabel independent pentru care atributul cod_prezentare reprezintă cheia primară.

Entităţile dependente devin tabele dependente. Cheia primară a entităţilor dependente conţine cheia primară a entităţii de care depinde (cheie externă) plus unul sau mai multe atribute adiţionale. De exemplu, cheia primară a entităţii dependente ACCESORIU este formată din atributul cod_vestimentatie, care reprezintă cheia primară a entităţii de care depinde (VESTIMENTATIE), plus atributul adiţional cod_accesoriu.

Subentităţile devin subtabele. Cheia externă se referă la supertabel, iar cheia primară este această cheie externă. De exemplu, cheia primară a subentităţii MODEL este cod_angajat care este o cheie externă (cheie primară a entităţii ANGAJAT_TEMP).

3.3.2. Transformarea relaţiilor

Relaţiile 1:1 şi 1:n devin chei externe. De exemplu, relaţia creeaza (CREATOR_creeaza_VESTIMENTATIE) devine coloană în tabelul VESTIMENTATIE. Atributul cod_creator, care este cheie primară în tabelul CREATOR, va fi cheie externă în tabelul VESTIMENTATIE. Relaţia 1:1 plasează cheia externă în tabelul cu mai puţine linii.

Relaţia m:n devine un tabel special, numit tabel asociativ, care are două chei externe pentru cele două tabele asociate. Cheia primară este compunerea acestor două chei externe plus eventuale coloane adiţionale. Un tabel asociativ se desenează punctat. De exemplu, relaţia participa (CASA_MODA_participa_PREZENTARE), care este de tip m:n, devine tabel asociativ având cheia primară formată din atributele cod_casa_moda şi cod_prezentare.

Relaţiile de tip trei devin tot tabele asociative. De exemplu, relaţia primeste ce leagă entităţile ANGAJAT_TEMP, PREZENTARE şi CASA_MODA, devine tabel asociativ. Cheia primară a tabelului este compunerea a trei chei externe: cod_angajat, cod_casa_moda

Page 143: CURS BD Combinat

11

şi cod_prezentare. Practic, în acest caz, este preferabil să fie introdusă o cheie primară artificială.

3.3.3. Transformarea atributelor

Un atribut singular devine o coloană. Atributele multiple devin tabele dependendente ce conţin cheia

primară a entităţii şi atributul multiplu. Cheia primară este formată dintr-o cheie externă, plus una sau mai multe coloane adiţionale. De exemplu, o persoană de contact poate cunoaşte mai multe limbi străine. În acest caz, atributul limba_cunoscuta este multiplu şi va genera tabelul dependent LIMBA.

Entităţile devin tabele, iar atributele lor devin coloane în aceste tabele. Ce devin atributele relaţiilor? Pentru relaţii 1:1 şi 1:n, atributele relaţiilor vor aparţine tabelului care conţine cheia externă, iar pentru relaţii m:n şi de tipul trei, atributele vor fi plasate în tabelele asociative.

Tabel Reprezintă Cheie primară

Independent entitate independentă nu conţine chei externe Subtabel subentitate o cheie externă

Dependent entitate dependentă o cheie externă şi una sau mai

multe coloane adiţionale Atribut multiplu

Asociativ relaţie m:n două sau mai multe chei externe

şi (opţional) coloane adiţionale relaţie de tip 3

Fig. 3.2. Clasificarea tabelelor

Page 144: CURS BD Combinat

12

Fig. 3.3. Diagrama conceptuală.

FIRMA_PUB

PUBLICITATE

PREZENTARE

ORGANIZATOR PERS CONTACT

LOCATIE

INFO CONTACT

LOCALIZARE

SPONSOR ANGAJAT_SEC

FIRMA_SEC

CASA MODA

CREATOR

VESTIMENTATIE

ACCESORIU

ANGAJAT_TEMP

MODEL

ISTORIC

SOC ASIG

AGENTIE are

refera are

creeaza

lucreaza

prezinta

face

asigura

are

se_face

face

organizeaza

are

are

are

are

prezinta lucreaza_la

×

× × ×

×

×

× ×

×

×

× ×

×

× ×

PRIMESTE ×

PARTICIPA

PAZA FINANTEAZA

LIMBA

cunoaste

Page 145: CURS BD Combinat

13

Cele patru tipuri de tabele (independente, dependente, subtabele şi asociative) se deosebesc prin structura cheii primare (figura 3.2.).

În figura 3.3 este prezentată diagrama conceptuală pentru proiectarea modelului relaţional comentat. Ea a fost construită din diagrama E/R prin adăugarea tabelelor asociative şi prin marcarea cheilor externe. În continuare va fi prezentată modalitatea efectivă de trecere de la diagrama entitate-relaţie la diagrama conceptuală pentru modelul de date real analizat în capitolul 2. Entităţile independente PERS_CONTACT, ORGANIZATOR, PREZENTARE, PUBLICITATE, SPONSOR, FIRMA_PUB, CASA_MODA, CREATOR, ANGAJAT_TEMP, ACCESORIU, LOCALIZARE, FIRMA_SEC, ANGAJAT_SEC, SOCIETATE_ASIG, INFO_CONTACT, AGENTIE, LOCATIE devin tabele independente. Cheile primare ale fiecărei entităţi au fost specificate în capitolul 2. Entităţile dependente ISTORIC şi ACCESORIU, care intervin în model, devin tabele dependente, iar cheile primare au fost specificate în capitolul 2. Subentitatea MODEL devine subtabel, având aceeaşi cheie primară cu superentitatea ANGAJAT_TEMP, adică atributul cod_angajat. Relaţiile de tip one-to-one şi one-to-many devin chei externe. Relaţia PERS_CONTACT_are_LOCALIZARE devine cheie externă în tabelul PERS_CONTACT. Dacă restricţia că o persoană de contact are o singură localizare este eliminată, atunci cardinalitatea relaţiei devine 1:n, iar atributul cod_pers_contact devine cheie externă în tabelul LOCALIZARE. Toate comentariile anterioare rămân valabile şi pentru entităţile FIRMA_PUB, FIRMA_SEC, PREZENTARE, ORGANIZATOR, CASA_MODA, SPONSOR, SOC_ASIG, CREATOR, LOCATIE, ANGAJAT_TEMP şi AGENTIE, care sunt legate de entitatea LOCALIZARE, permiţând astfel localizarea tuturor structurilor modelului. Relaţia PERS_CONTACT_are_INFO_CONTACT devine cheie externă în tabelul PERS_CONTACT. Dacă restricţia că pentru o persoană de contact există o singură posibilitate de contactare este eliminată, atunci cardinalitatea relaţiei devine 1:n, iar atributul cod_pers_contact devine cheie externă în tabelul INFO_CONTACT. Toate comentariile anterioare rămân valabile şi pentru entităţile FIRMA_PUB, FIRMA_SEC, ANGAJAT_TEMP, PREZENTARE, ORGANIZATOR, CASA_MODA, SPONSOR, SOC_ASIG, CREATOR, LOCATIE şi AGENTIE, care sunt legate de entitatea INFO_CONTACT, permiţând astfel accesarea tuturor structurilor modelului.

Page 146: CURS BD Combinat

14

Relaţia FIRMA_PUB_face_PUBLICITATE devine cheie externă în tabelul PUBLICITATE. Relaţia PUBLICITATE_se_face_pentru_PREZENTARE devine cheie externă în tabelul PUBLICITATE. Relaţia ORGANIZATOR_are_PERS_CONTACT devine cheie externă în tabelul PERS_CONTACT. Relaţia FIRMA_SEC_are_ANGAJAT_SEC devine cheie externă în tabelul ANGAJAT_SEC. Relaţia SOC_ASIG_asigura_PREZENTARE devine cheie externă în tabelul PREZENTARE. Relaţia CASA_MODA_lucreaza_CREATOR devine cheie externă în tabelul CREATOR. Relaţia CREATOR_creeaza_VESTIMENTATIE devine cheie externă în tabelul VESTIMENTATIE. Relaţia VESTIMENTATIE_are_ACCESORIU devine cheie externă în tabelul ACCESORIU. Relaţia MODEL_prezintă_VESTIMENTATIE devine cheie externă în tabelul VESTIMENTATIE. Relaţia CREATOR_face_ACCESORIU devine cheie externă în tabelul ACCESORIU. Relaţia PREZENTARE_prezinta_VESTIMENTATIE devine cheie externă în tabelul VESTIMENTATIE. Relaţia PREZENTARE_are_LOCATIE devine cheie externă în PREZENTARE. Relaţia MODEL_lucreaza_AGENTIE devine cheie externă în tabelul MODEL. Relaţia MODEL_are_ISTORIC devine cheie externă în tabelul ISTORIC. Relaţia ISTORIC_refera_AGENTIE devine cheie externă în tabelul ISTORIC. Relaţiile de tip many-to-many devin tabele asociative, având două chei externe pentru cele două tabele asociate. Relaţia ANGAJAT_SEC_paza_PREZENTARE devine tabel asociativ (PAZA). SPONSOR_finanteaza_PREZENTARE devine tabel asociativ (FINANTEAZA). CASA_MODA_participa_PREZENTARE devine tabel asociativ (PARTICIPA). Relaţiile de tipul trei (adică cele care leagă cel puţin trei entităţi) devin tabele asociative, având chei externe pentru fiecare dintre tabelele asociate.

Page 147: CURS BD Combinat

15

Relaţia primeste, care leagă entităţile ANGAJAT_TEMP, PREZENTARE şi CASA_MODA, devine tabel asociativ (PRIMESTE). În acest caz, s-a considerat o cheie primară artificială (atributul cod_primeste). Tabelul asociativ are drept chei externe atributele: cod_angajat, cod_casa_moda şi cod_prezentare. Atributele multiple devin tabele dependendente ce conţin cheia primară a entităţii şi atributul multiplu. Atributul limba_cunoscuta este multiplu (relativ la entitatea PERS_CONTACT) şi va genera tabelul dependent LIMBA. Acesta va avea drept cheie primară atributele cod_pers_contact şi limba_cunoscuta. Tabelul mai conţine trei atribute ce reprezintă nivelul de cunoaştere (scris, citit, vorbit) a limbii. Atributele entităţilor devin coloane în tabelele corespunzătoare. Pentru relaţii 1:1 şi 1:n, atributele relaţiilor vor aparţine tabelului care conţine cheia externă, iar pentru relaţii m:n şi de tipul trei, atributele vor fi plasate în tabelele asociative. Tabelul asociativ PRIMESTE va avea ca atribute, pe lângă cele ce constituie cheia primară, suma, data_achitare, cont, banca.

Schemele relaţionale corespunzătoare diagramei conceptuale din figura 3.3. sunt următoarele: MODEL(cod_angajat#, cod_agentie, inaltime, nr_pantof, info) ANGAJAT_TEMP(cod_angajat#, nume, prenume, data_nastere, nationalitate, sex, cod_localizare, cod_info_acces, tip) PUBLICITATE(cod_publicitate#, cod_firma_pub, cod_prezentare, tip, nume, suma, observatii) FIRMA_PUB(cod_firma_pub#, nume, info, director, observatii, cod_localizare, nume_pers_contact, cod_info_acces) ORGANIZATOR(cod_organizator#, denumire, banca, cont, cod_info_acces, informatii, cod_localizare) PERS_CONTACT(cod_pers_contact#, cod_organizator, nume, prenume, directie, cod_localizare, cod_info_acces) PREZENTARE(cod_prezentare#, denumire, data_start, data_final, cod_soc_asig, cod_organizator, cod_locatie) LOCATIE(cod_locatie#, denumire, tip, cod_localizare, cod_info_acces, capacitate) SPONSOR(cod_sponsor#, tip, nume, info, cod_localizare, cod_info_acces)

Page 148: CURS BD Combinat

16

CASA_MODA(cod_casa_moda#, nume, cifra_afaceri, proprietar, director, istoric, data_creare, cod_localizare, cod_info_acces) CREATOR(cod_creator#, nume, prenume, data_nastere, data_angajare, tip, mod_angajare, info, cod_casa_moda, cod_localizare, cod_info_acces) VESTIMENTATIE(cod_vestimentatie#, denumire, valoare, descriere, cod_creator, cod_model, cod_prezentare) ACCESORIU(cod_vestimentatie#, cod_accesoriu#, cod_creator, descriere, tip, valoare) AGENTIE(cod_agentie#, nume, data_creare, director, cifra_afaceri, info, cod_localizare, cod_info_acces) ISTORIC(cod_model#, data_angajare#, data_final, cod_agentie, conditii) LOCALIZARE(cod_localizare#, adresa, cod_postal, oras, tara) INFO_CONTACT(cod_info_acces#, telefon_fix, telefon_mobil, mail, fax) FIRMA_SEC(cod_firma_sec#, nume_firma, tip_servicii, director, cod_localizare, cod_info_acces, observatii) ANGAJAT_SEC(cod_angajat#, nume, prenume, data_nastere, specializare, nivel, observatii, cod_info_acces, cod_firma_sec) PAZA(cod_angajat#, cod_prezentare#, tip_paza, dotare, observatii) SOC_ASIG(cod_soc_asig#, conditii, suma, director, observatii, cod_localizare, nume_pers_contact_firma, cod_info_acces) PARTICIPA(cod_prezentare#, cod_casa_moda#, tip, data) FINANTEAZA(cod_sponsor#, cod_prezentare#, suma, banca, cont_emitent, data_emitere, cod_ordin_plata) PRIMESTE(cod_primeste#, cod_angajat, cod_prezentare, cod_casa_moda, data_achitare, suma, cont, banca) LIMBA(cod_pers_contact#, limba_cunoscuta#, niv_scris, niv_citit, niv_vorbit)

Page 149: CURS BD Combinat

17

3.4. Regulile lui Codd

Un SGBD relaţional îndeplineşte funcţiile unui SGBD, dar cu anumite

particularităţi care decurg din concepţia de organizare a datelor, respectiv din modelul relaţional. Fiecare SGBD relaţional implementează modelul relaţional într-o manieră proprie, care îl diferenţiază de restul sistemelor relaţionale. Caracterizarea unui SGBD relaţional se poate realiza la nivelul clasei sistemelor relaţionale, în sensul caracterizării globale, unitare în raport cu celelalte tipuri de SGBD-uri, sau la nivelul SGBD-ului relaţional individual în sensul caracterizării particularităţilor sale, în raport cu alte SGBD-uri relaţionale.

Realizarea funcţiilor SGBD-urilor relaţionale se face cu ajutorul unor mecanisme de lucru specifice, care le separă de sistemele nerelaţionale. Dintre mecanismele de lucru de care dispune un SGBD relaţional se pot menţiona:

• un limbaj relaţional pentru descrierea datelor la nivel fizic, logic şi conceptual;

• un limbaj relaţional pentru prelucrarea datelor; • mecanisme pentru controlul integrităţii semantice a datelor; • mecanisme pentru optimizarea cererilor de date; • mecanisme pentru asigurarea coerenţei datelor; • utilitare pentru generarea de rapoarte, pentru generarea de

aplicaţii, pentru generarea unor statistici referitoare la starea şi activitatea bazei de date etc.

În anul 1985, E.F. Codd a publicat un set de 13 reguli în raport cu care un sistem de gestiune a bazelor de date poate fi apreciat ca relaţional. Niciun sistem de gestiune a bazelor de date pus în vânzare pe piaţa comercială nu respectă absolut toate regulile definite de Codd, dar acest lucru nu împiedică etichetarea acestor sisteme drept relaţionale. Nu trebuie apreciat un SGBD ca fiind relaţional sau nu, ci măsura în care acesta este relaţional, deci numărul regulilor lui Codd pe care le respectă.

Regulile lui Codd au fost şi sunt cauza multor controverse. Unii le consideră doar un exerciţiu academic, alţii pretind că produsele lor satisfac majoritatea regulilor. De fapt, discuţiile în jurul acestor reguli au generat o cunoaştere mai bună a caracteristicilor esenţiale ale unui SGBD relaţional, atât din punctul de vedere al utilizatorilor, cât şi din cel al producătorilor de software.

Page 150: CURS BD Combinat

18

Regulile pot fi organizate în următoarele cinci domenii de funcţionalitate: reguli fundamentale, reguli structurale, reguli de integritate, reguli de prelucrare a datelor şi reguli privind independenţa datelor.

Regula 1 – regula gestionării datelor. Un SGBD relaţional trebuie să fie capabil să gestioneze o bază de date prin posibilităţile sale relaţionale. Practic, nicio implementare curentă de SGBD nu respectă această regulă, deoarece implementările conţin atât caracteristici relaţionale cât şi nerelaţionale.

Regula 2 – regula reprezentării informaţiei. Într-o bază de date relaţională, informaţia este reprezentată la nivel logic sub forma unor tabele ce poartă numele de relaţii. Este regula cea mai importantă şi conform lui Codd, un SGBD care nu respectă această regulă, nu poate fi considerat relaţional. Chiar şi meta-datele, conţinute în catalogul de sistem, trebuie să fie stocate ca relaţii.

Regula 3 – regula accesului garantat la date. Fiecare valoare dintr-o bază de date relaţională trebuie să poată fi adresată în mod logic printr-o combinaţie formată din numele relaţiei, valoarea cheii primare şi numele atributului.

Regula 4 – regula reprezentării informaţiei necunoscute. Un sistem relaţional trebuie să permită utilizatorului definirea unui tip de date numit „null“ pentru reprezentarea unei informaţii necunoscute la momentul respectiv. Într-un SGBD relaţional trebuie să putem face diferenţa între valoarea zero, un şir vid de caractere şi o valoare necunoscută.

Regula 5 – regula dicţionarelor de date. Asupra descrierii bazelor de date (informaţii relative la relaţii, vizualizări, indecşi etc.) trebuie să se poată aplica aceleaşi operaţii ca şi asupra datelor din baza de date. Descrierea bazei de date este reprezentată la nivel logic sub forma unor tabele care pot fi accesate în acelaşi mod ca şi datele efective. Prin urmare există un singur limbaj de prelucrare atât a meta-datelor, cât şi a datelor.

Regula 6 – regula limbajului de interogare. Trebuie să existe cel puţin un limbaj pentru prelucrarea bazei de date. În general, toate implementările SQL respectă această regulă. Limbajul permite utilizatorilor să definească relaţii şi vizualizări, să prelucreze datele interactiv sau prin intermediul programului, să regăsească informaţia şi să o poată actualiza, să verifice şi să corecteze datele de intrare, să implementeze constrângeri, să stabilească limite pentru tranzacţii etc.

Regula 7 – regula de actualizare a vizualizării. Un SGBD trebuie să poată determina dacă o vizualizare poate fi actualizată şi să stocheze rezultatul interogării, ce defineşte vizualizarea, într-un dicţionar de tipul

Page 151: CURS BD Combinat

19

unui catalog de sistem. Trebuie să existe un mecanism prin care să se poată determina dacă anumite vizualizări pot fi actualizate sau nu. Regula stabileşte că toate vizualizările care sunt teoretic reactualizabile pot fi reactualizate şi de către sistemul de gestiune. Nu au fost încă descoperite condiţiile pentru identificarea tuturor vizualizărilor care pot fi teoretic reactualizate.

Regula 8 – regula limbajului de nivel înalt. Capacitatea de tratare a unei relaţii de bază sau a unei vizualizări ca pe un singur operand se aplică atât pentru operaţiile de regăsire a datelor, cât şi asupra operaţiilor de inserare, actualizare şi ştergere a datelor. Un SGBD relaţional nu trebuie să oblige utilizatorul să caute într-o relaţie, tuplu cu tuplu, pentru a regăsi informaţia dorită. Operaţiile de prelucrare a datelor pot să fie aplicate atât în mod interactiv cât şi prin program, într-un limbaj gazdă.

Regula 9 – regula independenţei fizice a datelor. Programele de aplicaţie şi activităţile utilizatorilor nu depind de modul de depunere a datelor sau de modul de acces la date. Într-un SGBD relaţional trebuie să se separe aspectul fizic al datelor (stocare sau acces la date) de aspectul logic al datelor.

Regula 10 – regula independenţei logice a datelor. Programele de aplicaţie trebuie să fie transparente la modificările de orice tip efectuate asupra datelor. Orice modificare efectuată asupra unei relaţii nu trebuie să afecteze operaţiile de prelucrare a datelor.

Regula 11 – regula independenţei datelor din punct de vedere al inte-grităţii. Regulile de integritate trebuie să fie definite într-un sublimbaj relaţional de date, nu în programul de aplicaţie. SQL permite definirea de restricţii privind integritatea datelor şi stocarea lor în catalogul de sistem. Cu cât sunt mai multe constrângeri de integritate care pot fi întreţinute mai degrabă de către SGBD, decât în cadrul fiecărui program aplicaţie, cu atât garantarea calităţii datelor este mai bună.

Regula 12 – regula independenţei datelor din punct de vedere al distribuirii. Distribuirea datelor pe mai multe calculatoare dintr-o reţea de comunicaţii de date nu trebuie să afecteze programele de aplicaţie. ANSI-SQL nu menţionează regula în specificaţiile sale, deoarece este destul de greu de respectat. De observat că regula nu cere ca SGBD-ul să accepte o bază de date distribuite pentru a fi relaţional, dar stabileşte că limbajul de interogare va rămâne acelaşi atunci când se va introduce această capacitate, iar datele vor fi distribuite.

Page 152: CURS BD Combinat

20

Regula 13 – regula versiunii procedurale a unui SGBD. Orice componentă procedurală a unui SGBD trebuie să respecte aceleaşi restricţii de integritate ca şi componenta relaţională. De exemplu, dacă în partea de prelucrare a datelor a limbajului relaţional valoarea dintr-o coloană este de tipul not null, orice altă metodă procedurală de accesare a acestei coloane nu trebuie să permită introducerea unui null în această coloană. Prin urmare, regulile de integritate exprimate într-un limbaj relaţional de un anumit nivel nu pot fi distruse de un limbaj de nivel inferior.

Deoarece regulile lui Codd sunt prea severe pentru a fi respectate de un SGBD operaţional, s-au formulat criterii minimale de definire a unui SGBD relaţional.

Un SGBD este minimal relaţional dacă: • toate datele din cadrul bazei sunt reprezentate prin valori în tabele; • nu există pointeri observabili de către utilizator; • sistemul suportă operatorii relaţionali de proiecţie, selecţie şi

compunere naturală, fără limitări impuse din considerente interne. Un SGBD este complet relaţional dacă este minimal relaţional şi

satisface în plus condiţiile: • sistemul suportă restricţiile de integritate de bază (unicitatea cheii

primare, constrângerile referenţiale, integritatea entităţii); • sistemul suportă toate operaţiile de baza ale algebrei relaţionale.

Page 153: CURS BD Combinat

21

4. NORMALIZAREA RELAŢIILOR 4.1. Preliminarii

În procesul modelării unei baze de date relaţionale, o etapă importantă o

reprezintă normalizarea relaţiilor conceptuale. Aceasta presupune obţinerea de relaţii „moleculare“, fără a pierde nimic din informaţie, având scopul de a elimina redundanţa şi anomaliile reactualizării informaţiilor. Tehnica normalizării permite determinarea unei scheme conceptuale rafinate, printr-un proces de ameliorare progresivă a unei scheme conceptuale iniţiale a bazei de date relaţionale. După fiecare etapă de ameliorare, relaţiile bazei de date ating un anumit grad de perfecţiune, deci se află într-o anumită formă normală. Trecerea unei relaţii dintr-o formă normală în alta presupune eliminarea unui anumit tip de dependenţe nedorite, care sunt transformate în dependenţe admisibile, adică dependenţe care nu provoacă anomalii.

Procesul de ameliorare progresivă a schemei conceptuale trebuie să satisfacă următoarele cerinţe:

• să garanteze conservarea datelor, adică în schema conceptuală finală trebuie să figureze toate datele din cadrul schemei iniţiale;

• să garanteze conservarea dependenţelor dintre date, adică în schema finală fiecare dependenţă trebuie să aibă determinantul şi determinatul în schema aceleiaşi relaţii;

• să reprezinte o descompunere minimală a relaţiilor iniţiale, adică nici una din relaţiile care compun schema finală nu trebuie să fie conţinută într-o altă relaţie din această schemă.

Există două metode pentru a modela baze de date relaţionale fără anomalii sau pierderi de informaţie.

• Schema descompunerii pleacă de la o schemă relaţională universală care conţine toate atributele bazei de date. Schema se descompune prin proiecţii succesive în subrelaţii. Descompunerea se opreşte atunci când continuarea ei ar duce la pierderi de informaţie. Algoritmii de descompunere se bazează, în general, pe descrierea formală a dependenţei dintre atribute.

• Schema sintezei pleacă de la o mulţime de atribute independente. Utilizând proprietăţi de semantică şi legături între atribute se pot compune noi relaţii, astfel încât acestea să nu sufere de anumite anomalii pe care dorim să le evităm. Algoritmii de sinteză se bazează în general pe teoria grafurilor pentru a reprezenta legăturile între atribute.

Page 154: CURS BD Combinat

22

4.2. Dependenţe funcţionale Unul dintre conceptele principale asociate normalizării este cel de

dependenţă funcţională, care descrie formalizat legăturile dintre atribute. Dependenţa funcţională este o proprietate a semanticii atributelor dintr-o relaţie. Semantica indică modul în care sunt legate atributele şi specifică dependenţele dintre ele. Atunci când există o dependenţă funcţională, ea este specificată ca o constrângere între atribute.

O relaţie universală este o relaţie ce grupează toate atributele care modelează sistemul real cercetat. Fie E, mulţimea dependenţelor considerate de proiectantul bazei pentru o schemă relaţională sau pentru o relaţie universală.

Plecând de la o mulţime de proprietăţi formale ale dependenţelor, proprietăţi considerate drept reguli de deducţie (axiome), poate fi obţinută mulţimea maximală de dependenţe asociate lui E. Această mulţime defineşte închiderea lui E.

Fie R(A1, A2, ..., An) o schemă relaţională şi fie X, Y submulţimi de atribute ale lui R. X determină funcţional Y sau Y depinde funcţional (FD) de X, dacă pentru orice relaţie r (valoare curentă a lui R) nu există două tupluri care să aibă aceleaşi valori pentru atributele lui X şi să aibă valori diferite pentru cel puţin un atribut din Y. Cu alte cuvinte, o valoare a lui X determină unic o valoare a lui Y. Notaţia utilizată pentru desemnarea dependenţei funcţionale este X → Y. Altfel spus:

Definitie: Fie R un tabel relational si X si Y două submultimi de coloane ale lui R. Spunem că X determină functional pe Y sau că Y depinde functional de X dacă nu există două rânduri în tabelul R care să aibă aceleasi valori pentru coloanele din X si să aibă valori diferite pentru coloanele din Y.

Dependenţa funcţională X → Y reprezintă o constrângere aplicată tuplurilor relaţiei R, în sensul că oricare două tupluri din R care au aceeaşi valoare pentru X trebuie să ia aceeaşi valoare şi pentru Y.

Dacă pentru fiecare valoare a lui X există cel mult o valoare a lui Y, spunem că X este determinant iar Y este determinat.

Comparând toate submulţimile de atribute ale unei relaţii şi determinând legăturile dintre ele, se pot obţine toate dependenţele funcţionale pe care o relaţie le satisface. Această abordare nu este eficientă, consumând mult timp. Există posibilitatea ca, ştiind anumite dependenţe funcţionale şi utilizând reguli de deducţie, să fie obţinute toate dependenţele funcţionale.

Page 155: CURS BD Combinat

23

Fie X, Y, Z, W mulţimi de atribute ale unei scheme relaţionale R şi fie următoarele reguli de inferenţă (axiome) prin care noi dependenţe funcţionale pot fi deduse din cele date:

Ax1 – reflexivitate. X → X. Mai general, dacă Y ⊆ X, atunci X → Y. Ax2 – creşterea determinantului. Pot fi considerate trei formulări echi-valente pentru această axiomă.

1. Dacă X → Y şi X ⊆ Z, atunci Z → Y. 2. Dacă X → Y şi W ⊆ Z, atunci X ∪ Z → Y ∪ W. 3. Dacă X → Y atunci X ∪ Z → Y ∪ Z.

Ax3 – tranzitivitate. Dacă X → Y şi Y → Z, atunci X → Z.

4.3. Necesitatea normalizării Anomaliile care apar în lucrul cu baze de date se produc datorită

dependenţelor care există între datele din cadrul relaţiilor bazei. Aceste anomalii fac extrem de dificil lucrul cu baza de date. Aceste anomalii vor fi comentate cu ajutorul unui exemplu.

Se consideră o vizualizare (VP) asupra schemei relaţionale PREZENTARE ce conţine doar atributele cod_prezentare#, denumire, luna_start, cod_organizator. Aceste atribute reprezintă pentru fiecare prezentare de modă: codul acesteia, denumirea, luna în care începe prezentarea şi codul organizatorului.

Se consideră constrângerea: „toate prezentările de modă cu acelaşi nume încep în aceeaşi lună“.

cod_prezentar

e denumire luna_start cod_organizato

r 1 primavara mai 11 2 primavara mai 37 3 primavara mai 11 4 iarna martie 32 5 toamna august 11

Fig. 4.1. Vizualizarea VP

Datorită dependenţei introduse pot exista: anomalii la inserare,

modificare sau ştergere, redundanţă în date, probleme de reconexiune. 1. Redundanţă logică. Cuplul (primavara, mai) apare de trei ori.

Page 156: CURS BD Combinat

24

2. Anomalie la inserţie. Dacă se doreşte includerea unei prezentări de modă, care va incepe în luna aprilie şi va avea denumirea „veselie“, atunci perechea (veselie, aprilie) poate fi inserată în relaţia VP doar dacă se defineşte o nouă valoare pentru cheia primară.

3. Anomalie la ştergere. Dacă este ştearsă înregistrarea pentru care codul prezentării are valoarea 4, atunci se pierde informaţia că prezentarea având denumirea „iarna“ a început în luna martie.

4. Anomalie la modificare. Dacă se modifică luna de început a prezentării „primavara“ de la mai la februarie, atunci costul modificării este mare pentru a modifica toate înregistrările, iar dacă se modifică doar o înregistrare atunci constrângerea nu va mai fi verificată.

Anomaliile au apărut datorită dependenţei funcţionale (constrângerii) introduse anterior.

Normalizarea are drept scop: suprimarea redundanţei logice, evitarea anomaliilor la reactualizare, rezolvarea problemei reconexiunii. Există o teorie matematică a normalizării al cărei autor este E.F. Codd. Soluţia lui E.F. Codd este construirea unor tabele standard (forme normale).

Normalizarea este procesul reversibil de transformare a unei relaţii, în relaţii de structură mai simplă. Procesul este reversibil în sensul că nicio informaţie nu este pierdută în timpul transformării. O relaţie este într-o formă normală particulară dacă ea satisface o mulţime specificată de constrângeri.

Procesul normalizării se realizează plecând de la o relaţie universală ce conţine toate atributele sistemului de modelat, plus o mulţime de anomalii. Orice formă normală se obţine aplicând o schemă de descompunere.

4.4. Forme normale

Formele normale ale relaţiilor din baze de date relaţionale sunt

definite în raport cu anomaliile care pot apărea în lucrul cu aceste relaţii, deci în funcţie de dependenţele nedorite care se manifestă în cadrul relaţiilor.

Pe măsură ce relaţia este transformată în forme superioare, devine din ce în ce mai restrictivă ca format şi mai puţin expusă anomaliilor la reactualizare. Altfel spus:

Definitie: Normalizarea reprezintă procesul de descompunere a unui tabel relational în mai multe tabele care satisfac anumite reguli si care stochează aceleasi date ca si tabelul initial astfel încât să fie eliminate redundanta în date si anomaliile la actualizare.

Page 157: CURS BD Combinat

25

Prima formă normală (FN1)

O relaţie este în prima formă normală dacă fiecărui atribut care o

compune îi corespunde o valoare indivizibilă (atomică). În plus, un tuplu nu trebuie să conţină atribute sau grupuri de atribute repetitive.

Această formă figurează ca cerinţă minimală în majoritatea sistemelor relaţionale.

Algoritm AFN1 (aducerea unei relaţii în FN1 prin eliminarea atributelor compuse şi a celor repetitive)

1. Se introduc în relaţie, în locul atributelor compuse, componentele acestora.

2. Se plasează grupurile de atribute repetitive, fiecare în câte o nouă relaţie.

3. Se introduce în schema fiecărei noi relaţii de la pasul 2 cheia primară a relaţiei din care a fost extras atributul repetitiv.

4. Se stabileşte cheia primară a fiecărei noi relaţii create la pasul 2. Aceasta este compusă din cheia introdusă la pasul 3, precum şi din atribute proprii ale acestor noi relaţii.

Forma normală 2 (FN2) O relaţie R este în a doua formă normală dacă şi numai dacă: • relaţia R este în FN1; • fiecare atribut care nu este cheie (nu participă la cheia primară)

este dependent de întreaga cheie primară. A doua condiţie exprimă necesitatea dependenţei totale de cheia

primară. Această formă normală interzice manifestarea unor dependenţe funcţionale parţiale în cadrul relaţiei R.

Pentru a obţine o relaţie FN2 se poate aplica regula Casey-Delobel. Fie relaţia R(K1, K2, X, Y), unde K1 şi K2 definesc cheia primară, iar X şi Y sunt mulţimi de atribute, astfel încât K1 → X. Din cauza dependenţei funcţionale K1 → X care arată că R nu este în FN2, se înlocuieşte R (fără pierdere de informaţie) prin două proiecţii R1(K1, K2, Y) şi R2(K1, X). Caracterul reversibil al normalizării Prin caracter reversibil al normalizării se întelege faptul că descompunerea se face fără pierdere de informatie, adică tabelul initial poate fi reconstituit prin compunerea naturală, pe atribute comune, a tabelelor rezultate.

Page 158: CURS BD Combinat

26

Pentru un tabel R care se descompune prin proiectie în mai multe tabele: R1, R2, … Rn, conditia de descompunere fără pierdere de informatie presupune ca în urma operatiei de compunere naturală a tabelelor R1, R2, … Rn să se obtină tabelul R. Regula Casey-Delobel (caz particular de descompunere fără pierdere de informatie): Fie un tabel R(X, Y, Z) care se descompune prin proiectie în tabelele R1(X, Y) si R2(X, Z) unde prin X notăm setul de coloane comune ale tabelelor R1 si R2, iar prin Y si Z, coloanele specifice lui R1, respectiv R2. Conditia de descompunere fără pierdere de informatie presupune ca tabelul R să fie obtinut prin compunerea naturală a tabelelor R1 si R2. În SQL: SELECT R1.X, R1.Y, R2.Z FROM R1, R2 WHERE R1.X = R2.X

Algoritm AFN2 (aducerea unei relaţii în FN2 prin eliminarea depen-denţelor funcţionale parţiale din cadrul unor relaţii aflate în FN1)

1. Pentru fiecare dependenţă funcţională parţială se creează o nouă relaţie având schema formată din determinantul şi determinatul acestei dependenţe.

2. Se elimină din cadrul relaţiei iniţiale atributele care formează determinatul dependenţei parţiale.

3. Dacă în relaţia iniţială există mai multe dependenţe parţiale cu acelaşi determinant, pentru acestea se creează o singură relaţie cu schema formată din determinant (luat o singură dată) şi din determinaţii dependenţelor considerate.

4. Se determină cheia primară a fiecărei noi relaţii create. Aceasta va conţine atributele din determinantul dependenţei funcţionale parţiale care au stat la baza constituirii relaţiei.

5. Dacă noile relaţii create conţin dependenţe parţiale, atunci se face transfer la pasul 1, altfel procesul de aducere la FN2 s-a terminat.

Page 159: CURS BD Combinat

27

Exemplu Fie schema relaţională PARTICIPA (cod_prezentare#,

cod_casa_moda#, tip, data, data_start, data_final, denumire) Pentru relaţia PARTICIPA sunt adevărate dependenţele: {cod_prezentare} → {data_start, data_final, denumire} {cod_prezentare, cod_casa_moda} → {data, tip} Relaţia PARTICIPA este în FN1, dar nu este în FN2 deoarece

atributele data_start, data_final şi denumire nu depind de codul casei de modă, deci nu depind de întreaga cheie primară.

Pentru a obţine o relaţie în FN2 se aplică regula Casey Delobel şi relaţia PARTICIPA se proiectează în două relaţii:

PARTI1(cod_prezentare#, data_start, data_final, denumire) PARTI2(cod_prezentare#, cod_casa_moda#, data, tip).

Notă (reamintim C2): Entitatea PREZENTARE are atributele: cod_prezentare, denumire, data_start, data_final, cod_organizator, cod_soc_asig, cod_locatie. Entitatea CASA_MODA are atributele: cod_casa_moda, nume, cifra_afaceri, proprietar, director, istoric, data_creare, cod_localizare, cod_info_acces. Atribute ale relatiei PARTICIPA tip = variabilă de tip caracter, de lungime maximă 15, care reprezintă modalitatea în care o casă de modă participă la o prezentare, în sensul că poate fi organizator sau neorganizator. data = variabilă de tip dată calendaristică reprezentând ziua în care defilează modelele casei de modă. Atributul nu este multiplu, deoarece s-a presupus că defilarea unei case de modă are loc într-o singură zi. Alt Exemplu: Fie tabelul VANZARI care se foloseste la înregistrarea tranzactiilor unui magazin ce vinde articole la comandă. VANZARI (cod_client#, cod_comanda#, cod_articol#, nume_client, nr_telefon, data, nume_articol, cost_articol, cantitate) A1 C1 P1 Popescu 415355 08.10.04 camasa 400000 2 A1 C1 P3 Popescu 415355 08.10.04 tricou 200000 1

Page 160: CURS BD Combinat

28

A2 C2 P1 Ionescu 596322 09.10.04 camasa 400000 3 A2 C2 P3 Ionescu 596322 C2 09.10.04 tricou 200000 2 A2 C2 P2 Ionescu 596322 09.10.04 pantaloni 800000 1 A1 C3 P3 Popescu 415355 10.10.04 tricou 200000 3 A3 C4 P1 Marinescu 546229 C4 10.10.04 P1 camasa 400000 1 Tabelul de mai sus prezintă următoarele deficiente: a) redundante în date: - informatia (P1, camasa, 400000) este specificata de 3 ori - informatia (A1, Popescu, 415355) este specificata de 3 ori - informatia (A2, Ionescu, 196322) este specificata de 3 ori - s. a. m. d. b) anomalii la actualizare: - anomalie la insertie Dacă magazinul achizitionează un nou articol (P4, pantofi, 980000) informatia nu poate fi introdusă în tabel (un nou tuplu) pentru că s-ar introduce o valoare Null în cheia primară (cod_comanda). - anomalie la stergere Dacă este anulat articolul P2 în cadrul comenzii C2 se pierde informatia referitoare la numele si costul articolului respectiv. - anomalie la modificare Dacă se modifică numărul de telefon al unui client, modificarea trebuie facută în toate tuplurile (liniile) unde apare numele acelui client. În tabelul VANZARI există următoarele dependente functionale în care determinantul nu este cheie a tabelului: (cod_articol) → (nume_articol, cost_articol) (cod_comanda) → (data, cod_client, nume_client, nr_telefon) (cod_client) → (nume_client, nr_telefon)

Pentru a obţine o relaţie în FN2 se aplică regula Casey Delobel şi relaţia VANZARI se proiectează în trei relaţii:

VANZARI1(cod_articol# nume_articol, cost_articol) VANZARI2(cod_comanda#, data, cod_client, nume_client, nr_telefon) VANZARI3(cod_client #, nume_client, nr_telefon)

Page 161: CURS BD Combinat

29

Forma normală 3 (FN3) Intuitiv, o relaţie R este în a treia formă normală dacă şi numai dacă: • relaţia R este în FN2; • fiecare atribut care nu este cheie (nu participă la o cheie) depinde

direct de cheia primară. Fie R o relaţie, X o submulţime de atribute ale lui R şi A un atribut al

relaţiei R. A este dependent tranzitiv de X dacă există Y astfel încât X → Y şi Y → A (unde A nu aparţine lui Y şi Y nu determină pe X). De exemplu, dacă au loc dependenţele K1, K2, K3 → A1 şi K1, K2, A1 → A2, atunci K1, K2, K3 → K1, K2, A1 şi K1, K2, A1 → A2. Prin urmare, A2 este dependent tranzitiv de K1, K2, K3.

Formal, o relaţie R este în a treia formă normală dacă şi numai dacă: • relaţia R este în FN2; • fiecare atribut care nu este cheie (nu participă la o cheie) nu este

dependent tranzitiv de nicio cheie a lui R. A doua condiţie interzice utilizarea dependenţelor funcţionale tranzitive

în cadrul relaţiei R. Prin urmare, o relaţie este în FN3 dacă şi numai dacă fiecare

atribut care nu este cheie depinde de cheie, de întreaga cheie şi numai de cheie.

Pentru a obţine o relaţie FN3 se poate aplica regula de descompunere Casey-Delobel. Fie relaţia R(K, X1, X2, X3), unde atributul X2 depinde tranzitiv de K, iar K este cheia primară a lui R. Presupunem că K → X1 → X2. Din cauza dependenţei funcţionale X1 → X2 care arată că R nu este în FN3, se înlocuieşte R (fără pierdere de informaţie) prin două proiecţii R1(K, X1, X3) şi R2(X1, X2).

Dependenţa tranzitivă poate fi mai complexă. Fie K1 o parte a cheii K. Tranzitivitatea poate fi de forma K → Y → X2 unde Y = {K1, X1}. În acest caz, R poate fi descompusă în R1(K, X1, X3) şi R2(K1, X1, X2).

Algoritm AFN3 (aducerea unei relaţii FN2 în FN3 prin eliminarea dependenţelor funcţionale tranzitive)

1. Pentru fiecare dependenţă funcţională tranzitivă se transferă atributele implicate în dependenţa tranzitivă într-o nouă relaţie.

2. Se determină cheia primară a fiecărei noi relaţii create la pasul 1. 3. Se introduc în relaţia iniţială, în locul atributelor transferate, cheile

primare determinate la pasul 2.

Page 162: CURS BD Combinat

30

4. Se reanalizează relaţia iniţială. Dacă în cadrul ei există noi dependenţe tranzitive, atunci se face transfer la pasul 1, altfel procesul de aducere la FN3 s-a terminat.

Exemplu Fie schema relaţională PREZENT(cod_prezentare#, data_start,

data_final, denumire, cod_locatie, capacitate, cod_info_acces). Pentru relaţia PREZENT sunt adevărate dependenţele: {cod_prezentare} → {data_start, data_final, denumire, cod_locatie} {cod_locatie} → {capacitate, cod_info_acces} Relaţia PREZENT este în FN2, dar nu este în FN3 deoarece atributele

capacitate, cod_info_acces depind indirect de cheia primară, prin intermediul atributului cod_locatie.

Pentru a obţine o relaţie în FN3 se aplică regula Casey-Delobel şi relaţia PREZENT se proiectează în două relaţii, prin eliminarea dependenţelor funcţionale tranzitive. PREZENT1(cod_prezentare#, data_start, data_final, denumire, cod_locatie) PREZENT2(cod_locatie#, capacitate, cod_info_acces)

Forma normală Boyce-Codd (BCNF) Determinantul este un atribut sau o mulţime de atribute neredundante,

care constituie un identificator unic pentru alt atribut sau altă mulţime de atribute ale unei relaţii date.

Intuitiv, o relaţie R este în forma normală Boyce-Codd dacă şi numai dacă fiecare determinant este o cheie candidat.

Formal, o relaţie R este în forma normală Boyce-Codd dacă şi numai dacă pentru orice dependenţă funcţională totală X → A, X este o cheie a lui R.

Algoritm ABCNF (aducerea unei relaţii FN3 în BCNF prin eliminarea dependenţelor funcţionale ai căror determinanţi nu sunt chei candidat)

1. Dacă relaţia conţine unul sau cel mult două atribute, atunci nu pot exista dependenţe noncheie şi deci relaţia este în BCNF.

2. Dacă relaţia conţine mai mult de două atribute, se caută dacă ea conţine dependenţe noncheie. Dacă nu există astfel de dependenţe, relaţia este în BCNF.

3. Pentru fiecare dependenţă noncheie X → Y se creează două relaţii. Una dintre ele va avea schema formată din atributele {X, Y}, iar

Page 163: CURS BD Combinat

31

cealaltă va avea schema formată din toate atributele relaţiei iniţiale, mai puţin Y.

4. Se reiau paşii 1, 2, 3 pentru relaţiile obţinute la pasul 3. Exemplu Se consideră relaţia FINANTEAZA1, ce leagă entităţile

PREZENTARE şi SPONSOR. Ea are cardinalitatea many to many şi va genera un tabel asociativ. Se presupune că acest tabel are schema relaţională:

FINANTEAZA1(cod_prezentare#, cod_sponsor#, nume_prezentare, cod_ordin_plata).

Pentru exemplul analizat se presupune că numele prezentărilor sunt unice. Prin urmare, în orice moment fiecare prezentare are un cod unic şi un nume unic. Cheile candidat sunt {cod_prezentare, cod_sponsor}, respectiv {nume_prezentare, cod_sponsor}.

Între atributele relaţiei există dependenţele: {cod_prezentare, cod_sponsor} → {cod_ordin_plata} {cod_prezentare} → {nume_prezentare} Tabelul nu este în BCNF deoarece conţine doi determinanţi,

cod_prezentare şi nume_prezentare, care nu sunt chei candidat pentru tabelul respectiv. Ambele atribute sunt determinanţi deoarece fiecare îl determină pe celălalt.

Soluţia problemei constă în divizarea relaţiei în două proiecţii conform tehnicii Casey-Delobel.

PREZENTARE(cod_prezentare#, nume_prezentare) FINANTEAZA(cod_prezentare#, cod_sponsor#, cod_ordin_plata)

Forma normală 4 (FN4) Dacă BCNF elimină redundanţele datorate relaţiilor singulare, FN4

elimină redundanţele datorate relaţiilor m:n, adică datorate dependenţei multiple.

Intuitiv, o relaţie R este în a patra formă normală dacă şi numai dacă relaţia este în BCNF şi nu conţine relaţii m:n independente.

Exemplu Fie schema relaţională PERS_CONTACT(cod_pers#, limba_cunoscuta, nr_telefon). Se presupune că o persoană de contact poate cunoaşte mai multe limbi

străine şi poate avea mai multe numere de telefon. Între atributele relaţiei există multidependenţele:

Page 164: CURS BD Combinat

32

cod_pers# →→ limba_cunoscuta cod_pers# →→ nr_telefon. Pentru a aduce relaţia PERS_CONTACT (care este în BCNF) în FN4,

aceasta se va diviza în două proiecţii : PERS_CONTACT1(cod_pers#, limba_cunoscuta) PERS_CONTACT1(cod_pers#, nr_telefon).

Forma normală 5 (FN5) Semnificaţia lui FN5 este mai mult „academică“, ea apărând rar în

practică. A cincea formă normală îşi propune eliminarea redundanţelor care apar în relaţii m:n dependente. În general, aceste relaţii nu pot fi descompuse. S-a arătat că o relaţie de tip 3 este diferită de trei relaţii de tip 2. Există totuşi o excepţie, şi anume, dacă relaţia este ciclică.

Intuitiv, o relaţie R este în forma normală 5 dacă şi numai dacă: 1. relaţia este în FN4; 2. nu conţine dependenţe ciclice. Exemplu Se consideră o relaţie ce conţine informaţii despre creatori,

vestimentaţiile create de aceştia şi accesoriile corespunzătoare. Se consideră schema relaţională CREARE(cod_vestimentatie#, cod_creator#, cod_accesoriu#).

Se presupune că fiecare creator poate crea una sau mai multe vestimentaţii. Fiecare vestimentaţie poate fi creată de unul sau mai mulţi creatori. Similar, fiecare creator este responsabil de crearea unuia sau a mai multor accesorii, iar fiecare accesoriu este creat de unul sau mai mulţi creatori. Fiecare accesoriu apare în una sau mai multe vestimentaţii, iar fiecărei vestimentaţii i se ataşează unul sau mai multe accesorii.

Mai mult chiar, dacă creatorul C creează vestimentaţia V, iar accesoriul A este ataşat lui V, iar C este este responsabil de A, atunci C creează accesoriul A pentru vestimentaţia V.

Ţinând seama de constrângerile impuse modelului se obţin dependenţele:

{cod_vestimentatie#, cod_creator#} → {cod_accesoriu} {cod_vestimentatie#, cod_accesoriu#} → {cod_creator} {cod_accesoriu#, cod_creator#} → {cod_vestimentatie}. Datorită dependenţelor formulate anterior, relaţia nu este în FN5. Ea

se poate rupe prin proiecţie în trei relaţii: CREARE1(cod_vestimentatie#, cod_creator#)

Page 165: CURS BD Combinat

33

CREARE2(cod_vestimentatie#, cod_accesoriu#) CREARE3(cod_creator#, cod_accesoriu#). În acest caz, sunt evidente relaţiile: CREARE ≠ JOIN(CREARE1, CREARE2) CREARE ≠ JOIN(CREARE1, CREARE3) CREARE ≠ JOIN(CREARE2, CREARE3) CREARE = JOIN(JOIN(CREARE1, CREARE2), CREARE3). Concluzii: 1. FN1 → FN2 elimină redundanţele datorate dependenţei netotale a

atributelor care nu participă la o cheie, faţă de cheile lui R. Se suprimă dependenţele funcţionale care nu sunt totale.

2. FN2 → FN3 elimină redundanţele datorate dependenţei tranzitive. Se suprimă dependenţele funcţionale tranzitive.

3. FN3 → BCNF elimină redundanţele datorate dependenţei funcţionale. Se suprimă dependenţele în care partea stângă nu este o supercheie.

4. BCNF → FN4 elimină redundanţele datorate multidependenţei. Se suprimă toate multidependenţele care nu sunt şi dependenţe funcţionale.

5. FN4 → FN5 elimină redundanţele datorate dependenţei ciclice. Se suprimă toate join-dependenţele care nu sunt implicate de o cheie.

6. BCNF, FN4 şi FN5 corespund la regula că orice determinant este o cheie, dar de fiecare dată dependenţa cu care se defineşte deter-minantul este alta şi anume dependenţa funcţională, multidependenţa sau join-dependenţa.

7. Descompunerea unei relaţii FN2 în FN3 conservă datele şi dependenţele, pe când descompunerea unei relaţii FN3 în BCNF şi, respectiv, a unei relaţii BCNF în FN4 conservă doar datele.

Page 166: CURS BD Combinat

1

Partea a II-a. LIMBAJUL SQL În această tema: se prezintă conceptele limbajului SQL în 5 lecŃii,

după cum urmează: INTRODUCERE. Concepte SQL LECłIA 1. Limbajul de definire a datelor - DDL LECłIA 2. Limbajul de interogare a datelor - DQL LECłIA 3. Combinarea datelor din mai multe tabele –Uniuni LECłIA 4. Limbajul de manipulare a datelor – DML LECłIA 5. Limbajul de control al datelor – DCL

Introducere. Concepte SQL

SQL a devenit limbajul universal pentru bazele de date relaŃionale şi este acceptat de aproape toate sistemele SGBD moderne. Fără îndoială, acceptarea pe scară largă este rezultatul timpului şi eforturilor depuse pentru dezvoltarea caracteristicilor limbajului şi a standardelor, crescând nivelul de portabilitate a codului SQL între diferitele produseSGBD.

Ce este SQL?

SQL (Structured Query Language -limbaj structurat de interogare) este un limbaj standard folosit pentru crearea, actualizarea şi regăsirea informaŃiilor stocate în baze de date prin intermediul sistemelor de gestionare a bazelor de date ( SGBD-uri).

Numele limbajului poate fi pronunŃat pe litere (es-q-el) sau la fel ca şi cuvântul englezesc „sequel". O interogare (query) este o simplă cerere transmisă către baza de date, la care aceasta răspunde într-o anumită formă. SQL este limbajul folosit cel mai frecvent pentru interogarea bazelor de date. SQL este considerat un limbaj neprocedural sau declarativ, ceea ce înseamnă că-i spuneŃi calculatorului ce rezultate vreŃi, fară să-i spuneŃi cum să le obŃină. De exemplu, dacă vreŃi să obŃineŃi media numerelor de pe o coloană, folosiŃi funcŃia AVG. Nu este nevoie să număraŃi valorile din coloană şi să împărŃiŃi suma acestora la numărul obŃinut - procesorul limbajului SQL din SGBD se ocupă de toate aceste lucruri în locul dumneavoastră.

Este important să înŃelegi că SQL nu este un limbaj procedural, ca C, Pascal, Basic, FORTRAN, COBOL sau Ada. Un limbaj procedural foloseşte o serie de instrucŃiuni executate secvenŃial. De asemenea, limbajele procedurale includ instrucŃiuni care pot modifica secvenŃa de

Page 167: CURS BD Combinat

2

execuŃie, prin ramificarea la alte porŃiuni ale procedurii sau prin parcurgerea ciclică a unui set de instrucŃiuni din procedură. MulŃi producători de sisteme SGBD oferă extensii procedurale ale limbajului SQL de bază, cum ar fi Oracle PL/SQL (Procedural Language/SQL) sau Microsoft Transact-SQL, dar reŃineŃi că acestea sunt extensii SQL care formează noi limbaje - codul SQL pe care-1 conŃin rămâne neprocedural. De asemenea, SQL nu trebuie confundat cu limbajele orientate spre obiecte, precum Java şi C++.

Simplu spus, SQL este un limbaj neprocedural pentru gestionarea şi întreŃinerea bazelor de date relaŃionale, nu un limbaj potrivit pentru programarea generală a aplicaŃiilor, cum ar fi sistemele de prelucrare a comenzilor sau a plăŃilor.

SQL este deseori folosit în combinaŃie cu limbajele procedurale sau orientate spre obiecte menŃionate anterior pentru a manipula stocarea şi extragerea datelor, folosind instrucŃiuni din limbajul de programare cu destinaŃie generală pentru alte sarcini de programare, precum prezentarea datelor pe o pagină web sau furnizarea răspunsurilor la informaŃiile introduse de utilizatori de la tastatură sau mouse. Atunci când este necesară interacŃionarea cu baza de date, instrucŃiunile din limbajul procedural formează instrucŃiunea SQL, o transmit către SGBD în vederea prelucrării, primesc rezultatele returnate de SGBD şi le prelucrează într-un mod corespunzător.

Folosind SQL puteŃi transforma întrebări obişnuite :”Din ce oras sunt studentii notri?” în instrucŃiuni pe care le înŃelege soft-ul pentru baze de date: “SELECT oras FROM studenti”.

SQL se poate folosi nu numai pentru interogare, dar şi pentru a adăuga, a modifica sau a şterge înregistrări din bazele de date.

Majoritatea SGBD -urilor populare, ca de exemplu Microsoft Accsess, Oracle şi MySQL , asigură suport pentru SQL, chiar dacă acest nivel de suport diferă de la produs la produs.

Conectarea la baza de date Atunci când folosiŃi limbajul SQL pe un calculator personal, cu o

copie personală a unui sistem SGBD, precum Microsoft Access sau Oracle Personal Edition, toate componentele bazei de date rulează pe acelaşi sistem de calcul. Totuşi, acest aranjament nu este potrivit pentru bazele de date care trebuie să fie folosite în comun de mai mulŃi utilizatori. Ca urmare, sunt mult mai frecvent întâlnite situaŃiile în care baza de date este instalată într-un aranjament client/server.

Într-un aranjament client/server:

Page 168: CURS BD Combinat

3

• Sistemul rulează pe un server, care este un sistem de calcul partajat. Pentru scopurile acestei definiŃii, un sistem mainframe poate fi considerat un server de dimensiuni mari.

• Fişierele care compun baza de date din punct de vedere fizic sunt stocate pe discuri conectate la serverul de baze de date.

• Utilizatorii care au acces la baza de date folosesc staŃii de lucru, numite clienŃi. Clientul trebuie să aibă o conexiune de reŃea la baza de date, care poate fi o reŃea privată, instalată acasă sau la birou, ori o reŃea publică, precum Internet.

• Componentele software furnizate de producătorul SGBD rulează pe staŃiile de lucru alte clienŃilor pentru a oferi utilizatorilor posibilitatea să introducă instrucŃiuni SQL, să le transmită sistemului SGBD în vederea prelucrării şi să vadă rezultatele returnate de DBMS. În general, acest software se numeşte client SQL.

ReŃineŃi că nimic nu vă opreşte să instalaŃi clientul SQL pe acelaşi calculator cu sistemul SGBD. De fapt, mulŃi dezvoltatori care utilizează sisteme SGBD precum MySQL, Microsoft SQL Server şi Oracle fac în mod obişnuit acest lucru, deoarece este foarte convenabil să aibă întregul mediu de dezvoltare pe un singur calculator, cum ar fi un laptop. Totuşi, în momentul în care este necesar accesul partajat al mai multor utilizatori, este mult mai convenabil şi mai eficient să aveŃi o singură copie a sistemului SGBD pe un server partajat şi să aveŃi numai clientul SQL instalat pe staŃia de lucru a fiecărui client.

În funcŃie de interfaŃa cu utilizatorul de pe staŃia de lucru client, clienŃii SQL sunt clasificaŃi în trei categorii: în linia de comandă, grafici şi bazaŃi pe web. O interfaŃă în linia de comandă se bazează exclusiv pe intrări şi ieşiri de tip text, cu comenzile introduse de la tastatură şi răspunsurile afişate ca mesaje de tip text. Principalul avantaj al interfeŃelor în linia de comandă este că pot fi rulate pe aproape orice sistem de operare. De exemplu, clientul SQL*Plus rulat într-o fereastră de comandă Microsoft Windows.

Page 169: CURS BD Combinat

4

O interfaŃă grafică cu utilizatorul (GUI - Graphical User Interface)

rulează sub un tip oarecare de sistem bazat pe ferestre, cum ar fi : X Window System, Mac OS sau Microsoft Windows, şi afişează datele sau opŃiunile comenzilor folosind elemente grafice, precum pictograme, butoane şi casete de dialog. În figura de mai jos se prezintă clientul SQL*Plus(unul din clienții SQL furnizați de ORACLErulat ca aplicație GUI sub Microsoft Windows.

O interfaŃă bazată pe web rulează pe serverul de baze de date,

folosind un browser web de pe staŃia de lucru client pentru a interacŃiona cu utilizatorul bazei de date. Din punct de vedere tehnic, un client SQL bazat pe web nici nu este o aplicaŃie client, deoarece nu există nici o componentă software specifică producătorului SGBD rulată pe staŃia de lucru a clientului. Totuşi, aproape întotdeauna există componente furnizate de producătorul SGBD care sunt descărcate în fundal de browser-ul web pentru a asista în procesul de reprezentare grafică a formularelor web folosite pentru introducerea instrucŃiunilor SQL şi afişarea rezultatelor.

Tabelul următor prezintă clienŃi SQL oferiŃi de diferiŃi producători SGBD. În aceast curs nu prezentăm toate detaliile referitoare la fiecare client SQL pe care aŃi putea să-1 folosiŃi, aşa că vă rog să consultaŃi documentaŃia producătorului SGBD pentru informaŃii despre instalarea şi utilizarea clienŃilor SQL disponibile pentru sistemul SGBD pe care-1 folosiŃi

Page 170: CURS BD Combinat

5

Producător SGBD Client SQL Descriere

Microsoft Access Nu există

Microsoft Access este o bază de date de uz

personal, cu clientul SQL integrat în

DBMS, toate fiind rulate local pe staŃia de

lucru a utilizatorului.

Microsoft SQL Server iSQL

Client SQL care rulează ca aplicaŃie în

linia de comandă într-un nucleu de

comenzi Microsoft Windows.

Microsoft SQL Server Query Analyzer Client SQL care rulează ca

aplicaŃie Microsoft Windows.

MySQL MySQL MySQL

Client SQL care rulează ca

aplicaŃie în linia de comandă sub

diferite sisteme de operare, inclusiv

Microsoft Windows, Linux, Mac OS

X şi diferite implementări Unix.

Oracle Oracle iSQL*Plus

Client SQL bazat pe web -

acceptat în versiunile Oracle 9i

si mai noi.

Oracle Oracle SQL*Plus

Client SQL care rulează ca

aplicaŃie Microsoft Windows sau

ca aplicaŃie în linia de comandă

sub diferite sisteme de operare,

inclusiv Microsoft Windows,

Linux, Mac OS X, diferite

implementări Unix şi altele.

Oracle Oracle SQL Worksheet

Client SQL scris în Java -

disponibil în Oracle 8i şi 9i, dar

înlocuit de iSQL*Plus în Oracle

10g.

Sybase Sybase iSQL

Clientul SQL care rulează ca aplicaŃie

în linia de comandă într-un nucleu de

comenzi Microsoft Windows.

Asemănările cu Microsoft SQL Server

nu sunt întâmplătoare - primele

versiuni Microsoft SQL Server erau

bazate pe sistemul SGBDSybase.

Page 171: CURS BD Combinat

6

Un scurt istoric al limbajului SQL Către sfârşitul anilor '70, un grup de cercetători de la IBM au

dezvoltat o bază de date relaŃională, numită System/R, bazată pe lucrările Dr. E. F. Codd. În System/R a fost inclus un limbaj, numit SEQUEL (Structured English Query Language), pentru manipularea şi extragerea datelor. Acronimul „SEQUEL" a fost ulterior condensat în abrevierea „SQL", atunci când s-a descoperit că „SEQUEL" era marcă înregistrată a companiei Hawker-Siddeley Aircraft din Marea Britanie.

Deşi IBM a creat prima implementare SQL, două alte produse, cu nume diferite pentru limbajele de interogare, au fost lansate pe piaŃă ca primele produse pentru baze de date relaŃionale, Oracle, furnizat de Relational Software, şi INGRES, furnizat de Relational Technology. IBM a lansat în 1982 produsul SQL/DS, cu limbajul de interogare numit acum SQL (Structured Query Language). Dacă programarea structurată era expresia la modă în anii '80, cuvântul „structured" din SQL nu avea nici o legătură cu programarea structurată, deoarece SQL nu este un limbaj de programare procedural.

Comitetele de standardizare a limbajului SQL au fost formate de ANSI (American National Standards Institute) în 1986 şi ISO (International Organization for Standardization) în 1987. Din fericire, comitetele create de cele două organizaŃii au colaborat pentru dezvoltarea unui standard SQL comun, la nivel mondial. Doi ani mai târziu, au fost publicate primele specificaŃii ale standardului, numite SQL-89. După trei ani, specificaŃiile originale au fost extinse, sub forma standardului SQL-92, care avea aproximativ 600 de pagini. A treia generaŃie a fost numită SQL-99 sau SQL3. Cele mai multe produse SGBD sunt construite pe baza standardului SQL-92 (numit acum SQL2). SQL3 include multe caracteristici obiectuale, necesare pentru folosirea limbajului SQL cu o bază de date relaŃională orientată spre obiecte, precum şi extensii de limbaj care fac din SQL un limbaj de programare complet (adăugând cicluri, ramificări şi construcŃii de comutare, de tip case). Cea mai recentă generaŃie, numită SQL:2003, introduce caracteristici legate de XML şi alte îmbunătăŃiri. Aceste standarde nu sunt gratuite. Standardul SQL:2003 poate fi cumpărat de la ISO (www.iso.org) sau ANSI (webstore.ansi.org). Pentru cei care au un buget mai restrâns, este disponibilă o versiune apropiată de cea finală la Whitemarsh Information Systems Corporation (www.wiscorp.com/SQLStandards.html). Aproape toŃi furnizorii au adăugat extensii la „dialectul" SQL propriu, în parte deoarece doreau să diferenŃieze produsele proprii şi în parte deoarece cerinŃele pieŃei îi forŃau să implementeze caracteristici înainte a apărea standarde pentru acestea.

Un astfel de exemplu este acceptarea tipurilor de date TIMESTAMP şi DATE. Datele calendaristici sunt foarte importante

Page 172: CURS BD Combinat

7

pentru prelucrarea datelor comerciale, dar dezvoltatorii produselor SGBD originale erau academicieni şi oameni de ştiinŃă, nu specialişti în prelucrări comerciale, aşa că această cerinŃă nu a fost anticipată. Ca rezultat, primele dialecte SQL nu asigurau un suport special pentru datele calendaristice. Pe măsură ce au apărut produsele comerciale, furnizorii au răspuns cererilor lansate de clienŃii importanŃi şi au adăugat în grabă suportul pentru date calendaristice. Din nefericire, din cauza grabei fiecare a făcut-o în felul propriu. Codul SQL este foarte compatibil şi portabil între produsele diferiŃilor furnizori, dar sistemele complete de baze de date pot fi rareori transferate fară anumite ajustări.

SQL a sistemului Oracle este o extensie a normei SQL89 şi o implementare a normei SQL92.

ConvenŃii de sintaxă SQL Această secŃiune prezintă convenŃiile generale de sintaxă folosite

pentru construia instrucŃiunilor SQL. Totuşi, reŃineŃi că există o mulŃime de extensii şi variaŃii între diferiŃii producători. Pentru simplitate, termenul implementare este folosit pentru referirea fiecărei versiuni SQL a fiecărui producător (cu alte cuvinte, Oracle 9i, Oracle 10g, Microsoft SQL Server 7, Microsoft SQL Server 2000 şi Microsoft SQL Server 2005 conŃin implementări diferite ale limbajului SQL).

ConvenŃiile de sintaxă SQL sunt mai uşor de înŃeles folosind un exemplu simplu. InstrucŃiunea de mai jos returnează valorile Movie ID şi Movie Title pentru toate filmele din magazinul de produse video pentru care categoria MPAA este „PG":

SELECT FILM_ID, TITLU_FILM FROM FILM WHERE MPAA_RATING_COD = 'PG'; ConvenŃiile de bază sunt următoarele: • Fiecare instrucŃiune începe cu o comandă, de obicei sub forma

unui singur cuvânt, care aproape întotdeauna este un verb (în limba engleză) care descrie o acŃiune. În acest exemplu, instrucŃiunea începe cu comanda SELECT, care este descrisă în detaliu în lecŃia 3.

• Fiecare instrucŃiune se termină cu un delimitator, care este, de obicei, un caracter punct şi virgulă (;). Unele implementări permit schimbarea delimitatorului cu un alt caracter. Mai mult, unele implementări, cum ar fi cea din Oracle, nu execută o instrucŃiune SQL căreia-i lipseşte delimitatorul de sfârşit, în timp ce alte implementări consideră acest delimitator opŃional.

• InstrucŃiunile sunt construite într-o manieră similară cu propoziŃiile din limba engleză, cu unul sau mai multe spaŃii pentru

Page 173: CURS BD Combinat

8

separarea elementelor de limbaj. Un element de limbaj, asemănător cu un cuvânt dintr-o propoziŃie, poate fi un cuvânt cheie (SELECT, FROM, WHERE), numele unui obiect al bazei de date (FILM, FILM_ID, TITLU_FILM), un operator (=) sau o constantă ('PG') care apare într-o instrucŃiune.

• InstrucŃiunile sunt scrise într-o formă liberă, ceea ce înseamnă că nu există reguli stricte privind poziŃia elementelor de limbaj pe o linie sau locul în care se poate face trecerea la o linie nouă. Totuşi, în general nu este o idee bună să împărŃiŃi un element de limbaj pe mai multe linii. Din punct de vedere logic, instrucŃiunea de mai jos este identică cu cea prezentată la începutul acestei secŃiuni, dar nu este la fel de uşor de citit şi de înŃeles:

SELECT FILM_ID, TITLU_FILM FROM FILM WHERE MPAA_RATING_COD ='PG'; • InstrucŃiunile sunt organizate într-o serie de clauze şi, de obicei,

clauzele trebuie să apară într-o anumită ordine atunci când sunt folosite (multe clauze sunt opŃionale). în exemplul nostru, există trei clauze, fiecare începând cu un cuvânt cheie (SELECT, FROM, WHERE).

• Elementele de limbaj SQL pot fi scrise cu litere mari, cu litere mici sau în combinaŃii. Totuşi, în majoritatea implementărilor şi în conformitate cu standardele ANSI/ISO, toate minusculele sunt transformate în majuscule în vederea prelucrării. Aceasta nu înseamnă că datele nu pot conŃine litere mici, ci că numele obiectelor din baza de date (tabele, coloane etc.) şi comenzile trebuie să fie scrise cu litere mari. ExcepŃii notabile sunt Microsoft SQL Server şi Sybase, care permit modul de lucru cu diferenŃierea literelor mari de cele mici, caz în care numele de obiecte scrise diferit sunt tratate ca nume diferite. în MySQL, diferenŃierea literelor mari de cele mici în numele obiectelor este legată de capacitatea sistemului de operare de a face această diferenŃiere.

• Virgulele sunt folosite pentru separarea articolelor dintr-o listă. În exemplul nostru, numele a două coloane sunt specificate într-o listă separată prin virgule (FILM_ID, TITLU_FILM). SpaŃiile care urmează după virgule sunt opŃionale - puteŃi adăuga orice număr de spaŃii, inclusiv zero.

• Şirurile de caractere care apar în instrucŃiunile SQL trebuie să fie încadrate cu apostrofuri (unele implementări SQL permit şi folosirea ghilimelelor). Constantele numerice nu sunt niciodată încadrate cu apostrofuri. Dacă în şirul de caractere trebuie să apară un caracter apostrof, sunt inserate două apostrofuri unul lângă celălalt. De exemplu, dacă vreŃi să găsiŃi în baza de date un film numit Sophie's Choice, veŃi scrie clauza WHERE astfel:

WHERE TITLU_FILM = 'Sophie''s Choice'

Page 174: CURS BD Combinat

9

• Numele obiectelor bazei de date sunt formate folosind numai litere, cifre şi liniuŃe de subliniere. Caracterul underscore (liniuŃa de subliniere) este folosit, de obicei, ca separator între cuvinte, pentru îmbunătăŃirea lizibilităŃii. Aşa cum am menŃionat anterior, unele implementări permit folosirea numelor care fac diferenŃa între literele mari şi cele mici, cum ar fi PersonMiddleName, un stil numit deseori „scriere de tip cămilă", dar acest stil nu este recomandabil dacă doriŃi ca instrucŃiunile SQL să fie portabile pe alte implementări. în definitiv, un nume precum „PERSONMIDDLENAME" nu este foarte uşor de citit.

• In fiecare implementare SQL este definit un set de cuvinte rezervate, care sunt cuvinte cu o semnificaŃie specifică pentru procesorul SQL al sistemului SGBD şi, care urmare, nu trebuie folosite într-un alt context - de exemplu ca nume pentru obiectele bazei de date. Scopul acestei restricŃii este de a evita interpretarea greşită a instrucŃiunilor SQL de către SGBD. Aşa cum probabil bănuiŃi, lista cuvintelor rezervate diferă semnificativ de la o implementare SQL la alta, aşa că este bine să consultaŃi documentaŃia implementării pe care o folosiŃi pentru a vă familiariza cu aceste cuvinte.

• Un comentariu pe o singură linie începe cu două liniuŃe de despărŃire (--). Cele două liniuŃe se pot afla la începutul unei linii, ceea ce înseamnă că întreaga linie este considerată comentariu, sau oriunde în cadrul liniei, caz în care restul liniei, până la sfârşit, este considerat comentariu. De exemplu:

-- Acesta este un comentariu pe o singură linie în SQL. • Un comentariu pe mai multe linii începe cu combinaŃia dintre o

diagonală la dreapta (slash) şi un asterisc (/*) şi continuă până la întâlnirea combinaŃiei invers (*/). AveŃi grijă să terminaŃi corect comentariile, altfel multe linii SQL pe care le-aŃi scris vor fi tratate de către SGBD ca şi cum ar fi comentarii. Iată un exemplu de comentariu pe mai multe linii:

/* Acesta este un comentariu pe mai multe linii. Continuă până la întâlnirea combinaŃiei de caractere care

marchează sfârşitul comentariului. */

Sistemul impune anumite restricŃii asupra identificatorilor . • Numele unui obiect nu poate depăşi 30 de caractere, cu

excepŃia numelui bazei de date care este limitat la 8 caractere şi a numelui legăturii unei baze care poate ajunge la 128 caractere.

• Nu se face distincŃie între litere mici şi litere mari. • Numele trebuie să înceapă printr-un caracter alfabetic şi nu

poate fi un cuvânt cheie rezervat; poate să conŃină literele mari şi mici ale alfabetului englez, cifrele 0 - 9 şi caracterele $, _, #.

Page 175: CURS BD Combinat

10

• Un utilizator nu trebuie să definească două obiecte cu acelaşi nume.

• În general este bine ca numele unui obiect să fie descriptiv şi fără prescurtări excesive.

Categorii de instrucŃiuni SQL InstrucŃiunile SQL sunt împărŃite în categorii, după funcŃiile pe

care le îndeplinesc. Unii experŃi consideră aceste categorii ca fiind limbaje separate sau sublimbaje. Totuşi, în SQL acestea au aceeaşi sintaxă de bază şi respectă aceleaşi reguli, aşa că eu le consider categorii de instrucŃiuni din acelaşi limbaj.

Categoriile de instrucŃiuni, descrise în secŃiunile următoare, sunt: • Limbajul de definire a datelor (DDL sau LDD – Data

Definition Language) • Limbajul de interogare a datelor (DQL -Data Query Language) • Limbajul de manipulare a datelor (DML sau LMD - Data

Manipulation Language) • Limbajul pentru controlul datelor (DCL sau LCD–Data

Control Language) • Comenzile pentru controlul tranzacŃiilor (Transaction Control

Commands) Limbajul de definire a datelor (DDL) Limbajul de definire a datelor (DDL - Data Definition Language)

include instrucŃiuni SQL care permit utilizatorului bazei de date să creeze şi să modifice structura obiectelor bazei de date, cum ar fi tabele, vizualizări şi indexuri. InstrucŃiunile SQL care folosesc comenzile CREATE, ALTER şi DROP sunt considerate parte a DDL. Este important să înŃelegeŃi că instrucŃiunile DDL afectează containerele care stochează datele în baza de date, nu datele propriu-zise. Ca urmare, există instrucŃiuni DDL pentru crearea, ştergerea şi modificarea tabelelor, dar nici una dintre aceste instrucŃiuni nu oferă posibilitatea de a crea sau modifica rânduri de date din tabelele respective.

InstrucŃiunile LDD au efect imediat asupra bazei de date şi înregistrează informaŃia în dicŃionarul datelor. De asemenea, LDD contine instructiunile RENAME, TRUNCATE si COMMENT.

Page 176: CURS BD Combinat

11

Limbajul de interogare a datelor (DQL) Limbajul de interogare a datelor (DQL - Data Query Language)

include instrucŃiuni SQL care permit obŃinerea datelor din baza de date. Deşi reprezintă o parte foarte importantă a limbajului SQL, DQL este format din instrucŃiuni care folosesc o singură comandă: SELECT. Unii furnizori şi autori clasifică instrucŃiunile DQL şi DML în aceeaşi categorie.

Limbajul de manipulare a datelor (DML) Limbajul de manipulare a datelor (DML - Data Manipulation

Language) include instrucŃiuni SQL care permit utilizatorului bazei de date să adauge date în baza de date (sub forma rândurilor din tabele), să şteargă date şi să modifice datele existente în baza de date. InstrucŃiunile SQL care folosesc comenzile INSERT, UPDATE şi DELETE sunt considerate parte a DML.

Limbajul pentru controlul datelor (DCL) Limbajul pentru controlul datelor (DCL – Data Control Language)

include instrucŃiuni SQL care permit administratorilor să controleze accesul la datele din baza de date şi folosirea diferitelor privilegii ale sistemului DBMS, cum ar fi privilegiul de oprire şi pornire a bazei de date. InstrucŃiunile SQL care folosesc comenzile GRANT si ALTER sunt considerate parte a DCL.

Comenzile pentru controlul tranzacŃiilor

O tranzacŃie în baza de date este un set de comenzi pe care utilizatorul bazei de date vrea sa le trateze ca pe o unitate funcŃionala de tip „totul sau nimic”, întelegând prin aceasta că intreaga tranzactie trebuie sa reuseasca sau sa esueze. Comenzile pentru cotrolul tranzacŃiilor (Transaction Control Commands ) nu respectă cu exactitate sintaxa instrucŃiunilor SQL , dar afecteaza puternic comportamentul instructiuunilor SQL incluse în tranzacŃii.

Lecția 1:Limbajul de definire a datelor

La nivel logic, o bază de date Oracle este alcătuită din scheme. O schemă este o mulŃime de structuri logice de date, numite obiecte. Ea aparŃine unui utilizator al bazei de date şi poartă numele său.

Page 177: CURS BD Combinat

12

Specificarea bazelor de date şi a obiectelor care le compun se realizează prin intermediul limbajului de definire a datelor (DDL). Definirea unui obiect presupune crearea, modificarea şi suprimarea sa. Limbajul de definire a datelor cuprinde instrucŃiunile SQL care permit realizarea acestor operaŃii (CREATE, ALTER, DROP).

InstrucŃiunile DDL au efect imediat asupra bazei de date şi înregistrează informaŃia în dicŃionarul datelor. De asemenea, DDL contine instructiunile RENAME, TRUNCATE si COMMENT.

În cadrul unei scheme se pot defini obiecte de tip: tabel (table), vizualizare (view), vizualizare materializată (materialized view), secvenŃă (sequence), index (index), sinonim (synonym), grupare (cluster), procedură (procedure) şi funcŃie (function) stocată, declanşator (trigger), pachet stocat (package), legătură a bazei de date (database link), dimensiune (dimension) etc.

Se vor prezenta în continuare instrucŃiunile SQL folosite pentru definirea şi gestionarea obiectelor dintr-o bază de date relaŃională. InstrucŃiunile CREATE, ALTER şi DROP formează o categorie a limbajului SQL numită limbaj de definire a datelor (DDL– Data Definition Language).

Se prezintă DDL înaintea DQL, DML deoarece trebuiesc create obiectele bazei de date înainte de a insera date în baza de date.

ConvenŃii de sintaxă

InstrucŃiunile SQL DDL au mai multe opŃiuni decât alte instrucŃiuni SQL. Următoarele convenŃii sunt pentru a prezenta sintaxa instrucŃiunilor DDL:

• Cuvintele cheie şi cuvintele rezervate din SQL sunt scrise cu majuscule, cum ar fi CREATE TABLE.

• InformaŃiile pe care ar trebui să fie furnizate la scrierea instrucŃiunilor sunt scrise cu italic, cum ar fi nume_coloană.

• Elementele opŃionale sunt încadrate în paranteze pătrate, cum ar fi [WITH TIME ZONE].

• OpŃiunile dintr-o listă de elemente posibile sunt separate de o bară verticală (simbolul logic pentru „sau"), cum ar fi TABLE | VIEW | INDEX. Se pot întâlni uneori ca listă de elemente opŃionale, cum ar fi [NULL | NOT NULL].

• Elementele de grup care sunt explicate sau analizate ulterior pe componente (de obicei după descrierea unui tip principal de instrucŃiune) sunt încadrate de caracterele „mai mic decât" şi

Page 178: CURS BD Combinat

13

„mai mare decât", cum ar fi <specificaŃii_pentru_coloană> .

• Un element care se poate repeta este urmat de trei puncte, cum ar fi. [,<restricŃie_pentru_tabel>...].

Toate celelalte simboluri, în special virgulele şi parantezele, fac parte din sintaxa SQL obligatorie şi, ca urmare, trebuie să fie incluse aşa cum sunt scrise aici.

Tipuri de date O coloană este cea mai mică unitate denumită care poate fi referită

într-o bază de date relaŃională. Fiecare, coloană trebuie să aibă asociate un nume unic şi un tip de date. Un tip de date este o categorie pentru formatul folosit de o anumită coloană. Tipurile de date asigură câteva avantaje importante:

• RestricŃionarea, datelor din coloana respectivă la caracterele care au sens pentru tipul de date specificat.

• Asigurarea unor comportamente utile pentru utilizatorul datelor. De exemplu, dacă se scade un număr dintr-un alt număr, se obŃine ca rezultat un număr; dar dacă se scade o dată dintr-o altă dată, se obŃine ca rezultat diferenŃa în zile dintre cele două date calendaristice.

• Creşterea eficienŃei sistemului SGBD la stocarea datelor din coloane.

SQL acceptă trei categorii de tipuri de date: tipuri predefinite, tipuri construite şi tipuri definite de utilizator.

Tipurile de date predefinite sunt cele furnizate de către producător ca parte nativă a sistemului SGBD(vor fi tratate în continuare).

Tipurile de date construite, cunoscute şi ca tipuri de colecŃii, conŃin matrice sau seturi de tipuri de date predefinite, în scopul reprezentării în SGBD a construcŃiilor de date orientate spre obiect.

Tipurile de date definite de utilizator permit utilizatorului bazei de date să definească propriile tipuri de date, adaptate unor scopuri specifice.

Ultimele două tipuri de date nu vor fi tratate , fiind prea complicate pentru intenŃiile cursului.

Tipuri de date predefinite din standardul SQL:2003

Majoritatea implementărilorSQL acceptă cea mai mare parte parte

Page 179: CURS BD Combinat

14

a tipurilor de date definite de standardul SQL:2003.

Avem următoarele clase de tipuri:

Tipuri de date pentru caractere, tipuri de date numerice, tipuri de date temporale şi tipuri de date pentru obiecte mari.

Tipuri de date pentru caractere

Tipurile de date pentru caractere conŃin şiruri de caractere, adică litere, cifre şi alte simboluri permise de sistemul de calcul pe care se află baza de date.

Tipurile de date stardard pentru caractere sunt:

• Caracter cu lungime fixă - Un şir de caractere cu lungime finită. Sintaxa SQL este:

CHARACTER(lungime) | CHAR(lungime)

Exemplu: CNP CHAR(13)

• Caracter naŃional - Acest tip de date poate fi folosit pentru traducerea şirurilor de caractere în diferite limbi. Sintaxa SQL este:

NATIONAL CHARACTER(lungime) | NCHAR(lungime)

Exemplu: TITLU_FILM NCHAR(50)

• Caracter variabil - Un şir de caractere cu lungime variabilă, specificând lungimea maximă a şirurilor de caractere stocate. Sintaxa SQL este:

CHARACTER VARYING(lungime_maxim ă) |

VARCHAR(lungime_maximă)

Exemplu: NUME_CLIENT VARCHAR(125)

• Caracter naŃional variabil – O variantă a tipului de date pentru şiruri de caractere cu lungime variabilă, stocata într-un set de caractere al unei anumite limbi. Sintaxa SQL este:

NATIONAL CHARACTER VARYING(lungime_maxim ă) |

NVARCHAR (lungime_maximă)

Exemplu: TITLU_FILM NVARCHAR(100)

Tipuri de date numerice

Page 180: CURS BD Combinat

15

Acestea sunt utile mai ales pentru atributele folosite în calcule. Toate tipurile numerice au o precizie (un număr de cifre). De asemenea unele tipuri numerice au şi o scală (numărul de cifre aflate în dreapta punctului zecimal). Tipurile întregi şi tipurile numerice care include o scală sunt numite tipuri numerice exacte, în timp ce numerele reale care nu include o scală (numerele cu virgulă mobilă) sunt numite numerice aproximative.

Tipurile numerice standard sunt:

• Numeric - Un tip numeric exact care include o precizie şi o scală. Sintaxa SQL este:

NUMERIC (precizie, scală)

Exemplu: PLATA_PE_ORA_ANGAJAT NUMERIC(5,2)

• Zecimal - Un tip numeric exact care include o precizie şi o scală. Diferența față de Numeric, constă în faptul că precizia este mai mare , având scopul de a permite maparea tipului peste un tip al al platformei pe care rulează SGBD. Sintaxa SQL este:

DECIMAL(precizie, scală)

Exemplu: PLATA_PE_ORA_ANGAJAT DECIMAL(5,2)

• Întreg - Un tip numeric exact care include numai precizia, scris INTEGER sau INT. Numerele întregi nu au cifre zecimale, aşa că scala nu este necesară, deoarece este întotdeauna zero. Sintaxa SQL este:

INTEGER (precizie) | INT (precizie)

Exemplu: ID_CONT_CLIENT INTEGER

• Întreg mic - O variantă a tipului INTEGER, scrisă SMALLINT, care stochează numere mai mici şi, ca urmare, ocupă mai puŃin spaŃiu. Sintaxa SQL este:

SMALLINT (precizie)

Exemplu: ID_CONT_CLIENT SMALLINT

• Întreg mare - O variantă a tipului INTEGER, scrisă BIGINT, care stocheză numere mai mari şi ocupă mai mult spaŃiu.

Sintaxa SQL este:

BIGINT (precizie)

Exemplu: ID_CONT_CLIENT BIGINT

• Număr în virgul ă mobilă - Un tip numeric aproximativ, cu precizia mai mare sau egală cu precizia specificată. Specificarea

Page 181: CURS BD Combinat

16

preciziei este opŃională. Este scrisă FLOAT. Sintaxa SQL este:

FLOAT (precizie)

Exemple: RATA_DOBANDA FLOAT (16)

RATA_DOBANDA FLOAT

• Număr real - Un tip numeric aproximativ, cu precizie definită de implementare. Sintaxa SQL este:

REAL

Exemplu: RATA_DOBANDA REAL

• Număr real cu precizie dublă - Un tip numeric aproximativ, cu precizie definită de implementare, dar mai mare sau egală cu precizia definită pentru tipul REAL. Sintaxa SQL este:

DOUBLE PRECISION | DOUBLE

Exemplu: RATA_DOBANDA DOUBLE PRECISION

Tipuri de date temporale (tipuri pentru date şi ore)

Aceste tipuri stochează date care măsoară timpul, într-un mod oarecare. Tipurile de date temporale conŃin următoarele componente, numite de standard, câmpuri (fields) :

Numele câmpului (cuvânt cheie SQL)

DefiniŃie

YEAR Anul calendaristic, pe două sau patru cifre

MONTH Luna din an DAY Ziua din lună HOUR Ora din zi MINUTE Minutul din oră SECOND Secunda din minut

TIMEZONE_HOUR Valoarea orei cu diferenŃa de fus orar

TIMEZONE_MINUTE Valoarea minutului cu diferenŃa de fus orar

Câmpurile TIMEZONE_HOUR şi TIMEZONE_MINUTE sunt

incluse în toate tipurile de date temporale pentru care este specificat cuvântul cheie WITH TIMEZONE.

Page 182: CURS BD Combinat

17

Tipurile de date temporale sunt:

• Data - O dată calendaristică, incluzând câmpurile YEAR, MONTH şi DAY. Sintaxa SQL este: DATE [WITH TIMEZONE] Exemplu: DATA_NASTERE DATE

• Ora - Un tip de date pentru oră, incluzând câmpurile HOUR, MINUTE şi SECOND. Sintaxa SQL este: TIME [WITH TIMEZONE] Exemplu: TIMPUL_DEMARARE TIME

• Marcă temporală - Un tip de date combinat pentru dată şi oră, incluzând câmpurile YEAR, MONTH, DAY, HOUR, MINUTE şi SECOND. Sintaxa SQL este: TIMESTAMP [WITH TIMEZONE] Exemplu: DATA_TIMP_ NASTERE TIMESTAMP

• Interval - Un interval de timp, incluzând câmpurile specificate printr-un calificator de interval (internal qualifier), care reprezintă precizia intervalului. Sintaxa SQL este: INTERVAL câmp_de_start TO câmp_de_sfârşit|INTERVAL câmp Exemple: DURATA_PROIECT INTERVAL YEAR TO DAY TIMP_LUCRU INTERVAL HOUR TO MINUTE ZILE_VACANTA INTERVAL DAY

Tipuri de date pentru obiecte mari- LONG Obiectele mari permit stocarea unor date care depăşesc cu mult

posibilităŃile de stocare ale tipurilor de date prezentate până acum, ajungând deseori la dimensiuni de câŃiva megaocteŃi. Deoarece manipularea obiectelor mari este un subiect avansat, care nu vace obiectul cursului, se vor prezenta aceste tipuri fără sintaxa lor.

• Obiect mare pentru caractere - Un obiect mare pentru caractere, scris în SQL sub foma CLOB.

• Obiect mare pentru caractere, în format naŃional - Un obiect mare pentru caractere, stocat într-o anumită limbă, scris în SQL sub forma NLOB.

• Obiect mare binar - Un obiect mare care conŃine date binare, cum ar fi o imagine sau o secvenŃă sonoră, scris în SQL sub forma BLOB.

Page 183: CURS BD Combinat

18

Există restricŃii referitoare la folosirea tipului de date LONG.

• Într-un tabel poate să fie o singură coloană de tip LONG.

• Nu pot fi comparate două şiruri de caractere de tip LONG.

• O coloană de tip LONG nu poate fi parametru într-o procedură.

• O funcŃie nu poate întoarce ca rezultat o valoare de tip LONG.

• O coloană de tip LONG nu poate fi folosită în clauzele WHERE, ORDER BY, GROUP BY, CONNECT.

• Operatorii sau funcŃiile Oracle nu pot fi folosiŃi în SQL pentru a modifica coloane de tip LONG.

• O coloană de tip LONG nu poate fi indexată. Un alt tip de date Există un tip standard de date care nu este încadrat în nici una

dintre categoriile prezentate anterior: Boolean - Stochează o valoare logică adevărat sau fals. Sintaxa SQL este: BOOLEAN Exemplu: CLIENT_PREFERAT BOOLEAN

Extensii pentru tipuri de date şi diferenŃe faŃă de standard

Microsoft Access Microsoft Access este baza de date care respectă în cea mai mică măsură standardul, din toate sistemelm SGBD frecvent folosite. Tipurile de date acceptate de Microsoft Access sunt:

• Text - Echivalent cu tipul de date standard VARCHAR. Poate stoca până la 255 de caractere.

• Memo - ConŃine şiruri cu cel mult 65535 de caractere, dar este definit fără specificarea unei dimensiuni.

• Number - Echivalent cu tipul de date standard NUMERIC, dar precizia şi scala sunt stabilite folosind meniul derulant Field Size (Mărimea câmpului). Numerele întregi pot fi definite alegând valoarea zero (0) pentru parametrul Decimal Places (PoziŃii zecimale).

• Date/Time - Aproximativ echivalent cu tipul de date standard TIMESTAMP, dar poate stoca orice date şi oră valide între anii 100 şi 9999.

Page 184: CURS BD Combinat

19

• Currency - Un tip de date numeric echivalent cu tipul NUMERIC (19,4), adică un număr cu 15 cifre în stânga punctului zecimal şi cel mult 4 cifre în dreapta punctului zecimal.

• AutoNumber - Un câmp pe 4 sau 16 octeŃi (în funcŃie de valoarea Field Size) incrementat automat cu o unitate de fiecare dată când în tabel este inserat un nou rând.

• Yes/No - Aproximativ echivalent cu tipul de date standard BOOLEAN. Totuşi, Microsoft Access permite ca acest tip de date să fie formatat ca Yes/No, On/Off sau True/False.

• OLE Object - Similar cu tipul de date standard BLOB, acest tip de date permite stocarea unui obiect Microsoft OLE cu dimensiunea maximă de 1GB (gigaoctet).

• Hyperlink Un tip de date specializat care poate conŃine o adresă web din Internet.

• Lookup wizard - Un tip de date specializat care creează o legătură între o coloană din tabelul curent şi conŃinutul unei coloane dintr-un alt tabel. Acest tip de date poate fi folosit pentru legarea dinamică a tabelelor la crearea formularelor în Microsoft Access.

Oracle Oracle SQL acceptă următoarele tipuri de date standard:

• BLOB -Obiecte binare mari, cu dimensiunea maximă de (4GB-1) x (dimensiunea unui bloc din baza de date).

• CHAR - Şiruri de caractere cu lungime fixă, conŃinând cel mult 2000 de octeŃi.

• CLOB - Obiecte de tip caracter mari, cu dimensiunea maximă de (4GB- 1) x (dimensiunea unui bloc din baza de date).

• DATE - FuncŃionează ca tipul standard de date DATE, dar din punct de vedere tehnic seamănă mai mult cu tipul DATETIME, deoarece poate stoca atât data, cât şi ora. Acceptă date de la 1 ianuarie 4712 î.e.n. la 31 decembrie 9999 e.n. OpŃional, poate fi inclusă şi ora, în ore, minute şi secunde. Dacă partea opŃională este omisă, este stocată cu valoarea zero, echivalentă cu miezul nopŃii.

• DECIMAL - Implementat ca NUMBER(precizie,scală). • DOUBLE PRECISION - Implementat ca NUMBER. • FLOAT - Implementat ca NUMBER. • INTEGER - Implementat ca NUMBER(38).

Page 185: CURS BD Combinat

20

• INTERVAL - Un interval de timp, dar sunt acceptate din standard numai variantele INTERVAL YEAR TO MONTH şi INTERVAL DAY TO SECOND.

• NCHAR - Şiruri de caractere cu lungime fixă într-o limbă naŃională, cu dimensiunea maximă de 2000 de octeŃi.

• NCLOB - Şiruri de caractere cu lungime fixă într-o limbă naŃională, cu dimensiunea maximă de (4GB-1) x (dimensiunea unui bloc din baza de date).

• NUMERIC - Implementat NUMBER(precizie,scală). • NVARCHAR - Date de tip caracter cu lungime variabilă într-o

limbă naŃională, cu dimensiunea maximă de 4000 de octeŃi . • REAL - Implementat ca NUMBER. • SMALLINT - Implementat ca NUMBER(38). • TIMESTAMP - Data şi ora în ani, luni, zile, ore, minute şi

secunde. • VARCHAR - Date de tip caracter cu lungime variabilă,

conŃinând cel mult 4000 de caractere. Oracle oferă următoarele extensii la tipurile de date standard: • BFILE - O valoare de localizare a unui fişier binar de dimensiuni

mari, stocat în afara bazei de date. • LONG - Date de tip caracter cu lungime variabilă, cu

dimensiunea maximă de 2GB. • LONG RAW - Date binare, cu dimensiunea maximă de 2GB. • NUMBER - Date numerice, cu cel mult 38 de cifre. Poate stoca

valori întregi sau în virgulă mobilă. • NVARCHAR2 - Identic cu NVARCHAR. • RAW - Date binare, cu dimensiunea maximă de 2000 de octeli. • ROWID - Şir de caractere codat Base 64*, reprezentând adresa

unică a unui rând în tabelul din care face parte. • UROWID - Şir de caractere codat Base 64, reprezentând adresa

logică a unui rând într-un tabel indexat. • VARCHAR2 - Identic cu VARCHAR, dar Oracle recomandă

folosirea folosirea acestui tip în loc de VARCHAR, deoarece Oracle e posibil să schimbe la un moment dat implementarea tipului VARCHAR.

Precizari si exemple Pentru memorarea datelor numerice, tipurile cele mai frecvent

folosite sunt: NUMBER, INTEGER, FLOAT, DECIMAL.

Page 186: CURS BD Combinat

21

Pentru memorarea şirurilor de caractere, cele mai frecvent tipuri de date utilizate sunt: CHAR, NCHAR, VARCHAR2 , NVARCHAR2 şi LONG.

InformaŃii relative la timp sau dată calendaristică se obŃin utilizând tipul DATE. Pentru fiecare dată de tip DATE sunt depuse: secolul, anul, luna, ziua, ora, minutul, secunda. Pentru o coloană de tip DATE sistemul rezervă 7 bytes, indiferent dacă se memorează doar timpul, sau doar data calendaristică.

Formatul implicit al datei se defineşte cu ajutorul parametrului de iniŃializare NLS_DATE_FORMAT. În general, acest parametru este setat la forma DD-MON-YY. Dacă nu este specificat timpul, timpul implicit este 12:00:00.

Oracle9i introduce noi tipuri de date pentru timp: • TIMESTAMP(precizie_fracŃiuni_secundă) cuprinde

valori pentru anul, luna şi ziua unei date calendaristice, dar şi valori pentru oră, minut, secundă

• INTERVAL YEAR (precizie_an) TO MONTH stochează o perioadă de timp specificată în ani şi luni, unde precizie_an reprezintă numărul de cifre din câmpul YEAR.

• INTERVAL DAY (zi) TO SECOND (prec_frac_sec) stochează o perioadă de timp reprezentată în zile, ore, minute şi secunde.

Exemple

Să se creeze un tabel cu trei coloane, inceput, durata_1, durata_2.

Coloana inceput va cuprinde valori ce reprezintă momente de timp, inclusiv fracŃiunile de secundă corespunzătoare. Valorile coloanei durata_1 vor fi intervale de timp specificate în număr de zile, ore, minute şi secunde. Coloana durata_3 va conŃine intervale de timp precizate în număr de ani şi luni. Să se insereze o înregistrare în acest tabel.

CREATE TABLE TIMP (

inceput TIMESTAMP,

durata_1 INTERVAL DAY(2) TO SECOND(3),

durata_2 INTERVAL YEAR TO MONTH );

Exemple date inserate 1.

INSERT INTO timp

Page 187: CURS BD Combinat

22

VALUES (TIMESTAMP '2009-10-31 09:26:50.30',

INTERVAL '23 7:44:22' DAY TO SECOND,

INTERVAL '19-02' YEAR TO MONTH);

Ex. 2

INSERT INTO timp

VALUES (TIMESTAMP '2010-02-20 09:20:40.20',

INTERVAL '23 7:44:22' DAY TO SECOND,

INTERVAL '200-02' YEAR TO MONTH);

INTERVAL '200-02' da eroare, deoarece implicit precizia pentru

an este 2, iar 200 are 3 digiti

Ex.3

INSERT INTO timp

VALUES (TIMESTAMP '2010-01-25 09:26:50.30',

INTERVAL '23 7:44:22' DAY TO SECOND,

INTERVAL '20-100' YEAR TO MONTH);

Page 188: CURS BD Combinat

23

INTERVAL '20-100' eroare, deoarece 100 de luni adauga ani Ex.4

INSERT INTO timp

VALUES (TIMESTAMP '2010-01-25 09:26:50.30',

INTERVAL '23 2:2:2' DAY TO SECOND,

INTERVAL '20-10' YEAR TO MONTH);

Ex.5

INSERT INTO timp

VALUES (TIMESTAMP '2010-01-25 09:26:50.30',

INTERVAL '23 2:2:2' DAY TO SECOND,

INTERVAL '20-12' YEAR TO MONTH);

INTERVAL '20-12' eroare deoarece 12 luni fac un an si depasesc

intervalul de 20 ani Ex.6

Page 189: CURS BD Combinat

24

INSERT INTO timp

VALUES (TIMESTAMP '2010-01-25 09:26:50.30',

INTERVAL '23 2:2:2' DAY TO SECOND,

INTERVAL ‘120’ MONTH);

Se observă ca executând instructiunea:

SELECT * from timp ;

Ca durata_2 are valoarea 10;

Ex.7

INSERT INTO timp

VALUES (TIMESTAMP '2010-01-25 09:26:50.30',

INTERVAL '360' SECOND,

INTERVAL ‘144’ YEAR);

Page 190: CURS BD Combinat

25

Se observa că inregistrarea introdusa are :

• Durata_1 este de 6 min(360 sec) si

• Durata_2 de 12 ani(144 de zile)

Ex.8

INSERT INTO timp

VALUES (TIMESTAMP '2010-01-25 09:00:00.30',

INTERVAL '20' DAY(2), INTERVAL ‘10’ YEAR);

Se observa că inregistrarea introdusa are :

• Durata_1 de 20 zile si 0 secunde( fiind un INTERVAL DAY TO SECOND) si

• Durata_2 este 10 ani si 0 luni (fiind un INTERVAL YEAR TO MONTH)

Page 191: CURS BD Combinat

26

Exemplu

CREATE TABLE exemplu

(durata INTERVAL YEAR(3) TO MONTH);

INSERT INTO exemplu

VALUES (INTERVAL '120' MONTH);

SELECT TO_CHAR(SYSDATE+durata, 'DD-mon- YYYY') FROM exemplu;

Exemplu

CREATE TABLE noi_carti (codel NUMBER, start_data TIMESTAMP); INSERT INTO noi_carti VALUES (1,TIMESTAMP '2009-10-31 09:26:50.30'); SELECT codel ,start_data FROM noi_carti;

INSERT INTO noi_carti VALUES (5, timestamp '12-02-08 0:0:0');

Page 192: CURS BD Combinat

27

Pentru informatii de tip TIMESTAMP, numarul maxim de digiti

pentru fractiuni de secunda este 9, implicit este 6. Rezultatele cererii: 1 31-OCT-09 09.26.50.300000 AM 5 08-FEB-12 12.00.00.000000 AM

Pentru informatii de tip DATE, formatul implicit ar fi fost DD-MON-RR

Câmp Valori valide pentru date calendaristice

Valori valide pentru intervale

YEAR De la -4712 la 9999 (cu excepŃia anului 0).

Orice valoare întreagă.

MONTH De la 01 la 12. De la 0 la 11.

DAY

De la 01 la 31 (limitat de valorile câmpurilor MONTH şi YEAR, corespunzător regulilor calendarului curent).

Orice valoare întreagă.

HOUR De la 00 la 23. De la 0 la 23. MINUTE De la 00 la 59. De la 0 la 59.

SECOND De la 00 la 59.9(n), unde „9(n)“ este precizia fracŃiunilor de secundă.

De la 0 la 59.9(n), unde „9(n)“ este precizia fracŃiunilor de secundă.

TIMEZONE_HOUR De la –12 la 13 (prevede schimbările datorate trecerilor la ora de vară sau iarnă).

Nu se aplică.

TIMEZONE_MINUTE De la 00 la 59. Nu se aplică.

Sistemul Oracle permite construcŃia de expresii folosind valori de

tip dată calendaristică şi interval. OperaŃiile care pot fi utilizate în aceste expresii şi tipul rezultatelor obŃinute sunt următoarele:

• Data + Interval, Data – Interval, Interval + Data, iar rezultatul este de tip dată calendaristică;

• Data – Data, Interval + Interval, Interval – Interval, Interval * Number, Number * Interval, Interval / Number, iar rezultatul este de tip interval.

Page 193: CURS BD Combinat

28

Modele de format Un model de format este un literal caracter care descrie formatul

valorilor de tip DATE sau NUMBER stocate într-un şir de caractere. Atunci când se converteşte un şir de caractere într-o dată calendaristică sau într-un număr, modelul de format indică sistemului cum să interpreteze şirul respectiv.

În instrucŃiunile SQL se poate folosi un model de format ca argument al funcŃiilor TO_CHAR şi TO_DATE. În felul acesta se poate specifica formatul folosit de sistemul Oracle pentru a returna sau a stoca o valoare în/din baza de date. Un model de format nu schimbă reprezentarea internă a valorii în baza de date.

O parte dintre elementele cel mai frecvent întâlnite ale unui format de tip numeric sunt sintetizate în tabelul următor.

Element Exemplu Descriere

, (virgulă) 9,999

Plasează o virgulă în poziŃia specificată. Într-un model de format numeric pot fi precizate mai multe virgule, dar o virgulă nu poate apărea în partea dreaptă a punctului zecimal.

. (punct) 99.99 Plasează un punct zecimal în poziŃia specificată. Într-un format numeric, se poate specifica cel mult un punct zecimal.

$ $9999 Include semnul „$“ în faŃa unei valori.

0 0999; 9990

Plasează zerouri în faŃa sau la sfârşitul valorii.

9 9999 Întoarce valoarea cu numărul specificat de cifre. Valoarea va avea un spaŃiu, respectiv un minus în faŃă dacă este pozitivă, respectiv negativă.

C C999 Plasează în poziŃia specificată simbolul ISO pentru monede(valoarea curentă a parametrului NLS_ISO_CURRENCY).

D 99D99

Plasează în poziŃia specificată caracterul zecimal, care este valoarea curentă a parametrului NLS_NUMERIC_CHARACTER. Valoarea implicită este punctul. Se poate specifica cel mult un caracter zecimal într-un model de format numeric.

EEEE 9.9EEEE Returnează o valoare folosind notaŃia ştiinŃifică.

L L999 Întoarce în poziŃia specificată simbolul monedei locale (valoarea curentă a parametrului NLS_CURRENCY).

MI 9999MI

Plasează semnul minus la sfârşitul valorilor negative şi un spaŃiu la sfârşitul celor pozitive. Acest element poate fi specificat numai pe ultima poziŃie a modelului de format numeric.

S S9999; 9999S

Plasează semnele plus sau minus la începutul sau la sfârşitul valorii. Acest element poate apărea doar pe prima

Page 194: CURS BD Combinat

29

sau ultima poziŃie a modelului de format numeric.

Modelele de format pentru date calendaristice pot fi utilizate în cadrul următoarelor funcŃii de conversie:

• TO_DATE, pentru a converti o valoare de tip caracter, care este într-un alt format decât cel implicit, într-o valoare de tip DATE;

• TO_CHAR, pentru a converti o valoare de tip DATE, care este într-un alt format decât cel implicit, într-un şir de caractere.

• SYSDATE, pentru aflarea datei curente. De exemplu SELECT SYSDATE FROM dual;

Un model de format pentru date calendaristice este alcătuit dintr-unul sau mai multe elemente specifice. Scrierea cu litere mari sau mici a cuvintelor, abrevierilor sau a numeralelor romane este respectată în elementul de format corespunzător.

De exemplu, modelul de format „DAY“ produce cuvinte cu majuscule, cum ar fi „FRIDAY“, iar „Day“ şi „day“ au ca rezultat „Friday“, respectiv „friday“.

Într-un model de format pentru date calendaristice se pot preciza semne de punctuaŃie şi literale caracter, incluse între ghilimele. Toate aceste caractere apar în valoarea returnată pe locul specificat în modelul de format.

Element ExplicaŃie

AD sau A.D. Indicatorul AD (Anno Domini) cu sau fără puncte.

BC sau B.C. Indicatorul BC (Before Christ) cu sau fără puncte.

D Numărul zilei din săptămână (1-7). Duminica este considerată prima zi a săptămânii.

DAY Numele zilei completat cu spaŃii, până la lungimea de 9 caractere.

DD Numărul zilei din lună (1-31).

DDD Numărul zilei din an (1-366).

DY Numele zilei din săptămână, printr-o abreviere de 3 litere.

FF FracŃiunile de secundă.

HH sau HH12 Ora din zi (1-12).

HH24 Ora din zi (0-23).

MI Minutele din oră (0-59).

MM Luna din an (01-12).

MON Numele lunii, printr-o abreviere de 3 litere.

Page 195: CURS BD Combinat

30

MONTH Numele lunii completat cu spaŃii, până la lungimea de 9 litere.

RM Luna în cifre romane (I-XII).

RR Anul cel mai apropiat de data curentă.

RRRR Acceptă intrarea atât cu 2, cât şi cu 4 cifre. Dacă anul de intrare se dă cu 2 cifre, furnizează acelaşi lucru ca şi formatul RR.

SS Secundele din minut (0-59).

SSSSS Secundele trecute de la miezul noptii (0-86399).

TZH Ora regiunii.

TZM Minutul regiunii.

Y,YYY Anul scris cu virgulă după prima cifră.

YEAR sau SYEAR Anul în litere („S“ prefixează anii i.Hr. cu semnul minus).

YYYY sau SYYYY Anul cu 4 cifre.

YYY, YY sau Y Ultimele cifre ale anului.

Modificatorii FM şi FX pot fi utilizaŃi în modelele de format din cadrul funcŃiei TO_CHAR, controlând completarea cu spaŃii şi verificarea exactă a formatelor. Un modificator poate să apară într-un model de format de mai multe ori. În acest caz, efectele sale sunt active pentru porŃiunea din model care începe la prima apariŃie şi apoi dezactivate pentru porŃiunea din model care urmează celei de-a doua apariŃii ş.a.m.d.

Modificatorul FM (Fill Mode) suprimă completarea cu spaŃii în valoarea returnată de funcŃia TO_CHAR, iar FX (Format eXact) impune corespondenŃa exactă dintre argumentul de tip caracter şi modelul de format precizat pentru data calendaristică respectivă.

Exemplu:

SELECT nume, TO_CHAR(data_ang,’Month FMDD,YYYY’) angajare FROM angajati WHERE TO_CHAR(data_ang, ’YYYY’)=’2009’;

Nume Angajare Pop January 21,2009 Ene October 10,2009 Exemplu

SELECT nume, TO_CHAR(data_ang,’ DDTH ”of” Month YYYY’) angajare FROM angajati WHERE TO_CHAR(data_ang, ’YYYY’)=’2009’;

Page 196: CURS BD Combinat

31

Nume Angajare Pop 21st of January 2009 Ene 10TH of October 2009 Exemplu

SELECT TO_CHAR(data_ang,’ fmDDspth Month.Year’) angajare FROM angajati WHERE id_ang=100;

Angajare Twenty_NineTH July, Two Thousand Nine Exemplu

SELECT ’sesiune incepe pe ’|| TO_DATE(’20-09-2010’,’DD-MM-YYYY’) from dual;

Sesiunea incepe pe 20-09-2010 (Afi şează formatul standard pentru dată)

Valoarea null , reprezentând lipsa datelor, nu este egală sau diferită de nici o altă valoare, inclusiv null.

Totuşi, există două situaŃii în care sistemul Oracle consideră două valori null ca fiind egale: la evaluarea funcŃiei DECODE şi dacă valorile null apar în chei compuse. Două chei compuse care conŃin valori null sunt considerate identice dacă toate componentele diferite de null sunt egale.

Pseudocoloane

O pseudocoloană se comportă ca şi o coloană a unui tabel, dar nu este stocată efectiv într-un tabel. Se pot face interogări asupra pseudocoloanelor, dar nu se pot insera, actualiza sau şterge valorile acestora.

• LEVEL returnează nivelul liniilor rezultat ale unei cereri ierarhice.

• CURRVAL şi NEXTVAL sunt pseudocoloane utile în lucrul cu secvenŃe şi sunt tratate în secŃiunea corespunzătoare acestora.

• ROWID returnează adresa unei linii din baza de date, furnizând modul cel mai rapid de a accesa linia respectivă. În sistemul Oracle, valorile acestei pseudocoloane conŃin următoarele informaŃii necesare pentru a localiza o linie: numărul obiectului, blocul de date, fişierul de date, linia în cadrul blocului de date. Valorile pseudocoloanei ROWID sunt de tipul ROWID sau UROWID.

• ROWNUM returnează numărul de ordine al liniilor rezultate în

Page 197: CURS BD Combinat

32

urma execuŃiei unei cereri. Pseudocoloana poate fi utilizată pentru a limita numărul de linii returnate. Dacă este folosită clauza ORDER BY într-o subcerere, iar condiŃia în care apare ROWNUM este plasată în cererea de nivel superior, atunci condiŃia va fi aplicată după ordonarea liniilor.

Exemplu: Să se afişeze informaŃii despre operele de artă având cele mai mici

10 coduri. SELECT * FROM (SELECT * FROM opera ORDER BY cod_opera) WHERE ROWNUM < 11;

InstrucŃiuni DDL (Data Definition Language) InstrucŃiunile DDL (Data Definition Language) definesc obiectele

bazei de date, dar nu inserează şi nu actualizează date în obiectele respective. În SQL, există trei comenzi de bază pentru instrucŃiunile DDL:

CREATE - Creează în baza de date un nou obiect, de tipul specificat în instrucŃiune : CREATE DATABASE, CREATE TABLE, CREATE INDEX şi CREATE VIEW.

ALTER - Modifică definiŃia unui obiect existent în baza de date, de tipul specificat în instrucŃiune : ALTER TABLE, ALTER DATABASE, ALTER SYSTEM, ALTER USER, ALTER SESSION.

DROP - Şterge (distruge) un obiect existent în baza de date, de tipul specificat în instrucŃiune.

InstrucŃiunea CREATE DATABASE Definirea unei baze de date diferă destul de mult de la o

implementare la alta. Sintaxa generală pentru instrucŃiunea CREATE DATABASE este:

CREATE DATABASE nume bazadedate [opŃiuni_specifice _producătorul ]

În Oracle, instrucŃiunea CREATE USER crează în baza de date o schemă, cere este aproximativ echivalentă cu o bază de date.

Page 198: CURS BD Combinat

33

Standardul SQL prevede şi o instrucŃiune CREATE SCHEMA, care permite crearea unor grupuri de obiecte din baza de date, pentru simplificarea administrării.

FILM_ID PKFILM_COD_GEN FK1

MPAA_COD_RATING PK MPAA_COD_RATING FK2 FILM_COD_GEN PKMPAA_DESCRIERE_VARSTE FILM_NUME FILM_DESCRIERE_GEN

RETAIL_PRET_VHSRETAIL_PRET_DVDAN_PRODUS

FILM_ID PK,FK1 FILM_ID PK,FK1FILM_ID PK,FK1 NUMAR_COPIE PK NUMAR_COPIE PK,FK1COD_LIMBA PK,FK2 DATA_CUMPARARE TRANZACTIE_ID PK,FK2

DATA_VANZARE DATA_INTOARCEREFORMAT_MEDIA COST_INCHIRIERE

COST_INTARZIERE_SAU_PIERDEREDATA_RETURNARE

COD_LIMBA PKNUME_LIMBA CLIENT_CONT_ID PK TRANZACTIE_ID PK

CLIENT_HOLD_IND CLIENT_CONT_ID FK1DATA_INSCRIS ANGAJAT_PERSOANA_IDDATA_TERMINAT TRANZACTIE_DATACLIENT_DEPOZIT_SUMA VANZARI_TAXA

CLIENT_CONT_ID PK,FK1 CARD_CREDIT_LA_DOSAR_INDICPERSOANA_ID PK,FK2 COPIL_INCHIRIERE_PERMIS_INDIC

PERSOANA_ID PK PERSOANA_ID PK,FK1PERSOANA_PRENUME SUPERVISOR_PERSOANA_IDPERSOANA_NUME_MIJLOCIU ANGAJAT_TAXA_IDPERSOANA_NUME ANGAJAT_JOB_CATEGORIEPERSOANA_ADRESA_1 ANGAJAT_RATA_PE_ORAPERSOANA_ADRESA_2 ANGAJARE_DATAPERSOANA_ADRESA_ORAS INCHIDERE_DATAPERSOANA_ADRESA_JUDET_PROVPERSOANA_ADRESA_COD_POSTALPERSOANA_ADRESA_TARAPERSOANA_TELEFONNASTERE_DATAMOARTE_DATA

CLIENT_COD_PERSOANA

PERSOANA

CLIENT_TRANZACTIE

FILM_GEN

FILM_COPII

ANGAJAT

FILM_INCHIRIERE

CLIENT_CONT

FILM_LIMBA

LIMBA

FILM

MPAA_RATING

Page 199: CURS BD Combinat

34

Exemplu de Diagrama conceptuală

Exemplele din lucrare se referă la un model de gestiune a operelor de artă dintr-un muzeu. Diagrama entitate-relaŃie (E/R) corespunzătoare modelului analizat este prezentată în figura 2.1.

Schemele relaŃionale corespunzătoare diagramei conceptuale sunt: • OPERA(cod_opera#, tip, titlu, cod_artist, data_crearii,

data_achizitiei, valoare, cod_galerie, cod_sala, material, stil,

dim1, dim2, stare); • GALERIE(cod_galerie#, nume_galerie, nume_cladire, adresa); • SALA(cod_sala#, cod_galerie#, nume_sala, suprafata); • SECURITATE(cod_opera#, sistem#, descriere, valoare,

data_inst, firma, executant); • POLITA_ASIG(cod_opera, cod_polita#, descriere, firma,

valoare, semnat_contract); • SPECIALIST(cod_specialist#, nume, prenume, experienta,

autorizatie, tip, loc); • ARTIST(cod_artist#, nume, prenume, an_nastere, an_moarte,

nationalitate, observatii); • SURSA_BIBLIO(cod_sursa#, tip, titlu); • ARTICOL(cod_sursa#, nume_revista, nr_revista, data,

pag_revista); • CARTE(cod_sursa#, an, editura, ISBN); • AUTOR(cod_autor#, nume, prenume, descriere, job, adresa); • EXPOZITIE(cod_expo#, nume_expo, tip); • STUDIAZA(cod_opera#, cod_specialist#, data#, operatia,

metode, rezultat, plata); • MENTIONATA_IN(cod_opera#, cod_sursa#, pagina#); • FIGUREAZA_IN(cod_opera#, cod_expo#, cond_speciale,

localitate, data_inceput); • EDITATA_DE(cod_sursa#, cod_autor#); • ORGANIZATA_DE(cod_organizator#, cod_expozitie#); • ORGANIZATOR(cod_organizator#, nume, tip_organizator,

adresa).

Numele atributelor corespunzătoare relaŃiilor menŃionate sunt sugestive, astfel încât semnificaŃia lor este evidentă. Se pot face următoarele precizări:

• câmpul tip din tabelul opera este un şir de caractere ce reprezintă categoria în care se încadrează opera de artă respectivă (pictură, sculptură, grafică, tapiserie etc.);

Page 200: CURS BD Combinat

35

• material este un câmp de tip şir de caractere, ale cărui valori specifică materialul din care a fost concepută opera de artă (hârtie, pânză, bronz, aramă, piatră etc.);

• stil este un atribut de tip şir de caractere ce precizează stilul în care se încadrează opera de artă respectivă (clasic, renascentist, contemporan, impresionist etc.);

• dim1, dim2 sunt coloane numerice care specifică dimensiunile operei;

• stare este un atribut de tip şir de caractere care precizează starea fizică a operei de artă respective (medie, bună, foarte bună etc.);

• câmpul tip din tabelul specialist precizează calificarea unui specialist (expert, restaurator, evaluator etc.);

• loc reprezintă Ńara care a emis autorizaŃia corespunzătoare unui specialist;

• operatia specifică acŃiunea la care este supusă opera de artă (lipire, retuşare, curăŃare etc.);

• atributul metode specifică procedeele utilizate în realizarea operaŃiei (infraroşii, ultrasunete, raze X etc.);

• câmpul rezultat reŃine informaŃii asupra expertizei efectuate (dacă opera de artă este un fals, nivelul restaurării etc.);

• câmpul tip din tabelul sursa_biblio precizează categoria publicaŃiei în care apar referinŃe la opera de artă respectivă (articol, studiu, monografie etc.);

• câmpul job specifică profesia autorului unei surse bibliografice (profesor, expert, artist, jurnalist etc.);

• atributul observatii conŃine informaŃii referitoare la artişti (pseudonim, curentul artistic de care aparŃin etc.);

• câmpul tip din tabelul expozitie precizează categoria din care face parte o expoziŃie (fixă, itinerantă, temporară etc.).

Page 201: CURS BD Combinat

36

Figura 2.1. Diagrama E/R a modelului de gestiune a operelor de artă dintr-un muzeu

GALERIE cod_galerie#

SALA cod_sala# cod_galerie#

OPERA

cod_opera#

AUTOR

cod_autor#

ARTIST

cod_artist#

SECURITATE

cod_opera#

sistem#

POLITA_ASIG cod_polita#

SPECIALIST

cod_specialist#

EXPOZITIE

cod_expo#

ORGANIZATOR

cod_organizator#

1 inclusa_in M(1)

1

cuprinsa_in

M(1)

1 creata_de M(1)

protejata_prin 1 M(0)

1 asigurata_de M(0)

SURSA_BIBLIO cod_sursa# tip

ARTICOL

CARTE

M(1) studiaza

M(0)

M(1) organizata_de M(1)

M(0)

M(1)

mentionata_in

M(1)

M(0)

figureaza_in

M(1) editata_de

M(1)

Page 202: CURS BD Combinat

37

Asupra modelului considerat sunt definite anumite restricŃii. Conform acestora, o operă de artă poate:

• avea fie un singur autor, fie autor necunoscut; • avea mai multe sisteme de securitate instalate; • fi asigurată la mai multe firme; • fi menŃionată în aceeaşi sursă bibliografică, la pagini diferite.

InstrucŃiunea CREATE TABLE CREATE TABLE este una din instrucŃiunile fundamentale din

SQL. Modelul relaŃional cere ca toate datele stocate să fie ancorate într-un tabel, aşa că posibilitatea de a stoca orice într-o bază de date începe întotdeauna cu crearea unui tabel.

Crearea unui tabel constă din generarea structurii sale, adică atribuirea unui nume tabelului şi definirea caracteristicelor sale (se definesc coloanele, se definesc constrângerile de integritate, se specifică parametrii de stocare etc.).

În Oracle9i tabelele pot fi create în orice moment, chiar şi în timpul utilizării bazei. Structura unui tabel poate fi modificată online. Nu este necesar să se specifice dimensiunea acestuia. Totuşi, din considerente administrative, este important să se cunoască estimativ cât spaŃiu va utiliza tabelul.

Sintaxa de bază pentru instrucŃiunea CREATE TABLE este: CREATE TABLE nume_tabel (<definiŃie_coloană> [,<definiŃie_coloană> ...]) [,<restricŃie—tabel>... ]; Definirea coloanelor în SQL DDL Sintaxa de bază folosită pentru definirea coloanelor unui tabel este: <definiŃie_coloană> nume coloană tip_de_date [DEFAULT expresie] [NULL | NOT NULL]

Page 203: CURS BD Combinat

38

[<restricŃie_coloană>] Componentele din definiŃia unei coloane sunt: Numele coloanei - Numele coloanei trebuie să fie unic în cadrul

tabelului. Tipul de date - Tipul de date trebuie să fie un tip de date valid

pentru implementarea SGBD Restrictiile coloanei care sunt prezentate în continuare Structura unui tabel poate fi creată în următoarele patru moduri: • fără a indica cheile; • indicând cheile la nivel de coloană; • indicând cheile la nivel de tabel; • prin copiere din alt tabel.

Exemplu : Gestiunea activităŃilor de împrumut dintr-o bibliotecă

1. Crearea structurii unui tabel fără a indica cheile:

CREATE TABLE carte

(codel CHAR(5),

titlu VARCHAR2(30),

autor VARCHAR2(30),

pret NUMBER(8,2),

nrex NUMBER(3),

coded CHAR(5));

2. Crearea structurii unui tabel indicând cheile la nivel coloană:

CITITOR codec# nume dep

CARTE codel# titlu autor pret nrex coded DOMENIU

coded# intdom

imprumuta

apartine

M(1) M(0)

M(0) 1

Page 204: CURS BD Combinat

39

CREATE TABLE carte (codel CHAR(5) PRIMARY KEY, titlu VARCHAR2(30), autor VARCHAR2(30), pret NUMBER(8,2), nrex NUMBER(3), coded CHAR(5) NOT NULL

REFERENCES domeniu(coded));

Constrângerea de cheie primară sau externă ce presupune?

CREATE TABLE carte (codel CHAR(5) PRIMARY KEY, titlu VARCHAR2(30), autor VARCHAR2(30), pret NUMBER(8,2), nrex NUMBER(3), coded CHAR(5) NOT NULL

REFERENCES domeniu(coded) ON DELETE CASCADE);

CREATE TABLE domeniu (coded CHAR(5) PRIMARY KEY, den_dom VARCHAR2(30)); CREATE TABLE cititor (codec CHAR(5) PRIMARY KEY, den_cititor VARCHAR2(30));

OpŃiunea ON DELETE CASCADE specifică că suprimarea oricărui domeniu de carte din tabelul domeniu este autorizată şi implică suprimarea automată a tuturor cărŃilor din domeniul respectiv care se găsesc în tabelul carte.

3. Crearea structurii unui tabel indicând cheile la nivel de tabel:

CREATE TABLE carte (codel CHAR(5), titlu VARCHAR2(30), autor VARCHAR2(30), pret NUMBER(8,2), nrex NUMBER(3), coded CHAR(5) NOT NULL, PRIMARY KEY (codel),

FOREIGN KEY (coded)

Page 205: CURS BD Combinat

40

REFERENCES domeniu (coded));

Dacă cheia primară are mai mult de o coloană atunci cheile trebuie indicate la nivel de tabel.

CREATE TABLE imprumuta (codel CHAR(5), codec CHAR(5), dataim DATE DEFAULT SYSDATE, datares DATE, dataef DATE, PRIMARY KEY (codel, codec, dataim), FOREIGN KEY (codel) REFERENCES carte(codel), FOREIGN KEY (codec) REFERENCES cititor(codec));

INSERT INTO domeniu VALUES(’I’, ’Informatica’); INSERT INTO carte VALUES(’bnat1’, ’Baza_de_Date’, ’Popescu_Ioana’, 300.50, 100,’I’);

4. Crearea structurii unui tabel prin copiere din alt tabel:

CREATE TABLE carte_info AS SELECT codel, titlu, autor FROM carte WHERE coded = ’I’;

Page 206: CURS BD Combinat

41

Constrângeri

Constrângerea este un mecanism care asigură că valorile unei

coloane sau a unei mulŃimi de coloane satisfac o condiŃie declarată. Unei constrâgeri i se poate da un nume unic. Dacă nu se specifică un nume explicit atunci sistemul automat îi atribuie un nume de forma SYS_Cn, unde n reprezintă numărul constrângerii. Constrângerile pot fi şterse, pot fi adăugate, pot fi activate sau dezactivate, dar nu pot fi modificate.

RestricŃiile coloanelor RestricŃiile unei coloane limitează într-un mod oarecare valorile ce

pot fi stocate într-o coloană a unui tabel. RestricŃiile coloanelor pot avea oricare dintre următoarele forme:

Exemplu, crearea tabelului CONT_CLIENT, din baza de date a

magazinului de produse video.

CREATE TABLE CONT_CLIENT ( ID_CONT_CLIENT INTEGER NOT NULL, STARE_CONT_CLIENT CHAR(1) DEFAULT ‘N’ NOT NULL CHECK (STARE_CONT_CLIENT IN (‘Y’, ‘N’)), DATA_INSCRIERE DATE NOT NULL , DATA_INCHEIERE DATE NULL , SUMA_DEPOZIT_CLIENT NUMERIC(5,2) NULL , IND_CREDIT_CARD CHAR(1) NOT NULL CHECK (IND_CREDIT_CARD IN (‘Y’, ‘N’)), INDIC_PERMIS_INCHIRIERE_COPIL CHAR(1) NOT NULL CHECK (INDIC_PERMIS_INCHIRIERE_COPIL IN(‘Y’,‘N’)), PRIMARY KEY (ID_CONT_CLIENT) ); Descriere tabel: ID_CONT_CLIENT - cheie primara STARE_CONT_CLIENT de tip DA/NU, care indica daca un cont este sau nu blocat.(inchirierile nu sunt permise pt conturile blocate) DATA_INSCRIERE - data la care s-a deschis contul in magazin DATA_INCHEIERE - daca contul a fost inchis contine data; daca contul e activ contine NULL

Page 207: CURS BD Combinat

42

SUMA_DEPOZIT_CLIENT – pt clientii care nu au carte de credit, suma lasata ca depozit in magazin IND_CREDIT_CARD - de tip DA/NU, care indica daca un client a lasat inf despre carte de credit, pt a garanta platile asociate contului. INDIC_PERMIS_INCHIRIERE_COPIL - de tip DA/NU, care indica daca uncopil<18 ani are voie sa inchirieze filme folosind acest cont

• Clauza DEFAULT - O expresie care este aplicată coloanei atunci

când în tabel este inserat un nou rând, care nu conŃine o valoare explicită pentru coloana respectivă. Expresia poate fi orice expresie validă. Sintaxa SQL cu o clauză DEFAULT este:

[DEFAULT expresie] Exemplu: STARE_CONT_CLIENT CHAR(1) DEFAULT 'N' NOT NULL (la creare are val N , adica contul nu e blocat)

• RestricŃia NULL | NOT NULL - Specificarea cuvântului cheie NULL permite stocarca valorilor nule într-o coloană, în timp ce NOT NULL nu permite stocarca valorilor nule în coloana respectivă. O restricŃie NOT NULL poate fi scrisă şi sub forma unei restricŃii CHECK cu condiŃia IS NOT NULL .

Sintaxa SQL şi câteva exemple: NULL | NOT NULL Exemple: DATA_INSCRIERE DATE NOT NULL DATA_INCHEIERE DATE NULL

• RestricŃia CHECK - O restricŃie de verificare (check) poate fl folosită pentru impunerea unei reguli care poate fi aplicată unei singure coloane a unui tabel. CondiŃia inclusă în restricŃie trebuie să fie îndeplinită ori de câte ori datele din coloana respectivă a tabelului sunt modificate – în caz contrar, sistemul SGBD va respinge modificarea şi va afişa un mesaj de eroare.

Sintaxa restricŃiei CHECK şi un exemplu: [CONSTRAINT nume restricŃie] CHECK (condiŃie) Exemplu: IND_CREDIT_CARD CHAR(1) NOT NULL, CHECK (CREDIT_CARD_INDIC IN (‘Y’, ‘N’)) Clauză NOT NULL poate fi rescrisă şi sub forma unei restricŃii CHECK: ID_CONT_CLIENT INTEGER

Page 208: CURS BD Combinat

43

CONSTRAINT CK_CUST _ACCT _ID CHECK (ID_CONT IS NOT NULL )

• RestricŃia UNIQUE - O restricŃie UNIQUE impusă asupra unei coloane garantează unicitatea valorilor din coloana respectivă a tabelului. Sintaxa:

[CONSTRAINT nume_restricŃie] UNIQUE Exemplu: ID_CONT_CLIENT INTEGER UNIQUE

• RestricŃia PRIMARY KEY - O restricŃie de cheie primară (PRIMARY KEY) impusă asupra unei coloane declară coloana respectivă ca fiind cheia primară a tabelului, ceea ce înseamnă că în coloana respectivă nu pot exista valori nule, iar valorile trebuie să fie unice în cadrul tabelului.

Sintaxa : (CONSTRAINT nume_restricŃie] PRIMARY KEY Exemplu: ID_CONT_CLIENT INTEGER PRIMARY KEY

• RestricŃia referentială (FOREIGN KEY) - O restricŃie referenŃială impusă asupra unei coloane (numită şi restricŃie de cheie externă) defineşte relaŃia dintre o cheie externă şi o cheie primară.

Sintaxa: [CONSTRAINT nume_restricŃie] REFERENCES nume_tabel(nume_coloană) [ON DELETE CASCADE | ON DELETE SET NULL] Exemplu: MPAA_CODE_RATING din tabelul FILME este cheie externă

pentru tabelul MPPA_RATING, care are câmpurile: MPAA_CODE_RATING şi MPAA__RATING _DESCRIERE MPAA_COD_RATING CHAR (5) NOT NULL REFERENCES MPPA_RATING(MPAA_CODE_RATING) Clauza opŃională ON DELETE spune sistemului SGBD ce să facă atunci când este şters rândul referit din tabelul părinte cu opŃiunea de a şterge toate rândurile care conŃin cheia externă (CASCADE) sau de a insera valori nule pentru toate cheile externe (SET NULL).

Page 209: CURS BD Combinat

44

RestricŃiile tabelelor RestricŃia unei coloane poate fi rescrisă şi ca restricŃie a întregului

tabel, astfel încât clauza care defineşte restricŃia să apară în instrucŃiunea CREATE TABLE după definiŃiile tuturor coloanelor, nu după definiŃia unei coloane. Principalul avantaj al restricŃiilor la nivelul tabelului este că pot referi mai multe coloane. • RestricŃia CHECK

[CONSTRAINT nume_restricŃie] CHECK (condiŃie) RestricŃia de mai jos împiedică stocarea unei valori negative în

coloana SUMA_DEPOZITE_CLIENT . Operatorul OR permite stocarea valorilor nule , deoarece o valoare nulA nu este mai mare sau egală cu zero.

Exemplu: CONSTRAINT CK_SUMA_DEPOZITE_CLIENT CHECK (SUMA_DEPOZITE_CLIENT >= 0 OR SUMA_DEPOZITE_CLIENT IS NULL)

• RestricŃia UNIQUE

[CONSTRAINT nume_restricŃie) UNIQUE (nume_coloană [,nume coloană...]) Conform acestei restricŃii , combinaŃia de coloane

ID_CONT_CLIENT şi DATA_INSCRIERE trebuie să fie unică în rândurile din tabel.

Exemplu: CONSTRAINT UK_DATA_INSCR_CONT_CL UNIQUE (ID_CONT_CLIENT, DATA_INSCRIERE )

• RestricŃia PRIMARY KEY

[CONSTRAINT nume_restricŃie] PRIMARY KEY (nume_coloană [,nume_coloană...]) RestricŃia de mai jos este chiar definiŃia cheii primare din tabelul CONT_CLIENT [ Exemplu: CONSTRAINT PK_CONT_CLIENT PRIMARY KEY (ID_CONT_CLIENT)

• RestricŃia referenŃială (FOREIGN KEY)

Page 210: CURS BD Combinat

45

Spre deosebire de forma pentru restricŃia referenŃială a coloanei, aceasta poate referi mai multe coloane.

[CONSTRAINT nume_restricŃie] FOREIGN KEY (nume_coloană [,nume coloană...]) REFERENCES nume_tabel (nume_coloană [,nume_coloană...

[ON DELETE CASCADE |ON DELETE SET NULL] Exemple de constrîngeri la nivel de coloană şi tabel pentru

gestiunea cărților dintr-o bibliotecă.

Exemple: 1. Să se definească o constrângere la nivel de coloană prin care să

se specifice cheia primară şi cheia externă.

CREATE TABLE carte

(codel CHAR(5)

CONSTRAINT cp_carte PRIMARY KEY , Titlu VARCHAR2(30), autor VARCHAR2(30), pret NUMBER(8,2), nrex NUMBER(3), coded CHAR(5) CONSTRAINT nn_coded NOT NULL CONSTRAINT ce_coded REFERENCES domeniu(coded));

2. Să se definească o constrângere la nivel de tabel prin care să se specifice cheia primară şi cheia externă.

CREATE TABLE carte

(codel CHAR(5),

titlu VARCHAR2(30), autor VARCHAR2(30), pret NUMBER(8,2), nrex NUMBER(3), coded CHAR(5) NOT NULL,

CONSTRAINT cp_carte PRIMARY KEY (codel), CONSTRAINT ce_coded FOREIGN KEY (coded) REFERENCES domeniu(coded));

Page 211: CURS BD Combinat

46

ObservaŃii: • Liniile ce nu respectă constângerea sunt depuse automat într-un

tabel special.

• Constrângerile previn ştergerea unui tabel dacă există dependenŃe.

• Constrângerile pot fi create o dată cu tabelul sau după ce acesta a fost creat.

• Constrângerile pot fi activate sau dezactivate în funcŃie de necesităŃi.

Constrângeri declarative pot fi: constrângeri de domeniu, constrângerea de integritate a entităŃii, constrângerea de integritate referenŃială.

Constrângerile de domeniu definesc valori luate de un atribut (DEFAULT, CHECK, UNIQUE, NOT NULL).

• constrângerea (coloană) DEFAULT ;

• constrângerea (coloană sau tabel) CHECK ; constrângerea CHECK la nivel de tabel poate compara coloane între ele, poate face referinŃă la una sau mai multe coloane, dar nu poate conŃine subcereri. Constrângerea la nivel de coloană nu poate referi alte coloane ale aceluiaşi tabel.

CREATE TABLE carte (codel CHAR(5),… nrex NUMBER(3), pret NUMBER(8,2) CONSTRAINT alfa CHECK (pret < nrex ),…);

La execuŃia acestei comenzi apare mesajul: ORA – 02438: Column check constraint cannot reference other columns.

Dacă după NUMBER(8,2) se adaugă o virgulă, atunci constrângerea va fi la nivel de tabel, iar în aceste caz este permisă referirea altei coloane. • constrângerea (coloană sau tabel) UNIQUE ; • constrângerea declarativă NOT NULL poate fi doar la nivel coloană.

Constrângerea de integritate a entităŃii precizează cheia primară a unui tabel. Când se creează cheia primară se generează automat un index unic. Valorile cheii primare sunt distincte şi diferite de valoarea null.

Page 212: CURS BD Combinat

47

Constrângerea de integritate referenŃială asigură coerenŃa între cheile primare şi cheile externe corespunzătoare. Când este definită o cheie externă sistemul Oracle verifică:

• dacă a fost definită o cheie primară pentru tabelul referit de cheia externă;

• dacă numărul coloanelor ce compun cheia externă corespunde numărului de coloane a cheii primare;

• dacă tipul şi lungimea fiecărei coloane a cheii externe corespunde cu tipul şi lungimea fiecărei coloane a cheii primare.

Această constrângere poate fi definită la nivel de coloană sau tabel şi asigură coerenŃa între cheile primare şi cheile externe corespunzătoare. Constrângerea FOREIGN KEY desemnează o coloană sau o combinaŃie de coloane drept cheie externă şi stabileşte relaŃia cu o cheie primară sau o cheie unică din acelaşi tabel sau din altul.

O cheie externă compusă poate fi definită doar la nivel de tabel.

Cheia externă se defineşte în tabelul „copil“, iar tabelul care conŃine coloana referită reprezintă tabelul „părinte“. Valoarea unei chei externe trebuie să fie egală cu o valoare existentă în tabelul „părinte“ sau să fie null. Cheile externe se bazează pe valorile datelor şi sunt pointer-i logici.

Cheile externe se definesc folosind următoarele cuvinte cheie:

• FOREIGN KEY este utilizat într-o constrângere la nivel de tabel pentru a defini coloana din tabelul „copil“;

• REFERENCES identifică tabelul „părinte“ şi coloana corespunzătoare din acest tabel;

• ON DELETE CASCADE determină ca, odată cu ştergerea unei linii din tabelul „părinte“, să fie şterse şi liniile dependente din tabelul „copil“;

• ON DELETE SET NULL determină modificarea automată a valorilor cheii externe la valoarea null, atunci când se şterge valoarea „părinte“.

DefiniŃiile şi numele constrângerilor definite se pot fi consulta prin interogarea vizualizărilor USER_CONSTRAINTS şi ALL_CONSTRAINTS din dicŃionarul datelor (Desc USER_CONSTRAINTS;)

Modificarea structurii unui tabel

Page 213: CURS BD Combinat

48

Comanda care realizează modificarea structurii tabelului (la nivel de coloană sau la nivel de tabel), dar nu modificarea conŃinutului acestuia, este ALTER TABLE.

InstrucŃiunea ALTER TABLE InstrucŃiunea ALTER TABLE ajută să se facă modificări asupra tabelelor create. Utilizarea instrucŃiunii ALTER TABLE este un alt domeniu în care au un rol important stilul şi preferinŃele personale. MulŃi administratori de baze de date preferă să folosească instrucŃuni CREATE TABLE cât mai simple, evitând să definească restricŃii în instrucŃiunile CREATE TABLE. Aceştia adaugă după instrucŃiunea CREATE TABLE instrucŃiuni ALTER TABLE prin care specifică toate restricŃiile necesare (cheie primară, cheie externă, unicitate, verificare). Dezavantajul acestei metode este acela că necesită scrierea unei cantităŃi mai mari de cod. Pe de altă parte, instrucŃiunea CREATE TABLE este mult mai uşor de înŃeles fără restricŃii, iar scrierea separată a restricŃiilor simplifică refolosirea instrucŃiunilor.

Comanda ALTER TABLE permite:

• adăugarea (ADD) de coloane, chei (primare sau externe), constrângeri într-un tabel existent;

• modificarea (MODIFY) coloanelor unui tabel;

• specificarea unei valori implicite pentru o coloană existentă;

• activarea şi dezactivarea (ENABLE, DISABLE) unor constrângeri;

• suprimarea unei coloane;

• suprimarea (DROP) cheii primare, a cheii externe sau a unor constrângeri.

Comanda ALTER TABLE are următoarea sintaxă simplificată:

ALTER TABLE [<nume_schema>.] <nume_tabel> [ADD (<nume_coloana> <tip_date>, <constrângere>) | MODIFY (<nume_coloana_1>,…, <nume_coloana_n>) | DROP <clauza_drop>,] [ENABLE | DISABLE <clause>];

Page 214: CURS BD Combinat

49

• Adăugarea unei coloane la un tabel. Definirea coloanei se face cu aceeaşi sintaxă ca şi în cazul instrucŃiunii CREATE TABLE. Nu se poate specifica unde să apară coloana, ea devenind ultima coloană a tabelului.

ALTER TABLE nume_tabel ADD ( <definiŃie_co1oană> [,<definiŃie_co1oană> Exemplu: ALTER TABLE CONT_CLIENT ADD (DATA_CLIENT DATE, INTRODUSE_DE VARCHAR(50)); ALTER TABLE CITITOR ADD (ADRESA VARCHAR(50));

ALTER TABLE carte ADD(rezumat LONG);

• Modificarca defini Ńiei unei coloane. Majoritatea SGBD-urilor nu permit să scădeŃi precizia unei coloane dacă tabelul conŃine date şi foarte puŃine permit să se schimbe tipul de date al unei coloane existente. Sunt acceptate creşterea preciziei unei coloane, adăugarea sau modificarea valorii prestabilite pentru o coloană, şi trcerea de la NULL la NOT NULL sau invers.

ALTER TABLE nume_tabel MODIFY [COLUMN] (<definiŃie — coloană> [,<definiŃie_co1oană> ...]); Exemplu: ALTER TABLE CONT_CLIENT MODIFY (SUMA_DEPOZIT_CLIENT NUMERIC(7,2) DEFAULT 0 NOT NULL);

Page 215: CURS BD Combinat

50

• Adăugarea unei restricŃii. DefiniŃia restricŃiei este identică cu definiŃia unei restricŃii care ar putea apărea într-o instrucŃiune CREATE TABLE.

ALTER TABLE nume_tabel ADD CONSTRAINT <definiŃie_restricŃie>; Exemplu: ALTER TABLE CONT_CLIENT ADD CONSTRAINT CK_SUMA_DEPOZIT_CLIENT CHECK (SUMA_DEPOZIT_CLIENT >= 0 OR SUMA_DEPOZIT_CLIENT IS NULL);

Dacă pun o valoare negativă la suma, atunci apare eroare .

CREATE TABLE carte (CODEL char(5),

…); ALTER TABLE carte ADD CONSTRAINT cheie_prim PRIMARY KEY (codel);

• Ştergerea cheii primare a unui tabel.

Dacă cheia primară este referită de restricŃii referenŃiale, trebuie mai întâi şterse restricŃiile respective. ALTER TABLE nume_tabel DROP PRIMARY KEY;

Dacă există o CE care referă o CP şi dacă se încearcă ştergerea cheii primare, această ştergere nu se poate realiza (tabelele sunt legate prin declaraŃia de cheie externă). Ştergerea este totuşi permisă dacă

Page 216: CURS BD Combinat

51

în comanda ALTER apare opŃiunea CASCADE, care determină şi ştergerea cheilor externe ce referă cheia primară.

ALTER TABLE domeniu DROP PRIMARY KEY CASCADE; • Ştergerea cheii externe se face ca si pentru ştergerea cheii

primare

ALTER TABLE carte ADD CONSTRAINT beta FOREIGN KEY (coded) REFERENCES domeniu; • Schimbarea cheii primare. Este destul de complicat procesul

schimbării cheii primare fără a afecta modul de proiectare a bazei de date. Schimbarea se face în două etape: se şterge cheia primară şi apoi se recreează.

ALTER TABLE carte ADD (PRIMARY KEY(codel)); ALTER TABLE carte DROP PRIMARY KEY; ALTER TABLE carte ADD PRIMARY KEY(titlu, autor));

• Redenumirea unei coloane.

Dintre bazele de date care acceptă această sintaxă este numai Oracle, începând cu versiunea 8.0 ALTER TABLE nume_tabel RENAME COLUMN nume_vechi_coloană TO nume _nou_coloană; ALTER TABLE timp RENAME COLUMN durata_1 TO dur_1; ALTER TABLE timp RENAME COLUMN durata_2 TO dur_2;

Page 217: CURS BD Combinat

52

• Pentru a activa (ENABLE) sau dezactiva (DISABLE) constrângeri:

ALTER TABLE nume_tabel ENABLE nume_constrangere; ALTER TABLE carte DROP CONSTRAINT beta; ALTER TABLE cititor ADD CONSTRAINT cp_cititor PRIMARY KEY (codec) DISABLE; ALTER TABLE cititor ENABLE CONSTRAINT cp_cititor; Stergerea unei coloane se face ca şi a unei constringeri; ALTER TABLE nume_tabel DROP nume_coloana;

ALTER TABLE CONT_CLIENT DROP (DATA_CLIENT ,INTRODUSE_DE );

ObservaŃii

• Nu se poate specifica poziŃia unei coloane noi în structura tabelului. O coloană nouă devine automat ultima în cadrul structurii tabelului.

Page 218: CURS BD Combinat

53

• Modificarea unei coloane presupune schimbarea tipului de date, a dimensiunii sau a valorii implicite a acesteia. O schimbare a valorii implicite afectează numai inserările care succed modificării.

• Dimensiunea unei coloane numerice sau de tip caracter poate fi mărită, dar nu poate fi micşorată decât dacă acea coloană conŃine numai valori null sau dacă tabelul nu conŃine nici o linie.

• Tipul de date al unei coloane poate fi modificat doar dacă valorile coloanei respective sunt null.

• Alte opŃiuni ale comenzii ALTER TABLE, care au apărut începând cu versiunea Oracle8i, sunt SET UNUSED şi DROP UNUSED COLUMNS:

ALTER TABLE nume_tabel ET UNUSED [ ( ] nume_coloană [ ) ];

ALTER TABLE nume_tabel DROP UNUSED COLUMNS;

OpŃiunea SET UNUSED permite marcarea uneia sau mai multor coloane ca fiind nefolosite, cu scopul de a fi şterse atunci când necesităŃile sistemului impun acest lucru. Coloanele nefolosite sunt tratate ca şi cum ar fi fost suprimate, deşi datele acestora rămân în liniile tabelului. După ce o coloană a fost marcată UNUSED, utilizatorul nu mai are acces la aceasta prin intermediul cererilor. În plus, numele şi tipurile de date ale coloanelor nefolosite nu vor fi afişate cu comanda DESCRIBE din SQL*Plus. Utilizatorul poate să adauge tabelului o nouă coloană având acelaşi nume cu cel al unei coloane nefolosite.

DROP UNUSED COLUMNS şterge din tabel toate coloanele marcate ca fiind nefolosite. Acest lucru se poate utiliza pentru eliberarea spaŃiului de pe disc corespunzător coloanelor nefolosite din tabel. Dacă tabelul nu conŃine nici o coloană nefolosită, instrucŃiunea nu întoarce o eroare şi nu are nici un efect.

Atunci când se elimină o coloană dintr-un tabel folosind opŃiunea DROP a comenzii ALTER TABLE, vor fi suprimate şi coloanele din tabel care sunt marcate cu opŃiunea SET UNUSED.

Suprimarea unui tabel Pentru ştergerea unui tabel este utilizată comanda DROP TABLE:

DROP TABLE [nume_schema.]nume_tabel [CASCADE CONSTRAINTS];

Clauza CASCADE CONSTRAINTS permite suprimarea tuturor constrângerilor de integritate referenŃială corespunzătoare cheilor primare şi unice din tabelul supus ştergerii. Dacă se omite această clauză şi există

Page 219: CURS BD Combinat

54

constrângeri de integritate referenŃială, sistemul returnează o eroare şi nu suprimă tabelul.

Suprimarea unui tabel presupune: 0suprimarea definiŃiei sale în dicŃionarul datelor; 0suprimarea indecşilor asociaŃi; 0suprimarea privilegiilor conferite în legătură cu tabelul; 0recuperarea spaŃiului ocupat de tabel;

0permanentizarea tranzactiilor in asteptare; 0invalidarea (dar nu suprimarea) funcŃiilor, procedurilor,

vizualizărilor, secventelor, sinonimelor referitoare la tabel.

Odată executată, instrucŃiunea DROP TABLE este ireversibilă. Ca şi în cazul celorlalte instrucŃiuni ale limbajului de definire a datelor, această comandă nu poate fi anulată (ROLLBACK).

InstrucŃiunea DROP InstrucŃiunea DROP este cea mai simplă dintre instrucŃiunile DDL. Sintaxa de bază este:

Pentru ştergerea unui tabel este utilizată comanda DROP TABLE:

DROP TABLE [nume_schema.]nume_tabel [CASCADE CONSTRAINTS];

Clauza CASCADE CONSTRAINTS permite suprimarea tuturor constrângerilor de integritate referenŃială corespunzătoare cheilor primare şi unice din tabelul supus ştergerii. Dacă se omite această clauză şi există constrângeri de integritate referenŃială, sistemul returnează o eroare şi nu suprimă tabelul.

Suprimarea unui tabel presupune: 0suprimarea definiŃiei sale în dicŃionarul datelor; 0suprimarea indecşilor asociaŃi; 0suprimarea privilegiilor conferite în legătură cu tabelul; 0recuperarea spaŃiului ocupat de tabel;

0permanentizarea tranzactiilor in asteptare; 0invalidarea (dar nu suprimarea) funcŃiilor, procedurilor,

vizualizărilor, secventelor, sinonimelor referitoare la tabel. Odată executată, instrucŃiunea DROP TABLE este ireversibilă. Ca şi în cazul celorlalte instrucŃiuni ale limbajului de definire a datelor, această comandă nu poate fi anulată (ROLLBACK).

Page 220: CURS BD Combinat

55

Tipul de obiect specifică tipul obiectului care urmează să fie şters, cum ar fi INDEX, TABLE sau VIEW. OpŃiunile de ştergere sunt specifice fiecărui SGBD. Sintaxa este diferită de la un producător la altul — PostgreSQL şi MySQL folosesc în acest scop cuvântul cheie CASCADE, în timp ce în Oracle trebuie să se folosească CASCADE CONSTRAINTS. Exemplu: DROP TABLE COD_CLIENT; DROP TABLE COD_CLIENT CASCADE CONSTRAINTS; (Oracle) DROP INDEX IX_TITLU_FILM;

Pentru ştergerea întregului conŃinut al unui tabel şi eliberarea

spaŃiului de memorie ocupat de acesta, sistemul Oracle oferă instrucŃiunea:

TRUNCATE TABLE nume_tabel;

Fiind o instrucŃiune DDL, aceasta nu poate fi anulată ulterior

(printr-o operaŃie ROLLBACK). Ea reprezintă o alternativă a comenzii DELETE din limbajul de prelucrare a datelor(DML). De remarcat că instrucŃiunea DELETE nu eliberează spaŃiul de memorie. Comanda TRUNCATE este mai rapidă deoarece nu generează informaŃie ROLLBACK şi nu activează declanşatorii asociaŃi operaŃiei de ştergere. Dacă tabelul este „părintele“ unei constrângeri de integritate referenŃială, el nu poate fi trunchiat. Pentru a putea fi aplicată instrucŃiunea TRUNCATE, constrângerea trebuie să fie mai întâi dezactivată.

In DDL, informaŃiile despre tabele se găsesc în vizualizarea USER_TABLES.

Dintre cele mai importante coloane ale acesteia, se remarca le obtinem cu instructiunea:

Page 221: CURS BD Combinat

56

DESCRIBE USER_TABLES;

TABLE_NAME Numele tabelului TABLESPACE_NAME SpaŃiul tabel în care se află tabelul CLUSTER_NAME Numele cluster-ului din care face parte tabelul PCT_FREE Procentul de spaŃiu păstrat liber în interiorul fiecărui

bloc PCT_USED Procentul de spaŃiu ce poate fi utilizat în fiecare bloc INI_TRANS Numărul iniŃial de tranzacŃii concurente în interiorul

unui bloc NITIAL_EXTENT Dimensiunea spaŃiului alocat pentru prima extensie NEXT_EXTENT Dimensiunea spaŃiului alocat pentru următoarea

extensie MIN_EXTENTS Numărul minim de extensii ce se alocă la crearea

unui tabel MAX_EXTENTS Numărul maxim de extensii ce se alocă la crearea

unui tabel PCT_INCREASE Procentul cu care creşte dimensiunea unei extensii BACKED_UP Y sau N, după cum tabelului i-a fost făcută o copie de

siguranŃă de la ultima modificare NUM_ROWS Numărul de înregistrări din tabel BLOCKS Numărul de blocuri utilizate de tabel EMPTY_BLOCKS Numărul de blocuri ce nu conŃin date AVG_SPACE SpaŃiul mediu liber din tabel AVG_ROW_LEN Lungimea medie, în octeŃi, a unei linii TABLE_LOCK ENABLED (activat) sau DISABLED (dezactivat):

este activată sau nu blocarea tabelului PARTITIONED YES sau NO, indică dacă tabelul este partiŃionat (sau

nu) TEMPORARY Y sau N, indică dacă tabelul este temporar (sau nu) NESTED YES sau NO, indică dacă tabelul este imbricat (sau

nu)

Exemplu: SELECT TABLE_NAME, NUM_ROWS, NESTED FROM USER_TABLES;

Exemplu: SELECT 'DROP TABLE ' || OBJECT_NAME || ';' FROM USER_OBJECTS WHERE OBJECT_TYPE = 'TABLE';

Page 222: CURS BD Combinat

57

Instruc Ńiunea CREATE INDEX Indexurile sunt instrumente puternice, deoarece permit sistemului

să găsescă datele mult mai repede, tot aşa cum indexul unei cărŃi ne permite să găsim mai rapid ceea ce ne interesează. De asemenea, indexurile pe coloanele cheilor externe cresc mult peformanŃele la unirea tabelelor. Sistemul SGBD întreŃine automat indexul, dar activitatea de întreŃinere consumă din resursele calculatorului.

Pentru îmbunătăŃirea performanŃelor unor interogări, trebuie luată în considerare crearea unui index. De asemenea, un index poate fi utilizat pentru a impune unicitatea valorilor unei coloane sau ale unei colecŃii de coloane.

Un index este un obiect al schemei, care conŃine câte o intrare pentru fiecare valoare ce apare în coloanele indexate ale unui tabel sau grupare şi determină accesul rapid şi direct la înregistrări, prin utilizarea unui pointer.

Indecşii sunt utilizaŃi şi întreŃinuŃi automat de către server-ul Oracle. Odată creat, un index nu necesită o acŃiune directă din partea utilizatorului.

Un index poate fi creat asupra: • uneia sau mai multor coloane ale unui tabel nepartiŃionat,

partiŃionat, organizat pe bază de index sau ale unui cluster; • unuia sau mai multor atribute de tip scalar ale unui obiect dintr-

Page 223: CURS BD Combinat

58

un tabel sau cluster; • unui tabel imbricat.

Indecşii sunt independenŃi din punct de vedere logic şi fizic de tabelul pe care îl indexează. Aceasta înseamnă că indecşii pot fi creaŃi sau suprimaŃi la orice moment fără a avea vreun efect asupra tabelelor de bază sau asupra altor indecşi.

Un index este un obiect al schemei unei baze de date care: • creşte viteza de execuŃie a cererilor; • garantează că o coloană conŃine valori unice.

Un index trebuie să aibă cel puŃin o coloană, dar, nu există o limită superioară a numărului de coloane.

Server-ul Oracle utilizează identificatorul ROWID pentru regăsirea liniilor în structura fizică a bazei de date. Indexul, din punct de vedere logic, este compus dintr-o valoare cheie şi din identificatorul adresă ROWID. select rowid, cod_artist,nume,prenume from artist; ROWID COD_ARTIST NUME PRENUME ------------------ ---------- ------------------------------ ------------ AAAHkEAAJAAAAbPAAA 1 Grigorescu Dan AAAHkEAAJAAAAbPAAB 2 ene ana select * from artist where rowid='AAAHkEAAJAAAAbPAAA'; COD_ARTIST NUME PRENUME -------------------- ----------------------- ------------------------ 1 Grigorescu Dan

Cheia indexului poate fi coloana unui tabel sau concatenarea mai

multor coloane (numărul maxim de coloane care pot defini cheia indexului este 32). Coloanele care apar în cheia indexului trebuie declarate NOT NULL în tabel.

Indecşii sunt utilizaŃi şi întreŃinuŃi automat de către server-ul Oracle. Odată creat indexul, el nu necesită o acŃiune directă din partea utilizatorului.

Indecşii pot fi creaŃi în două moduri: • automat, de server-ul Oracle (PRIMARY KEY, UNIQUE);

Page 224: CURS BD Combinat

59

• manual, de către utilizator (CREATE INDEX).

Server-ul Oracle creează automat un index unic atunci când se defineşte o constrângere PRIMARY KEY sau UNIQUE asupra unei coloane sau unui grup de coloane. Numele indexului va fi acelaşi cu numele constrângerii.

Indecşii, fiind obiecte ale schemei bazei, beneficiază de procesul de definire a unui obiect.

Crearea unui index (care nu este obligatoriu unic) pe una sau mai

multe coloane ale unui tabel se face prin comanda: CREATE [{UNIQUE | BITMAP} ] [UNIQUE] INDEX <nume_index> ON [<nume_schema>.] <nume_tabel> (<nume_col> [ASC | DESC], <nume_col> [ASC | DESC], …);

Cuvântul cheie opŃional UNIQUE defineşte indexul ca unic, însemnând că nu pot exista două rânduri din tabel cu exact acceaşi combinaŃie de valori în coloanele specificate. Această clauză nu poate fi specificată alături de clauza BITMAP sau pentru un index domeniu.

Clauza BITMAP determină crearea indexului cu o hartă de biŃi (bitmap) pentru fiecare cheie distinctă, în loc de a indexa separat fiecare linie. Fiecare bit din bitmap corespunde unei valori ROWID posibile. Dacă un bit este setat, înseamnă că linia având valoarea ROWID corespunzătoare acestuia conŃine valoarea cheii. Reprezentarea internă a bitmap-urilor este adecvată aplicaŃiilor cu niveluri scăzute ale tranzacŃiilor concurente (de exemplu, aplicaŃii data warehouse).

Cuvântul cheie opŃional ASC creează indexul în ordine crescătoare,

în timp ce DESC creează indexul în ordine descrescătoare. Dacă nu este specificată nici una dintre cele două opŃiuni, ordinea prestabilită este crescătoare.

Când este creat un index, un segment de date este rezervat automat în spaŃiul tabel. Alocarea de memorie este controlată prin clauzele INITIAL_EXTENT, PCT_INCREASE, PCT_FREE, NEXT, care pot să apară în comanda CREATE INDEX.

Exemplu: 1) Să se creeze un index descrescător relativ la coloana adresa din

tabelul cititor.

CREATE INDEX cititor_idx

Page 225: CURS BD Combinat

60

ON cititor (adresa DESC);

CREATE INDEX cit_den ON cititor (DEN_CITITOR); 2) Să se afişeze informaŃiile referitoare la indexul cititor_idx.

SELECT TABLE_NAME FROM USER_INDEXES WHERE INDEX_NAME=’CITITOR_IDX’;

SELECT TABLE_NAME FROM USER_INDEXES WHERE INDEX_NAME=’CIT_DEN’; 3) Să se afişeze toate indexurile(numele tabelelor, numele indexului si

daca a fost sau nu generat)

SELECT TABLE_NAME, INDEX_NAME, TABLE_TYPE FROM USER_INDEXES;

4)Să se creeze un index explicit, referitor la cheia primara a unui tabel.

Pentru a schimba numele unei chei altul decit cel dat de sistem oracle, Sys_Cn;

CREATE TABLE exem ( cod_id NUMBER(6) PRIMARY KEY USING INDEX (CREATE INDEX cod_id_idx ON exem (cod_id)), nume VARCHAR2(20));

Mai mulŃi indecşi asupra unui tabel nu implică întotdeuna interogări mai rapide. Fiecare operaŃie LMD care este permanentizată asupra unui tabel cu indecşi asociaŃi presupune actualizarea indecşilor respectivi.

Prin urmare, este recomandată crearea de indecşi numai în anumite situaŃii:

• coloana conŃine o varietate mare de valori; • coloana conŃine un număr mare de valori null; • una sau mai multe coloane sunt utilizate frecvent împreună într-

o clauză WHERE sau într-o condiŃie de join; • tabelul este mare şi este de aşteptat ca majoritatea interogărilor

asupra acestuia să regăsească mai puŃin de 2-4% din linii.

Page 226: CURS BD Combinat

61

Crearea unui index nu este recomandată în următoarele cazuri: • tabelul este mic; • coloanele nu sunt utilizate des în cadrul unei condiŃii dintr-o

cerere; • majoritatea interogărilor regăsesc mai mult de 2-4% din liniile

tabelului; • tabelul este actualizat frecvent; • coloanele indexate sunt referite în expresii.

In concluzie, ce tabele sau ce coloane trebuie (sau nu) indexate?

• indexaŃi tabelele pentru care interogările selectează un număr redus de rânduri (sub 5%);

• indexaŃi tabelele care sunt interogate folosind clauze SQL simple;

• nu indexaŃi tabelele ce conŃin puŃine înregistrări (accesul secvenŃial este mai simplu);

• nu indexaŃi tabelele care sunt frecvent actualizate, deoarece ştergerile, inserările şi modificările sunt îngreunate de indecşi;

• indexaŃi coloanele folosite frecvent în clauza WHERE sau în clauza ORDER BY;

• nu indexaŃi coloanele ce conŃin date asemănătoare (puŃine valori distincte);

Exemplu: Pentru a asigura că server-ul Oracle utilizează indexul şi nu

efectuează o căutare asupra întregului tabel, valoarea funcŃiei corespunzătoare expresiei indexate trebuie să nu fie null în interogările ulterioare creării indexului. Următoarea instrucŃiune garantează utilizarea indexului dar, în absenŃa clauzei WHERE, server-ul Oracle ar putea cerceta întreg tabelul.

SELECT * FROM artist WHERE UPPER(nume) IS NOT NULL ORDER BY UPPER(nume);

Exemplu: Să se creeze tabelul artist, specificându-se indexul asociat cheii

primare.

CREATE TABLE artist( cod_artist NUMBER PRIMARY KEY USING INDEX (CREATE INDEX artist_cod_idx ON artist(cod_artist)),

Page 227: CURS BD Combinat

62

nume VARCHAR2(30) NOT NULL, prenume VARCHAR2(30)); INSERT INTO ARTIST VALUES(1,’Grigorescu’,’Dan’); INSERT INTO ARTIST VALUES(2,’ene’,’ana’); INSERT INTO ARTIST VALUES(4,’Adam’,’Horia’); (trebuie creat privilegiu din Security ..query rewrite)

CREATE INDEX up_nume_id

ON artist(UPPER(nume));

Indexul creat prin instrucŃiunea precedentă facilitează prelucrarea unor interogări precum:

SELECT * FROM artist WHERE UPPER(nume) = 'ene';

Ştergerea unui index se face prin comanda:

DROP INDEX nume_index [ON [nume_schema.] nume_tabel]

Pentru a suprima indexul trebuie ca acesta să se găsească în schema personală sau să ai privilegiul de sistem DROP ANY INDEX.

Pentru a reconstrui un index se pot folosi două metode: • se şterge indexul (DROP INDEX) şi se recreează (CREATE

INDEX); • se utilizează comanda ALTER INDEX cu opŃiunea REBUILD.

Modificarea parametrilor de stocare a indecşilor (STORAGE), alocarea (ALLOCATE EXTENT) şi dealocarea (DEALLOCATE UNUSED) manuală a spaŃiului utilizat de un index se pot realiza cu ajutorul comenzii ALTER INDEX. Începând cu Oracle9i, este posibilă modificarea structurii indecşilor prin comanda ALTER INDEX.

Validarea unui index, adică verificarea integrităŃii indexului specificat pentru un tabel, se face prin comanda:

VALIDATE INDEX nume_index [ON nume_tabel] [WITH LIST] VALIDATE INDEX artist_cod_idx;

InformaŃii referitoare la indecşi şi la coloanele care îi definesc pot fi regăsite în vizualizările USER_INDEXES, respectiv

Page 228: CURS BD Combinat

63

USER_IND_COLUMNS din dicŃionarul datelor. Dintre coloanele tabelului USER_INDEXES se remarcă, dând

Desc USER_INDEXES;

INDEX_NAME Numele indexului INDEX_TYPE Tipul indexului (NORMAL, LOB, CLUSTER etc.) TABLE_OWNER Proprietarul tabelului indexat TABLE_NAME Numele tabelului indexat TABEL_TYPE Tipul tabelului indexat (TABLE, CLUSTER etc.) UNIQUENESS Starea de unicitate (UNIQUE, NONUNIQUE) TABLESPACE_NAME SpaŃiul tabel în care este stocat indexul INITIAL_EXTENT SpaŃiul alocat pentru prima extensie NEXT_EXTENT SpaŃiul alocat pentru următoarea extensie MIN_EXTENTS Numărul minim de extensii alocate MAX_EXTENTS Numărul maxim de extensii PCT_INCREASE Procentul cu care cresc extensiile BLEVEL Nivelul din B-arbore. Acesta arată adâncimea indexului de

la ramuri la frunze LEAF_BLOCKS Numărul de blocuri frunză din index DISTINCT_KEYS Numărul de chei distincte în index STATUS Starea indexului (VALID, INVALID, DIRECT_LOAD) NUM_ROWS Numărul de linii utilizate. Acesta nu trebuie să includă

valorile NULL din tabelul de bază PARTITIONED Determină dacă indexul este partiŃionat (YES sau NO) GENERATED Determină dacă sistemul a generat numele indexului (Y)

sau utilizatorul (N)

SELECT TABLE_NAME, INDEX_NAME, TABLE_TYPE FROM USER_INDEXES;

Page 229: CURS BD Combinat

64

Pentru a vedea informatiile din USER_IND_COLUMNS, avem Desc USER_IND_COLUMNS;

Exemplu: Să se obŃină informaŃii referitoare la indecşii tabelului carte.

Page 230: CURS BD Combinat

65

SELECT a.index_name, a.column_name, a.column_position poz, b.uniqueness FROM user_indexes b, user_ind_columns a WHERE a.index_name = b.index_name AND a.table_name = ’CITITOR’;

SecvenŃe

Multe aplicaŃii necesită utilizarea de numere unice ca valori ale cheilor primare. Pentru a obŃine astfel de numere, se pot implementa în aplicaŃie unităŃi de program corespunzătoare sau se pot utiliza secvenŃe.

De obicei, secvenŃele sunt utilizate pentru crearea de valori ale cheii primare care trebuie să fie unice pentru fiecare linie. SecvenŃa este incrementată sau decrementată de către o rutină internă Oracle. Numerele secvenŃei sunt stocate şi generate independent de tabele. Prin urmare, aceeaşi secvenŃă poate fi utilizată pentru mai multe tabele.

O secvenŃă este un obiect al bazei de date, creat de utilizator. Acest obiect poate fi folosit de mai mulŃi utilizatori pentru a genera numere întregi unice în sistemele multi-utilizator, evitând apariŃia conflictelor şi a blocării.

O secvenŃă poate fi creată de un utilizator şi poate fi partajată de mai mulŃi utilizatori.

Page 231: CURS BD Combinat

66

Crearea unei secvenŃe se face cu ajutorul comenzii:

CREATE SEQUENCE [<nume_schema>.]<nume_secventa> [INCREMENT BY n] [START WITH m] [{ MAXVALUE n | NOMAXVALUE}] [{MINVALUE n|NOMINVALUE}] [{ CACHE k | NOCACHE}]

OpŃiunea INCREMENT BY specifică diferenŃa dintre valorile succesive ale secvenŃei. Dacă această opŃiune este omisă, numerele generate de secvenŃă vor fi incrementate prin valoarea 1.

OpŃiunea START WITH specifică primul număr care va fi generat de secvenŃă. Dacă această opŃiune este omisă, secvenŃa începe de la valoarea 1.

OpŃiunile MAXVALUE, MINVALUE precizează valoarea maximă, respectiv minimă pe care o poate genera secvenŃa. OpŃiunile NOMAXVALUE, NOMINVALUE sunt implicite. NOMAXVALUE specifică valoarea maximă de 1027 pentru o secvenŃă crescătoare şi -1 pentru o secvenŃă descrescătoare. NOMINVALUE specifică valoarea minimă 1 pentru o secvenŃă crescătoare şi -1026 pentru o secvenŃă descrescătoare.

OpŃiunile CYCLE şi NOCYCLE specifică dacă secvenŃa continuă să genereze numere după obŃinerea valorii maxime sau minime. NOCYCLE este opŃiunea implicită. Se recomandă să nu fie utilizată opŃiunea CYCLE dacă secvenŃa este folosită pentru generarea de chei primare, cu excepŃia cazului în care există un mecanism care şterge liniile vechi din tabel mai repede decât ciclează secvenŃa.

CACHE k precizează numărul de valori pe care server-ul Oracle le prealocă şi le păstrează în memorie. În mod implicit, acest număr de valori este 20. OpŃiunea CACHE pemite accesul mai rapid la valorile secvenŃei care sunt păstrate în memorie. Aceste valori sunt generate la prima referinŃă asupra secvenŃei. Fiecare valoare din secvenŃă se furnizează din secvenŃa memorată. După utilizarea ultimei valori prealocate secvenŃei, următoarea solicitare a unei valori determină încărcarea unui alt set de numere în memorie. Pentru a nu fi prealocate şi reŃinute în memorie astfel de valori, se utilizează opŃiunea NOCACHE.

O secvenŃă este referită într-o comandă SQL cu ajutorul pseudo-coloanelor:

• NEXTVAL – referă valoarea următoare a secvenŃei;

• CURRVAL – referă valoarea curentă a secvenŃei.

Page 232: CURS BD Combinat

67

NEXTVAL şi CURRVAL pot fi folosite în:

• clauza VALUES a unei comenzi INSERT;

• clauza SET a unei comenzi UPDATE;

• lista SELECT a unei subcereri dintr-o comanda INSERT;

• lista unei comenzi SELECT.

NEXTVAL şi CURRVAL nu pot fi folosite în: • subinterogare in SELECT, DELETE sau UPDATE;

• interogarea unei vizualizări;

• comandă SELECT cu operatorul DISTINCT;

• comandă SELECT cu clauza GROUP BY, HAVING sau ORDER BY;

• clauza WHERE a unei comenzi SELECT;

• condiŃia unei constrângeri CHECK; • valoarea DEFAULT a unei coloane într-o comandă CREATE

TABLE sau ALTER TABLE; • comandă SELECT care este combinată cu altă comandă SELECT

printr-un operator mulŃime (UNION, INTERSECT, MINUS).

Din dicŃionarul datelor pot fi obŃinute informaŃii despre secvenŃe folosind vizualizarea USER_SEQUENCES.

1) Să se creeze o secvenŃă domeniuseq care să fie utilizată pentru a

insera noi domenii în tabelul domeniu şi să se insereze un nou domeniu.

2) Să se afişeze informaŃiile referitoare la secvenŃa domeniuseq.

CREATE SEQUENCE domeniuseq START WITH 4 INCREMENT BY 1; INSERT INTO domeniu VALUES (domeniuseq.NEXTVAL,’Arta’);

Page 233: CURS BD Combinat

68

SELECT INCREMENT_BY,MAX_VALUE, MIN_VALUE FROM USER_SEQUENCES WHERE SEQUENCE_NAME = 'DOMENIUSEQ’;

Modificarea unei secvenŃe se face prin comanda ALTER SEQUENCE. Sintaxa comenzii este similară instrucŃiunii CREATE SEQUENCE , dar:

• noua valoare maximă pentru MAXVALUE nu poate fi mai mică decât valoarea curentă;

• opŃiunea START WITH nu poate fi modificată de comandă. Exemplu: Să se schimbe pasul secventei de la 1 la 2

ALTER SEQUENCE DOMENIUSEQ

INCREMENT BY 2;

Suprimarea unei secvenŃe se face cu ajutorul comenzii:

DROP SEQUENCE [<nume_schema>.]<nume_secventa>;

După ce a fost ştearsă, secvenŃa nu mai poate fi referită. Pentru a putea şterge sau modifica secvenŃa trebuie fie să fi proprietarul acesteia, fie să ai privilegiul de sistem DROP ANY SEQUENCE, respectiv privilegiul ALTER SEQUENCE.

DROP SEQUENCE domeniuseq;

Sinonime

Page 234: CURS BD Combinat

69

Oracle oferă posibilitatea de a atribui mai multe nume aceluiaşi obiect. Aceste nume adiŃionale sunt numite sinonime (synonymes). Ele sunt utile deoarece permit simplificarea formulării cererii şi referirea la obiecte, fără a fi nevoie să se specifice proprietarii obiectelor sau localizarea acestora(schema).

Spre deosebire de alias a cărui durată de viaŃă este limitată la cererea ce conŃine alias-ul, sinonimele sunt salvate în dicŃionarul datelor şi pot fi reutilizate.

Sistemul Oracle permite crearea de sinonime pentru obiecte de tipul: tabel, vizualizare, secvenŃă, funcŃie, procedură, pachet, clişeu, sinonim.

Crearea unui sinonim se realizează prin comanda:

CREATE [PUBLIC] SYNONYM [schema.]nume_sinonim FOR [schema.]obiect

Exemplu:

CREATE SYNONYM artist1 FOR artist;

SELECT * from user_objects;

SELECT * from artist1; CREATE SYNONYM domeniu1seq for domeniuseq;

Administratorul bazei poate produce şi poate suprima sinonime publice sau private, iar utilizatorii pot genera sau suprima doar sinonime private. Pentru suprimarea unui sinonim din baza de date se utilizează comanda:

DROP [PUBLIC] SYNONYM [schema.]nume_sinonim

Page 235: CURS BD Combinat

70

Vizualizări

O vizualizare (view) nu conŃine date şi poate fi interpretată ca o „fereastră“ prin care informaŃiile din tabele pot fi consultate şi modificate. Un astfel de obiect al bazei de date extrage rezultatul unei cereri şi îl tratează ca pe un tabel. Prin urmare, o vizualizare poate fi considerată drept o cerere stocată sau un tabel virtual. O vizualizare este o interogare SQL stocată, care poate fi referită de instrucŃiunile SQL DML şi DQL ca şi cum ar fi un tabel real. Unii consideră că vizualizările sunt „tabele virtuale", deoarece se comportă la fel ca tabelele, dar nu există ca tabele fizice.

Numele vizualizării trebuie să respecte aceleaşi reguli de denumire

ca şi tabelele şi alte obiecte ale bazei de date. Interogarea SQL inclusă în definiŃia vizualizării poate fi orice

instrucŃiunea SQL SELECT validă. Vizualizarea (view) este un tabel logic (virtual) relativ la date din

una sau mai multe tabele sau vizualizări. Vizualizarea este definită plecând de la o cerere a limbajului de interogare a datelor, moştenind caracteristicile obiectelor la care se referă. Vizualizarea, fiind virtuală, nu solicită o alocare de memorie pentru date. Ea este definită în DD cu aceleaşi caracteristici ca şi un tabel.

Spre deosebire de tabele, pentru conŃinutul vizualizării nu se alocă spaŃiu de stocare. SpaŃiul ocupat de o vizualizare este doar cel alocat definiŃiei acesteia (cererii stocate) din dicŃionarul datelor. Tabelele din care cererea stocată selectează date se numesc tabele de bază ale vizualizării. Ele pot fi tabele sau chiar vizualizări, inclusiv vizualizări materializate.

Textul cererii care defineşte vizualizarea este salvat în DD. Nucleul Oracle determină fuzionarea cererii relative la vizualizare cu comanda de definire a vizualizării, analizează rezultatul fuziunii în zona partajată şi execută cererea.

Oracle transformă cererea referitoare la o vizualizare într-o cerere relativă la tabelele de bază. Vizualizarea este memorata in DD sub forma unui SELECT.

Dacă sunt utilizate clauzele UNION, GROUP BY şi CONNECT BY, atunci Oracle nu determină fuzionarea, el va rezolva vizualizarea şi apoi va aplica cererea rezultatului obŃinut.

Page 236: CURS BD Combinat

71

O vizualizare reflectă la orice moment conŃinutul exact al tabelelor de bază. Orice modificare efectuată asupra tabelelor se repercutează instantaneu asupra vizualizării. Ştergerea unui tabel implică invalidarea vizualizărilor asociate tabelului şi nu ştergerea acestora.

Vizualizările sunt definite pentru: • furnizarea unui nivel mai înalt de securizare a bazei; • simplificarea formulării unei cereri; • mascarea complexităŃii datelor; • afişarea datelor într-o altă reprezentare decât cea a tabelelor de

bază; • asigurarea independenŃei datelor; • asigurarea confidenŃialităŃii anumitor informaŃii; • definirea constrângerilor de integritate; • restricŃionarea acesului la date.

Vizualizările pot fi simple şi complexe. O vizualizare simplă extrage date dintr-un singur tabel, nu conŃine funcŃii sau grupări de date şi asupra ei pot fi efectuate operaŃii LMD.

O vizualizare este considerată complexă dacă extrage date din mai multe tabele, conŃine funcŃii sau grupări de date şi nu permite întotdeauna (prin intermediul său) operaŃii LMD asupra tabelelor de bază.

OperaŃiile LMD asupra vizualizărilor complexe sunt restricŃionate de următoarele reguli:

• nu se poate insera, actualiza sau şterge o linie dintr-o vizualizare dacă aceasta conŃine funcŃii grup, clauza GROUP BY, cuvântul cheie DISTINCT sau pseudocoloana ROWNUM;

• nu se poate adăuga sau modifica o linie dintr-o vizualizare, dacă aceasta conŃine coloane definite prin expresii;

• nu pot fi adăugate linii printr-o vizualizare, dacă tabelul de bază conŃine coloane care au constrângerea NOT NULL şi nu apar în lista SELECT a vizualizării.

Pentru a obŃine informaŃii referitoare la vizualizările definite, se pot interoga vizualizările USER_VIEWS şi ALL_VIEWS din dicŃionarul datelor. Textul instrucŃiunii SELECT care defineşte o vizualizare este stocat într-o coloană de tip LONG, numită TEXT.

Atunci când datele sunt accesate prin intermediul unei vizualizări, server-ul Oracle efectuează următoarele operaŃii:

• recuperează definiŃia acesteia din USER_VIEWS; • verifică privilegiile de acces la tabelele ei de bază; • converteşte cererea într-o operaŃie echivalentă asupra tabelelor

de bază.

Page 237: CURS BD Combinat

72

Crearea unei vizualizări se realizează cu ajutorul comenzii:

CREATE [OR REPLACE][FORCE | NOFORCE] VIEW [<nume_schema>.]<nume_view> [(<alias>[,<alias>]…)] AS <cerere_SELECT> [WITH { CHECK OPTION [CONSTRAINT <nume_constrangere>] | READ ONLY }];

– OR REPLACE recreează vizualizarea dacă aceasta deja există.

– FORCE creează vizualizarea chiar dacă tabelul de bază nu există sau chiar dacă vizualizarea face referinŃă la obiecte care încă nu sunt create. Deşi vizualizarea va fi creată, utilizatorul nu poate să o folosească.

– NO FORCE este implicită şi se referă la faptul că vizualizarea este creată numai dacă tabelele de bază există.

– Cererea este o comandă SELECT care poate să conŃină alias pentru coloane.

– WITH CHECK OPTION specifică faptul că reactualizarea datelor din tabele (inserare sau modificare) se poate face numai asupra datelor selectate de vizualizare (care apar în clauza WHERE).

– WITH READ ONLY asigură că nici o operaŃie LMD nu poate fi executată asupra vizualizării.

Exemplu:

Să se genereze o vizualizare care conŃine informaŃii referitoare la împrumutul cărŃilor şi în care să fie implementată constrîngerea că orice carte, care există într-un singur exemplar, poate fi împrumutată maximum 15 zile.

CREATE VIEW imprumutare AS SELECT * FROM imprumuta WHERE codel NOT IN

(SELECT codel FROM carte WHERE nrex = 1)

OR datares - dataim < 15 WITH CHECK OPTION;

Cererea care defineşte vizualizarea poate fi complexă, incluzând join-uri, grupări şi subcereri, însă nu poate conŃine clauza ORDER BY. Dacă este necesar, această clauză poate fi specificată la interogarea vizualizării. Interogarea unei vizualizări este similară celei unui tabel.

Page 238: CURS BD Combinat

73

Numărul coloanelor specificate în definiŃia vizualizării trebuie să fie egal cu cel din lista asociată comenzii SELECT.

Asupra cererii care defineşte vizualizarea se impun următoarele restricŃii:

• nu pot fi selectate pseudocoloanele CURRVAL şi NEXTVAL ale unei secvenŃe;

• dacă sunt selectate pseudocoloanele ROWID, ROWNUM sau LEVEL, acestora trebuie să li se specifice alias-uri;

• dacă cererea selectează toate coloanele unui tabel, utilizând simbolul „*“, iar ulterior se adaugă coloane noi tabelului, vizualizarea nu va conŃine acele coloane până la recrearea sa printr-o instrucŃiune CREATE OR REPLACE VIEW;

• pentru vizualizările obiect, numărul şi tipul elementelor selectate de cerere trebuie să coincidă cu cel al atributelor de pe primul nivel al tipului obiect.

Aportul versiunii Oracle9i în ceea ce priveşte instrucŃiunea CREATE VIEW constă în posibilitatea:

• creării de subvizualizări ale vizualizărilor obiect; • definirii de constrângeri asupra vizualizărilor.

Exemplu: a) Să se creeze o vizualizare care conŃine numele şi prenumele

artistului, numărul operelor sale şi valoarea medie a acestora. CREATE VIEW artist_nr_val(nume, numar_opere, val_medie) AS SELECT a.nume || ' ' || a .prenume "Nume si prenume", COUNT(o. cod_opera) numar, AVG(o.valoare) medie FROM opera o, artist a WHERE o.cod_artist = a.cod_artist GROUP BY o.cod_artist, a.nume, a.prenume;

b) Să se creeze vizualizarea sculptura ce va conŃine codul operei, data achiziŃiei, codul artistului şi stilul operelor al căror tip este „sculptura“.

CREATE OR REPLACE VIEW sculptura (cod_sculptura, informatii, cod_sculptor, stil) AS SELECT cod_opera, 'Sculptura ' || titlu || ' a fost achizitionata la data ' || data_achizitiei, cod_artist, stil FROM opera WHERE tip = 'sculptura';

Page 239: CURS BD Combinat

74

Modificarea unei vizualizări presupune modificarea definiŃiei

acesteia. Pentru a înlocui o vizualizare trebuie avut privilegiul de

sistem necesar pentru distrugerea şi crearea acesteia. Înlocuirea se

poate face în două moduri.

• Vizualizarea poate fi distrusă (DROP VIEW) şi apoi recreată (CREATE) cu noua definiŃie. Atunci când este distrusă, toate privilegiile sunt retrase. Aceste privilegii trebuie să fie create pentru noua vizualizare.

• Vizualizarea poate fi recreată prin redefinire cu instrucŃiunea CREATE VIEW, dar cu clauza OR REPLACE. Această metodă conservă toate privilegiile curente.

In Oracle9i este posibila adaugarea de constrangeri unei vizualizari

prin comanda ALTER VIEW.

Modificarea unui vizualizări are următoarele efecte:

• definiŃia vizualizării din DD este actualizată;

• nici unul din obiectele de bază nu este afectat de înlocuire;

• toate restricŃiile care existau în vizualizarea originală sunt distruse;

• toate vizualizările şi programele PL/SQL dependente de vizualizarea înlocuită devin invalide.

Suprimarea unei vizualizări se realizează prin comanda DROP VIEW care şterge definiŃia vizualizării din baza de date.

DROP VIEW <nume_view> [CASCADE CONSTRAINT];

Ştergerea vizualizării nu va afecta tabelele relativ la care a fost definită vizualizarea. AplicaŃiile şi vizualizările care se bazează pe vizualizarea suprimată devin invalide. Pentru a suprima o vizualizare, utilizatorul trebuie să aibă privilegiul DROP ANY VIEW sau să fie creatorul vizualizării respective.

Similar opŃiunii corespunzătoare din comanda DROP TABLE, clauza CASCADE CONSTRAINTS permite suprimarea tuturor constrângerilor de integritate referenŃială corespunzătoare cheilor primare şi unice din vizualizarea supusă ştergerii. Dacă se omite această clauză şi

Page 240: CURS BD Combinat

75

există astfel de constrângeri, instrucŃiunea DROP VIEW va eşua.

Recompilarea unei vizualizări permite detectarea eventualelor erori referitoare la vizualizare, înaintea executării vizualizării. După fiecare modificare a tabelelor de bază este recomandabil ca vizualizarea să se recompileze:

ALTER VIEW <nume_view> COMPILE;

Reactualizarea tabelelor implică reactualizarea corespunzătoare a vizualizărilor!!!

Reactualizarea vizualizărilor implic ă reactualizarea tabelelor de bază? NU! Există restricŃii care trebuie respectate!!!

• Nu pot fi modificate date din vizualizare sau adaugate date prin vizualizare, daca aceasta contine coloane definite prin expresii.

• Nu pot fi înserate, şterse sau actualizate date din vizualizări ce conŃin: operatorul DISTINCT; clauzele GROUP BY, HAVING, START WITH, CONNECT BY; pseudo-coloana ROWNUM; funcŃii grup; operatori de mulŃimi.

• Nu pot fi inserate sau actualizate date care ar încălca constrângerile din tabelele de bază.

• Nu pot fi inserate sau actualizate valorile coloanelor care rezultă prin calcul.

• Nu se pot face operaŃii LMD asupra coloanelor calculate cu DECODE.

Alături de restricŃiile prezentate anterior, aplicabile tuturor vizualizărilor, există restricŃii specifice, aplicabile vizualizărilor bazate pe mai multe tabele.

Regula fundamentală este că orice operaŃie INSERT, UPDATE sau DELETE pe o vizualizare bazată pe mai multe tabele poate modifica datele doar din unul din tabelele de bază. In care???

Un tabel de bază al unei vizualizări este protejat prin cheie (key preserved table) dacă orice cheie selectată a tabelului este de asemenea şi cheie a vizualizării. Deci, un tabel protejat prin cheie este un tabel ale cărui chei se păstrează şi la nivel de vizualizare. Pentru ca un tabel să fie protejat prin cheie nu este necesar ca tabelul să aibă toate cheile selectate în vizualizare. Este suficient ca, atunci când cheia tabelului este selectată, aceasta să fie şi cheie a vizualizării.

Asupra unui join view pot fi aplicate instrucŃiunile INSERT, UPDATE sau DELETE, doar dacă sunt îndeplinite următoarele condiŃii:

• instrucŃiunea LMD afectează numai unul dintre tabelele de bază;

Page 241: CURS BD Combinat

76

• în cazul instrucŃiunii UPDATE, toate coloanele care pot fi reactualizate trebuie să corespundă coloanelor dintr-un tabel protejat prin cheie (în caz contrar, Oracle nu va putea identifica unic înregistrarea care trebuie reactualizată);

• în cazul instrucŃiunii DELETE, rândurile unei vizualizări pot fi şterse numai dacă există un tabel în join protejat prin cheie şi numai unul (în caz contrar, Oracle nu ar şti din care tabel să şteargă);

• în cazul instrucŃiunii INSERT, toate coloanele în care sunt inserate valori trebuie să provină dintr-un tabel protejat prin cheie.

ALL_UPDATABLE_COLUMNS, DBA_UPDATABLE_COLUMNS şi USER_UPDATABLE_COLUMNS sunt vizualizări din DD ce conŃin informaŃii referitoare la coloanele vizualizărilor existente, care pot fi reactualizate.

Exmplu: 1. Să se creeze un view ce conŃine câmpurile nume, prenume, job din

tabelul salariat. 2. Să se insereze, să se actualizeze şi să se şteargă o înregistrare în

acest view. Ce efect vor avea aceste acŃiuni asupra tabelului de bază?

CREATE VIEW vederea2

AS SELECT nume, prenume, job FROM salariat;

Nu se pot face inserari deoarece view-ul nu conŃine cheia primară!

INSERT INTO vederea2 VALUES ('Popescu','Valentin','grafician');

va genera eroarea:

ORA-01400: cannot insert NULL into ("SCOTT"."SALARIAT"."COD_SALARIAT")

Actualizarea job-ului salariatului având numele "Popescu":

UPDATE vederea2

SET job = 'programator' WHERE nume = 'Popescu'; SELECT nume, prenume, job FROM salariat;

Ştergerea înregistrării referitoare la salariatul având numele "Popescu":

DELETE vederea2 WHERE nume = 'Popescu';

Page 242: CURS BD Combinat

77

OperaŃiile care se realizează asupra view-ului se realizează şi în tabelul salariat. Pentru un caz mai general, când view-ul conŃine cheia externă a tabelului de bază, sunt permise modificări ale view-ului, dacă acestea nu afectează cheia externă.

Exemplu: Să se creeze un view care conŃine câmpurile nume, prenume, job

din tabelul salariat. Să se introducă în view doar persoanele care sunt graficieni.

CREATE VIEW vederea21 AS SELECT nume, prenume, job FROM salariat WHERE job = 'grafician' WITH CHECK OPTION;

Să se creeze o vizualizare care să conŃină cod_salariat, nume, prenume din tabelul salariat şi coloana tip din tabelul grafician. Apoi să se insereze, să se actualizeze şi să se şteargă o înregistrare din acest view (vizualizarea conŃine cheia primară cod_salariat din tabelele salariat şi grafician).

CREATE VIEW vederea4 AS SELECT s.cod_salariat,nume,prenume,tip FROM salariat s, grafician g WHERE s.cod_salariat=g.cod_salariat;

În cazul inserării unei înregistrări pentru care se specifică toate câmpurile:

INSERT INTO vederea4 VALUES (30,'Popescu','Valentin','artist plastic');

va apare următoarea eroare:

ORA-01776: cannot modify more than one base TABLE through a join view

Pot fi inserate date doar într-un tabel de bază (în oricare, dar în unul singur) prin intermediul view-ului, astfel:

INSERT INTO vederea4 (cod_salariat, nume) VALUES (30, 'Popescu');

Comanda pentru ştergerea unei înregistrări:

DELETE vederea4 WHERE cod_salariat = 3;

va genera următoarea eroare:

Page 243: CURS BD Combinat

78

ORA-01752: cannot delete from view without exactly one key-preserved TABLE.

Modificarea unei înregistrări se face prin secvenŃa care urmează. Toate actualizările care se fac în view se fac şi în tabelele de bază.

UPDATE vederea4 SET tip = 'designer' WHERE cod_salariat = 3;

Exemplu: Care dintre coloanele unei vizualizări sunt actualizabile?

SELECT column_name, updatable

FROM user_updatable_columns WHERE table_name = 'vederea4';

Exemplu:

1. Să se creeze un view (vederea3) care să conŃină, pentru fiecare categorie de salariat, salariile medii şi numărul de angajaŃi din tabelul salariat.

2. Să se insereze, să se actualizeze şi să se şteargă o înregistrare în view.

CREATE VIEW vederea3 (nr, job, salmed) AS SELECT COUNT(*), job, AVG(salariu) FROM salariat GROUP BY job;

Nu se pot face inserări, actualizări sau ştergeri într-un view ce conŃine funcŃii grup. După oricare din aceste operaŃii apare acelaşi mesaj:

ORA-01732: data manipulation operation not legal on this view

Exemplu: Să se creeze o vizualizare care să conŃină coloanele

cod_contractant, adresa, telefon din tabelul contractant şi coloanele nr_contract, tip_contract, data_incheiere din tabelul contract. Să se insereze o înregistrare în vizualizare.

CREATE VIEW vederea44 AS SELECT c.cod_contractant, adresa, telefon, co.nr_contract, tip_contract,

data_incheiere FROM contractant c, contract co WHERE c.cod_contractant=co.cod_contractant;

La inserarea unei înregistrări căreia i se specifică valorile tuturor câmpurilor din ambele tabele:

Page 244: CURS BD Combinat

79

INSERT INTO vederea44(cod_contractant, adresa, nr_contract, data_incheiere) VALUES (200, 'Str. Marmurei, 14', '6235',

TO_DATE('January 03,2002','Month dd,yyyy'));

se obŃine eroarea:

ORA-01779: cannot modify a column which maps to a non key-preserved TABLE

Cele două tabele de bază, contractant şi contract, se află într-o relaŃie “one-to-many”, iar view-ul creat conŃine cheile primare din ambele tabele.

Doar tabelul contract este protejat prin cheie şi, prin urmare, doar el poate fi modificat prin intermediul view-ului. Aceasta, deoarece ar putea exista mai multe înregistrări în view, cu aceeaşi valoare corespunzătoare câmpului cod_contractant (CP în contractant).

Exact aceeaşi eroare se obŃine dacă încercăm inserarea unei înregistrări în vederea44, specificând fie şi numai un câmp provenind din tabela contractant (indiferent dacă el conŃine sau nu CP).

Singura operaŃie de inserare permisă este aceea efectuată prin specificarea cheilor provenind doar din tabelul contract. Astfel, prin executarea comenzii:

INSERT INTO vederea44(nr_contract, tip_contract) VALUES ('6234', 0);

este creată o înregistrare, dar este modificat şi tabelul contract. Dacă la inserŃie nu se specifică cheia primară din contract:

INSERT INTO vederea44(tip_contract) VALUES (1);

ORA-01400: mandatory (NOT NULL) column is missing or NULL during insert

Cererea din definiŃia vizualizării poate fi restricŃionată prin clauzele WITH READ ONLY şi WITH CHECK OPTION. OpŃiunea WITH READ ONLY asigură că nu pot fi efectuate operaŃii LMD asupra vizualizării. Constrângerea WITH CHECK OPTION garantează faptul că va fi permisă, prin intermediul vizualizării, numai inserarea sau actualizarea de linii accesibile acesteia (care sunt selectate de cerere). Prin urmare, această opŃiune asigură constrângeri de integritate şi verificări asupra validităŃii datelor inserate sau actualizate.

OpŃiunea WITH CHECK OPTION nu poate funcŃiona dacă: • există o cerere imbricată în cadrul subcererii vizualizării sau în

vreuna dintre vizualizările de bază;

Page 245: CURS BD Combinat

80

• operaŃiile de inserare, ştergere şi modificare se fac prin intermediul declanşatorilor INSTEAD OF.

Cuvântul cheie CONSTRAINT permite numirea constrângerii WITH CHECK OPTION. În absenŃa acestei clauze, constrângerea va avea un nume implicit de forma SYS_Cn, unde n este un număr întreg unic.

Exemplu: Să se creeze o vizualizare ce conŃine artiştii de naŃionalitate

română, care au opere expuse în muzeu. DefiniŃia vizualizării nu va permite modificarea naŃionalităŃii unui artist sau inserarea unui artist având altă naŃionalitate decât cea română.

CREATE VIEW artist_roman AS SELECT * FROM artist WHERE nationalitate = 'romana' WITH CHECK OPTION CONSTRAINT artist_roman_ck;

UPDATE artist_roman SET nationalitate = 'engleza' WHERE cod_artist = 25;

Încercarea de actualizare a unei linii prin instrucŃiunea anterioară va genera eroarea „ORA-01402: view WITH CHECK OPTION where-clause violation“.

Exemplu: Să se creeze o vizualizare asupra tabelului galerie care să nu

permită efectuarea nici unei operaŃii LMD.

CREATE VIEW viz_galerie AS SELECT cod_galerie, nume_galerie FROM galerie WITH READ ONLY; DELETE FROM viz_galerie WHERE cod_galerie = 10;

Încercarea de ştergere a unei linii din vizualizarea viz_galerie determină apariŃia erorii „ORA-01752: cannot delete from view without exactly one key-preserved table“. Dacă se încearcă modificarea sau inserarea unei linii prin intermediul unei vizualizări asupra căreia a fost definită o constrângere WITH READ ONLY, server-ul Oracle generează eroarea „ORA-01733: virtual column not allowed here“.

Exemplu: Să se creeze o vizualizare care conŃine codul şi titlul operelor de

artă, codul şi numele artiştilor care le-au creat, precum şi codul galeriilor unde sunt expuse. Să se afle dacă este posibilă adăugarea unei noi înregistrări prin intermediul acestei vizualizări.

Page 246: CURS BD Combinat

81

CREATE VIEW opera_artist AS SELECT o.cod_opera, o.titlu, o.cod_galerie, a.cod_artist, a.nume FROM opera o, artist a WHERE o.cod_artist = a.cod_artist;

InstrucŃiunea următoare afişează numele coloanelor şi valorile YES/NO, după cum aceste coloane sunt, sau nu, modificabile.

SELECT COLUMN_NAME, UPDATABLE FROM USER_UPDATABLE_COLUMNS WHERE TABLE_NAME = 'OPERA_ARTIST';

Se va obŃine că doar primele trei coloane ale vizualizării sunt modificabile.

Indexul primar al coloanei cod_artist din tabelul artist nu este unic în vizualizarea opera_artist. Prin urmare, tabelul artist nu este key-preserved, iar coloanele sale nu sunt modificabile.

InstrucŃiunea următoare va genera eroarea „ORA-01776: cannot modify more than one base table through a join view“.

INSERT INTO opera_artist VALUES (200, 'Poeme de l''ame', 20, 147, 'Janmot');

În schimb, instrucŃiunea următoare va fi executată cu succes, întrucât adaugă o înregistrare în tabelul de bază opera, ale cărui coloane sunt modificabile.

INSERT INTO opera_artist (cod_opera, titlu, cod_galerie) VALUES (200, 'Poeme de l''ame', 20);

Constrângeri asupra vizualizărilor Începând cu versiunea Oracle9i pot fi specificate constrângeri

pentru vizualizări. Se pot defini constrângeri la nivel de vizualizare, respectiv la nivel de coloană sau atribut. Constrângerile asupra vizualizărilor constituie o submulŃime a constrângerilor specifice tabelelor.

Pot fi specificate explicit numai constrângerile UNIQUE, PRIMARY KEY şi FOREIGN KEY. Constrângerea de tip CHECK poate fi realizată prin precizarea clauzei WITH CHECK OPTION în comanda care defineşte vizualizarea.

Constrângerile asupra vizualizărilor pot fi definite numai în modul DISABLE NOVALIDATE. Aceste cuvinte cheie trebuie specificate la declararea constrângerii, nefiind permisă precizarea altor stări.

Exemplu:

Page 247: CURS BD Combinat

82

Să se creeze o vizualizare care conŃine codurile, numele şi adresele galeriilor. Se va impune unicitatea valorilor coloanei adresa şi constrângerea de cheie primară pentru coloana corespunzătoare codului galeriei. CREATE VIEW viz_galerie( cod_gal, nume, adresa UNIQUE DISABLE NOVALIDATE, CONSTRAINT cp_viz PRIMARY KEY (cod_gal) DISABLE NOVALIDATE) AS SELECT cod_galerie, nume_galerie, adresa FROM galerie;

Informa Ńii despre obiectele bazei de date

Pot fi obŃinute consultând DD(Dicționarul de Date). Dintre ele se remarcă:

• definiŃiile tuturor obiectelor din baza de date;

• spaŃiul alocat şi spaŃiul utilizat în prezent de obiectele schemei;

• constrângerile de integritate;

• numele utilizatorilor bazei;

• privilegiile şi rolurile acordate fiecărui rol;

• alte informaŃii generale despre baza de date.

Tabelul USER_CATALOG conŃine informaŃii despre tabelele şi vizualizările definite de un utilizator particular. Acest tabel poate fi referit şi prin sinonimul său public CAT.

Tabelul USER_OBJECTS conŃine informaŃii despre toate obiectele definite de utilizatorul curent. Tabelul are următoarea schemă relaŃională:

USER_OBJECTS (object_name, object_id, object_type, created, last_ddl_time, timestamp, status)

Vizualizările cele mai importante ale dicŃionarului datelor conŃin:

• descrierea tabelelor definite de utilizatori (USER_ALL_TABLES),

• informaŃii despre constrângerile definite de utilizator(USER_CONSTRAINTS),

• informaŃii despre legăturile bazei de date (USER_DB_LINKS),

• erorile curente ale obiectelor depozitate (USER_ERRORS),

• informaŃii despre indecşii creaŃi de utilizator (USER_INDEXES),

• informaŃii despre tabelele utilizatorului (USER_TABLES) etc.

Page 248: CURS BD Combinat

83

Vizualizările din dicŃionarul datelor referitoare la tabele conŃin:

• USER_TAB_COLUMNS|COLS – informaŃii despre coloanele tabelelor,

• USER_CONS_COLUMNS – informaŃii despre constrângeri la nivel coloană,

• USER_TAB_COMMENTS – informaŃii despre comentarii la nivel tabel,

• USER_COL_COMMENTS – informaŃii despre comentarii la nivel coloană,

• USER_TAB_PARTITIONS – informaŃii despre partiŃiile tabelelor.

Page 249: CURS BD Combinat

1

Limbajul de interogare a datelor(DQL) Limbajul SQL de interogare a datelor (DQL – Data Query

Language) include o singură comandă SELECT, care este cea mai folosită pentru a obŃine date din baza de date, astfel încât acestea să fie prelucrate de o anumită aplicaŃie sau să fie afişate. Rezultatul unei instrucŃiuni SELECT, numit şi set de rezultate, este returnat sub forma unui tabel. Deoarece SQL este un limbaj neprocedural, se specifică rezultatele pe care le doriŃi să le obŃineŃi, nu şi modul lor de obŃinere.

Instruc Ńiunea SELECT de bază

Cererea (interogarea) este realizată de instrucŃiunea SELECT. Cu ajutorul ei pot fi extrase submulŃimi de valori atât pe verticală (coloane), cât şi pe orizontală (linii) din unul sau mai multe tabele. Sintaxa comenzii este simplă, apropiată de limbajul natural.

SELECT [ALL | DISTINCT] { * | listă de atribute selectate | expr AS alias} FROM { [schema.]tabel [alias_tabel] } [WHERE condiŃie] [GROUP BY listă de expresii [HAVING condiŃie]] [ORDER BY { expresie | poziŃie | c_alias} [ASC | DESC]]

Forma elementară a instrucŃiunii SELECT conŃine două clauze: SELECT [DISTINCT] - Specifică lista de coloane care

urmează să fie returnate în setul de rezultate, separate prin virgule. Se poate folosi simbolul asterisc (*) în locul listei de coloane pentru a selecta toate coloanele dintr-un tabel sau dintr-o vizualizare. Cuvântul cheie DISTINCT poate fi adăugat după cuvântul cheie SELECT pentru a elimina rândurile duplicate din rezultatele interogării.

FROM - Specifică lista tabelelor sau vizualizărilor din care urmează să fie selectate datele. În locul numelor reale ale tabelelor sau vizualizărilor se poate folosi sinonime, adică pseudonime pentru tabele sau vizualizări definite în baza de date. PrezenŃa clauzelor SELECT şi FROM este obligatorie deoarece acestea specifică coloanele selectate, respectiv tabelele din care se vor extrage datele. Tabelele specificate în clauza FROM pot fi urmate de un alias, care va reprezenta numele folosit pentru referirea tabelului respectiv în cadrul instrucŃiunii.

Page 250: CURS BD Combinat

2

Eliminarea duplicatelor se poate realiza folosind clauza DISTINCT. Dacă nu se specifică parametrul DISTINCT, parametrul ALL este implicit şi are ca efect afişarea dublurilor.

Simbolul “*” permite selectarea tuturor atributelor din tabelele asupra cărora se execută cererea. Atributele sau expresiile din lista clauzei SELECT pot conŃine alias-uri, care vor reprezenta numele câmpurilor respective în cadrul tabelului furnizat ca rezultat de instrucŃiunea SELECT.

Clauza WHERE poate fi folosită pentru a impune anumite condiŃii liniilor din care se vor extrage atributele specificate în clauza SELECT.

Clauza GROUP BY grupează înregistrările după anumite câmpuri; în cazul prezenŃei acestei clauze, clauza HAVING poate impune restricŃii suplimentare asupra rezultatului final.

Ordonarea înregistrărilor se poate face cu ajutorul clauzei ORDER BY. Cu ajutorul parametrilor ASC şi DESC se poate specifica ordonarea crescătoare, respectiv descrescătoare a înregistrărilor. Pentru o secvenŃă crescătoare valorile null sunt afişate ultimele. Dacă nu se face nici o specificaŃie, atunci ordinea de returnare este la latitudinea server-ului.

În exemplul următor se selectează coloanele:

COD_GEN_FILM, MPAA_RATING_COD şi TITLU_FILM din tabelul FILM.

SELECT COD_GEN_FILM, COD_ RATING, TITLU_FILM FROM FILM; Pseudonime pentru numele coloanelor In setul de rezultate din interogări numele coloanelor din tabel

apare automat ca titlu de coloane în interogare. Dacă se doreşte un alt nume pentru coloanele unei interogări se folosesc pseudonime.

Pseudonimele (aliases) specificate devin numele coloanelor din setul de rezultate. Pseudonimele nu există decât după rularea instrucŃiunii SQL, aşa că nu pot fi folosite în alte părŃi ale instrucŃiunii SQL. Pseudonimul unei coloane este specificat prin plasarea cuvântului cheie ”AS" după numele coloanei în lista SELECT (cu cel puŃin un spaŃiu înainte şi după), urmat de numele dorit pentru a fi atribuit coloanei în setul de rezultate.

SELECT COD_GEN_FILM AS GEN, MPAA_RATING_COD AS RATING, TITLU_FILM AS FILM FROM FILM;

Page 251: CURS BD Combinat

3

Dacă în interiorul alias-ului apare un spaŃiu liber sau caractere speciale, atunci alias-ul trebuie scris între ghilimele.

SELECT dateres–dataim ”numar zile” FROM imprumuta; Sortarea rezultatelor Rezultatele interogărilor sunt deseori mult mai utile dacă se

specifică pentru rândurile returnate o ordine care să aibă o semnificaŃie pentru persoana sau aplicaŃia care foloseşte informaŃiile. În SQL, acest lucru este făcut prin adăugarea în instrucŃiunea SELECT a clauzei ORDER BY, cu o listă de una sau mai multe coloane care vor fi folosite pentru sortarea rândurilor în ordine ascendentă sau descendentă, în conformitate cu valorile datelor din coloane. De asemenea, se Ńine seama de următoarele aspecte:

Ordinea prestabilită pentru fiecare coloană este ascendentă, dar se poate adăuga cuvântul cheie ASC după numele coloanei pentru obŃinerea unei ordonări ascendente sau cuvântul cheie DESC pentru obŃinerea unei ordonări descendente.

Nu este obligatoriu ca numele coloanelor din lista ORDER BY să fie incluse şi în lista de rezultate (adică în lista SELECT).

Motorul SQL din SGBD va găsi cea mai bună cale de ordonare a coloanelor. În general, sortarea datelor este un proces costisitor din punct de vedere al resurselor de calcul, aşa că majoritatea sistemelor SGBD folosesc un index pentru accesul la rânduri în ordinea dorită, presupunând că există, şi fac o sortare propriu-zisă numai ca ultimă soluŃie.

Se poate folosi pseudonimele coloanelor în clauza ORDER BY, dar dacă se face acest lucru se forŃează motorul SQL să sorteze rezultatele abia după rularea interogării.

În locul coloanelor, se poate specifica în lista de ordonare poziŃia relativă a coloanelor. De exemplu, clauza ORDER BY 1,2 va sorta rezultatele în ordine ascendentă după primele două coloane din setul de rezultate. Numărul specificat nu are nici o legătură cu poziŃia coloanei în tabelul sau vizualizarea sursă. Această opŃiune nu este agreată în programarea SQL formală, deoarece dacă ulterior cineva modifică interogarea, este posibil să amestece coloanele din lista SELECT, fără să-şi dea seama că astfel schimbă şi coloanele folosite pentru sortarea rezultatelor.

Exemplu: SELECT MPAA_RATING_COD AS RATING, COD_GEN_FILM AS GEN, TITLU_FILM AS FILM

Page 252: CURS BD Combinat

4

FROM FILM ORDER BY MPAA_RATING_COD, COD_GEN_FILM ;

Dacă dorim să ordonăm acum crescător după rating şi descrescător

după gen, atunci instrucŃiunea de mai sus modificată va fi

SELECT MPAA_RATING_COD AS RATING, COD_GEN_FILM AS GEN, TITLU_FILM AS FILM FROM FILM ORDER BY MPAA_RATING_COD ASC, COD_GEN_FILM DESC;

ObservaŃie: Oracle va afişa titlu de coloana la dimensiunea maximă a valorilor

din coloana(de ex. dacă în coloana RATING val cea mai mare este de 5 caractere, interogarea va afişa RATIN). În noua versiune de SQL produs de Oracle, iSQL*Plus, nu mai prescurtează.

Exemplu : SELECT titlu, autor, pret, coded as domeniu from carte order by coded, autor; SELECT titlu, autor, pret, coded as domeniu from carte order by coded desc, pret; Se observa ca domeniu este trunchiat la 5 caractere, DOMEN

Page 253: CURS BD Combinat

5

Utilizarea clauzei WHERE pentru filtrarea rezultatelor SQL foloseşte clauza WHERE pentru a filtra rândurile ce urmează

să fie afişate. O interogare fără o clauză WHERE returnează un set de rezultate care conŃine toate rândurile din tabelele sau vizualizările referite în clauza FROM. Dacă este inclusă o clauză WHERE, sunt folosite regulile algebrei booleene, evaluând clauza WHERE pentru fiecare rând de date. În rezultatele interogării sunt afişate numai rândurile pentru care clauza WHERE este evaluată la valoarea logică „adevărat".

Operatorii utilizați în clauza WHERE se impart în patru categorii:

- Operatori de comparare - Operatori conjuctivi - Operatori logici - Operatori aritmetici

Operatori de comparare Operatorii de comparare sunt folosiŃi în clauza WHERE pentru

compararea a două valori, având ca rezultat o valoare logică de „adevărat" sau „fals". Cele două valori comparare pot fi constante furnizate în clauza WHERE, valori ale unor coloane din baza de date sau combinaŃii ale celor două. Operatorii de comparare care pot fi folosiŃi în clauza WHERE sunt prezentaŃi în tabelul următor:

Page 254: CURS BD Combinat

6

Operator Descriere = Egal cu < Mai mic decât <= Mai mic sau egal > Mai mare decât >= Mai mare sau egal != Diferit de <> Diferit de (standard ANSI)

Exemple din schema FILM: • Să se afişeze toate filmele pentru care RATING are valoarea PG-13. SELECT MPAA_RATING_COD AS RATING, TITLU_FILM FROM FILM WHERE MPAA_RATING_COD = 'PG-13' ORDER BY TITLU_FILM; • Să se afişeze filmele pentru care COD_RATING are altă valoare decât

PG-13. SELECT COD_RATING AS RATING, TITLU_FILM FROM FILM WHERE COD_RATING <> 'PG-13' ORDER BY TITLU_FILM; • Să se afişeze toate filmele cu preŃul de vânzare cu amănuntul pentru

formatul DVD(DVD Retail Price) mai mare de 25.00, în ordinea crescătoare a preŃurilor.

SELECT PRET_VANZARE_DVD, TITLU_FILM FROM FILM

WHERE PRET_VANZARE_DVD >= 25.00 ORDER BY PRET_VANZARE_DVD DESC;

Exemple pe schema BIBLIOTECA

• Să se obtină codul cărtii care are data restituirii >.. SELECT codel FROM imprumuta WHERE datares >= ’05–oct–09’;

Page 255: CURS BD Combinat

7

• Să se obŃină titlurile şi numărul de exemplare ale cărŃilor care au

nrex>100 ; SELECT titlu, nrex FROM carte WHERE nrex>100;

Operatori conjunctivi Uneori sunt necesare condiŃii multiple pentru a îngusta setul de

rezultate al unei interogări. Atunci când sunt folosite mai multe condiŃii, ele trebuie să fie combinate din punct de vedere logic în clauza WHERE, iar aceasta este sarcina operatorilor conjunctivi. Aceşti operatori sunt:

• AND (ŞI) - Clauza WHERE este evaluată ca „adevărată" dacă toate condiŃiile conectate cu operatorul AND sunt adevărate.

• OR (SAU) - Clauza WHERE este evaluată ca „adevărată" dacă oricare din condiŃiile conectate cu operatorul OR este adevărată. Operatorul AND are prioritate mai mare şi, ca urmare, este evaluat

înaintea operatorilor OR. Exemple de folosire a operatorilor conjunctivi:

• Să se afişeze toate filmele pentru care categoria RATING este PG-13 şi preŃul de vânzare cu amănuntul pentru formatul DVD este 19.99 sau mai mic, în ordinea crescătoare a preŃurilor.

SELECT COD_RATING AS RATING, PRET_VANZARE_DVD AS PRET, TITLU_FILM FROM FILM WHERE COD_RATING = 'PG-13' AND PRET_VANZARE_DVD <= 20.00 ORDER BY PRET_VANZARE_DVD;

Page 256: CURS BD Combinat

8

• Să se afişeze toate filmele pentru care categoria RATING este PG-13 sau preŃul de vânzare cu amănuntul pentru formatul DVD este 19.99 sau mai mic, în ordinea crescătoare a preŃurilor.

SELECT COD_RATING AS RATING,

PRET_VANZARE_DVD AS PRET, TITLU_FILM FROM FILM WHERE COD_RATING = 'PG-13' OR PRET_VANZARE_DVD <= 20 ORDER BY PRET_VANZARE_DVD;

• Afi şaŃi toate filmele pentru care categoria RATING este PG-13 şi sunt din genul dramă sau acŃiune/aventură.

SELECT COD_RATING AS RATING,

PRET_VANZARE_DVD AS PRET, TITLU_FILM FROM FILM WHERE COD_GEN_FILM= 'ActAd' OR COD_GEN_FILM = 'Drama' AND COD_RATING = 'PG-13' ORDER BY COD_GEN_FILM, COD_RATING;

• Să se adauge parantezele necesare, astfel încât să obŃinem filmele cu categoria PG-13 şi genul acŃiune/aventură sau dramă.

SELECT COD_GEN_FILM AS GEN, COD_RATING AS RATING, TITLU_FILM FROM FILM

WHERE (COD_GEN_FILM = 'ActAd' OR COD_GEM_FILM = 'Drama') AND COD_RATING='PG-13'

ORDER BY COND_GEN_FILM, COD_RATING;

Operatori logici Operatorii logici folosesc cuvinte cheie în locul simbolurilor la

formarea expresiilor de comparare. La oricare dintre aceşti operatori poate fi adăugat cuvântul cheie NOT, pentru a inversa valoarea logică a comparaŃiei.

Page 257: CURS BD Combinat

9

IS NULL Operatorul IS NULL este folosit pentru a determina dacă o valoare

este nulă. Exemple:

• Să se găsească toate conturile de clienŃi active, adică toate conturile pentru care coloana DATA–TERMINATA conŃine o valoare nulă:

SELECT ID_CONT_CLIENT FROM CONT_CLIENT WHERE DATA_INCHEIERE IS NULL;

• Să se găsească toate conturile inactive, adică toate conturile pentru

care coloana DATA–TERMINAT conŃine o altă valoare decât NULL:

SELECT ID_CONT_CLIENT FROM CONT_CLIENT

WHERE DATA_INCHEIERE IS NOT NULL;

BETWEEN Operatorul BETWEEN este folosit pentru a determina dacă o

valoare se încadrează într-un interval special. Intervalul este specificat folosind o valoare minimă şi o valoare maximă, fiind un interval inclusiv, ceea ce înseamnă că include şi valori specificate.

Exemple: • Să se afişeze toate filmele cu preŃul de vânzare cu amănuntul pentru

formatul DVD între 14.99 şi 19.99, ordonate crescător după preŃ. SELECT TITLU_FILM, PRET_VANZARE_DVD FORM FILM WHERE PRER_VANZARE_DVD BETWEEN 14.99 AND 19.99 ORDER BY PRER_VANZARE_DVD; • Să se afişeze toate filmele pentru care preŃul de vânzare cu amănuntul

pentru formatul DVD nu este în intervalul 14.99-19.99, ordonate crescător după preŃ.

SELECT TITLU_FILM, PRET_VANZARE_DVD FORM FILM WHERE PRET_VANZARE_DVD NOT BETWEEN 14.99 AND 19.99 ORDER BY PRET_VANZARE_DVD; • Să se afişeze toate conturile de clienŃi în luna ianuarie 2009. SELECT ID_CONT_CLIENT, DATA_INSCRIERE FROM CONT_CLIENT WHERE DATA_INSCRIERE BETWEEN ”2009/01/01” AND „2009/01/31”;

Page 258: CURS BD Combinat

10

Tabelul DUAL se află în schema SYS şi poate fi accesat de către toŃi utilizatorii. Tabelul este util atunci când se afişează valoarea unei constante, pseudocoloane sau expresii care nu este construită pe baza datelor vreunui tabel. În general, tabelul DUAL este utilizat pentru a completa sintaxa instrucŃiunii SELECT, întrucât clauzele SELECT şi FROM sunt obligatorii.

Să se afişeze data şi ora curentă.

SELECT TO_CHAR(SYSDATE,’DD/MM/YY HH24:MI:SS’) FROM DUAL;

LIKE Operatorul LIKE este folosit pentru a compara o valoare de tip

caracter cu un tipar*(pattern), returnând valoarea logică “adevărat” dacă valoarea de tip caracter se încadrează în tipar şi “fals" în caz contrar. Pentru definirea tiparului pot fi folosite două caractere de înlocuire:

• Liniu Ńa de subliniere (_) - Caracterul liniuŃă de subliniere poate fi folosit drept caracter de înlocuire poziŃional, ceea ce înseamnă că se potriveşte cu orice caracter aflat pe poziŃia respectivă în şirul de caractere evaluat.

• Procent (%) - Simbolul procent (%) poate fi folosit drept caracter de înlocuire nepoziŃional, ceea ce înseamnă că se potriveşte cu orice număr de caractere, indiferent de lungime, reprezentând orice secvenŃă de zero sau mai multe caractere, şi „_“, reprezentând un singur caracter.

Exemple de tipare: Tipar Interpretare Now% Se potriveşte cu orice şir de caractere care incepe cu

„Now". N_w Se potriveşte cu orice şir de caractere format din

exact trei caractere, care începe cu „N" şi se termină cu „w".

Page 259: CURS BD Combinat

11

%N-w% Se potriveşte cu orice şir de caractere care conŃine litera „N", urmată de orice alt caracter, urmat de litera „w" (1a începutul, la sfârşitul sau undeva în mijlocul şirului de caractere)

%Now% Se potriveşte cu orice şir de caractere care conŃine „Now" (1a inceput, la sfârşit sau în mijloc).

%Now Se potriveşte cu orice şir de caractere care se termină cu „Now".

Datele din bazele de date relaŃionale fac întotdeauna diferenŃierea

literelor mari de cele mici. O literă mica din date nu se potriveşte cu o literă mare din tiparul unei clauze LIKE, şi invers.

Exemple de utilizare a operatorului LIKE: • Să se afişeze toate titlurile de filme care conŃin şirul de caractere

„on": SELECT TITLU_FILM FROM FILM WHERE TITLU_FILM LIKE '%on%';

• Dacă se intenŃionează să se găsească titlurile care conŃin cuvântul „on", nu literele „on" din alte cuvinte, ar fi trebuit să includă în tipar şi spatiile necesare, ca în exemplul următor:

Exemple

Să se afişeze cartile ale căror titlu conŃine cuvântul „Baza“, sau pentru care al treilea caracter din autor este „p“.

SELECT titlu, autor FROM carte WHERE titlu LIKE '%Baza%' OR autor LIKE '__p%';

Page 260: CURS BD Combinat

12

IN Operatorul IN este folosit pentru a determina dacă o valoare face

parte dintr-o listă de valori. Lista poate fi specificată ca valori literale, folosind o listă de valori separate prin virgule şi încadrate între paranteze, sau poate fi selectată din baza de date folosind o subselecŃie (o subinterogare), care este o interogare în cadrul unei alte interogări.

Exemple de utilizare a operatorului IN:

• Să se afişeze toate filmele pentru care COD_GEN_FILM este Drama, Forgn.

SELECT COD_GEN_FILM AS GEN, TITLU_FILM

FROM FILM WHERE COD_GEN_FILM IN ('Drama', 'Forgn') ORDER BY COD_GEN_FILM, TITLU_FILM;

• Să se afişeze toate filmele pentru care descrierea genului conŃine cuvântul „and". AveŃi nevoie de o subinterogare prin care să găsiŃi toate valorile COD_GEN_FILM care conŃin cuvântul „and" în descriere. Operatorul IN este apoi folosit pentru a găsi filmele care au unul dintre codurile selectate de subinterogare.

SELECT COD_GEN_FILM AS GEN, TITLU_FILM FROM FILM WHERE COD_GEN_FILM IN

(SELECT COD_GEN_FILM FROM GEN_FILM WHERE GEN_FILM DESCRIPTION LIKE '% and %') ORDER BY COD_GEN_FILM AS GEN, TITLU_FILM;

• Să se afişeze toate cartile din domeniile ’I’si ’M’. SELECT TITLU, AUTOR FROM CARTE WHERE CODED IN(’I’,’M’);

Page 261: CURS BD Combinat

13

EXISTS Operatorul EXISTS este folosit pentru a detemina dacă o

subinterogare conŃine înregistrări. Dacă în setul de rezultate al subinterogării nu există nici un rând, operatorul returnează valoarea „false”; dacă setul de rezultate conŃine cel puŃin un rând, valoarea devine „adevărat”.

Exemple de utilizare a operatorului EXIST:

• Proprietarul magazinului a auzit că filmul The Last Samurai se închiriază bine atât în format DVD, cât şi-n format VHS şi vrea să se asigure că în inventarul magazinului există o copie VHS. Tabelul FILM_COPIAT conŃine un rând pentru fiecare copie a unui film din inventarul magazinului, aşa că puteŃi folosi o subinterogare pentru a afla dacă există copii VHS ale filmului în inventar. De cele mai multe ori, operatorul EXISTS este folosit in conjuncŃie cu o formă mai complexă de subinterogare, numită subinterogare corelat. (correlated subquery),în care valorile datelor din interogarea externă (ID_FILM, în acest caz) sunt comparate cu rândurile din interogarea intenă.

SELECT ID_FILM, TITLU_FILM FROM FILM M WHERE TITLU_FILM = 'The Last Samurai'

AND EXISTS (SELECT ID_FILM FROM FILM_COPIAT C WHERE M. ID_FILM = C. ID_FILM);

• Dacă inversaŃi logica, folosind operatorul NOT EXISTS, puteŃi afişa titlul filmului numai dacă nu există o copie VHS în inventar. SELECT ID_FILM, TITLU_FILM FROM FILM M WHERE TITLU_FILM = 'The Last Samurai'

AND NOT EXISTS (SELECT ID_FILM FROM FILM_COPIAT C WHERE M. ID_FILM = C. ID_FILM);

Page 262: CURS BD Combinat

14

Operatori aritmetici În SQL, operatorii aritmetici sunt folosiŃi pentru efectuarea

calculelor matematice – la fel ca şi în formulele dintr-o foaie de calcul tabelar sau într-un limbaj de programare, precum Java sau C. Cei patru operatori aritmetici din SQL sunt:

Ca şi în cazul operatorilor conjunctivi, dacă se amestecă operatorii aritmetici în aceeaşi instrucŃiune SQL fără a folosi paranteze, ordinea în care sunt evaluate operaŃiile este determinată de prioritatea predefinită. Din fericire, prioritatea operatorilor din SQL este cea pe care o folosim în operaŃiile matematice obişnuite.

Exemple de utilizare a operatorilor aritmetici: • Cât v-ar costa să cumpăraŃi copiile VHS şi DVD ale filmului The Last

Samurai? SELECT PRET_VANZARE_VHS + PRET_VANZARE _DVD

AS COST FROM FILM WHERE TITLU_FILM = 'The Last Samurai'; • Cât v-ar costa aceeaşi achiziŃie dacă aŃi avea un bon valoric de 8 ron? SELECT (PRET_VANZARE _VHS + PRET_VANZARE _DVD) - 8

AS COST FROM FILM WHERE TITLU_FILM = 'The Last Samurai'; • Dacă taxele sunt de 8.25% (0.0825), cât reprezintă taxele de vânzare

din costul achiziŃiei anterioare? SELECT (PRET_VANZARE _VHS+ PRET_VANZARE _DVD) *

0.0825 AS TAX FROM FILM WHERE TITLU_FILM = 'The Last Samurai'; • Care este costul mediu pentru o copie a filmului The Last Samurai? SELECT (PRET_VANZARE_VHS+PRET_VANZARE _DVD) / 2

AS AVG_COST FROM FILM WHERE TITLU_FILM = 'The Last Samurai'

Operator Descriere + Adunare - Scădere * ÎnmulŃire / ÎmpărŃire

Page 263: CURS BD Combinat

15

FuncŃii SQL elementare O funcŃie este un tip special de program, care returnează o singură

valoare de fiecare data când este apelată. Termenul provine de la conceptul matematic al unei funcŃii. În SQL, funcŃiile necesită întotdeauna specificarea unei expresii, care deseori include numele unei coloane. Cel mai des, funcŃiile sunt folosite în lista de coloane a unei instrucŃiuni SELECT, sunt apelate pentru fiecare rând prelucrat de interogare şi, ca urmare, returnează o singură valoare pentru fiecare rând din setul de rezultate. Uneori este folosit termenul funcŃie de coloană, pentru a indica faptul că o funcŃie este aplicată unei coloane dintr-un tabel sau o vizualizare. Un număr de funcŃii sunt furnizate de producătorul DBMS şi se pot scrie propriile funcŃii, folosind un limbaj special livrat împreună cu sistemul DBMS, cum ar fi PL/SQL pentru Oracle sau Transact SQL pentru Microsoft SQL Server şi Sybase Adaptive Server.

AtenŃie la folosirea funcŃiilor SQL în condiŃiile WHERE. În cele mai multe situaŃii, pentru o coloană căreia îi este aplicată o funcŃie nu poate fi folosită indexarea. Ca urmare, în cazul tabelelor mari, utilizarea funcŃiilor în condiŃiile WHERE poate duce la probleme de performanŃă cu adevărat memorabile.

FuncŃiile pot fi clasificate în multe moduri, dar majoritatea specialiştilor le împart după ceea ce fac.

FuncŃii pentru caractere FuncŃiile pentru caractere sunt numite astfel deoarece manipulează

date de tip text.

Concatenarea şirurilor de caractere FuncŃia de concatenare a şirurilor de caractere reuneşte mai multe

şiruri de caractere pentru a forma o singură valoare în rezultatele interogării. FuncŃia standard de concatenare a şirurilor de caractere din SQL este apelată cu două bare verticale (||), dar există şi excepŃii, cum ar fi Microsoft SQL Server, care foloseşte semnul plus (+) pentru concatenarea şirurilor de caractere.

Exemple de concatenare a şirurilor de caractere: • Magazinul de produse video vrea să trimită fiecărui client o

scrisoare care începe cu formula "Client", plus prenumele şi numele persoanei. Numele sunt stocate în tabelul PERSON. SoluŃia acestei cerintŃe în Oracle:

SELECT 'Client' || NUME_PERSOANA|| ' ' || NUME_FAMILIE_PERSOANA AS SALUT_CLIENT FROM PERSOANA;

Page 264: CURS BD Combinat

16

Aceeaşi soluŃie, modificată pentru a funcŃiona în Microsoft SQL Server :

SELECT ‚Client' + NUME_PERSOANA + ' ' + NUME_FAMILIE_PERSOANA AS SALUT_CLIENT

FROM PERSOANA; <nume angajat> castiga <salariu> lunar, dar doreste <salariu de 3

ori mai mare> SELECT last_name||'castiga'||salary||'lunar, dar doreste'||salary*3 "salariul ideal" FROM employees;

UPPER FuncŃia UPPER este deseori folosită în condiŃiile WHERE.

FuncŃia UPPER transformă literele dintr-un şir de caractere în litere mari. Numerele şi caracterele speciale sunt lăsate ca stare.

Exemple: • Să se afişeze comediile (COD_GEN_FILM = 'Comdy') scriind

titlurile cu majuscule. SELECT UPPER(TITLU_FILM) AS TITLU_FILM

FROM FILM WHERE COD_GEN_FILM = 'Comdy';

• Să presupunem că nu vă amintiŃi dacă valorile COD_GEN_FILM au fost stocate cu litere mari, litere mici sau combinaŃii ale acestora. Dacă în condiŃia WHERE transformaŃi valorile în litere mari, puteŃi obŃine rezultatele corecte indiferent de modul de stocare. SELECT UPPER(TITLU_FILM) AS TITLU_FILM FROM FILM WHERE UPPER(COD_GEN_FILM) = 'COMDY';

LOWER FuncŃia LOWER este inversa funcŃiei UPPER — transformă

literele dintr-un * de caractere în litere mici. Exemple de utilizare a funcŃiei LOWER:

• Să se afişeze comediile (GEN_COD_FILM = 'Comedy') scriind titlurile cu minuscule. SELECT LOWER(TITLU_FILM) AS TITLU_FILM FROM FILM WHERE GEN_COD_FILM = 'Comedy';

Page 265: CURS BD Combinat

17

• Se poate folosi funcŃia LOWER într-o clauză WHERE, atunci când nu ştiti sigur ce tip de litere obŃine textul pe care vreŃi să-1 comparaŃi. Afi şaŃi toate filmele care au în titlu cuvântul „of ", indiferent dacă este scris cu litere mari sau mici. SELECT TITLU_FILM FROM FILM WHERE LOWER(TITLU_FILM) LIKE ' % of %' OR LOWER(TITLU_FILM) LIKE 'of % ' OR LOWER(TITLU_FILM) LIKE ' % of ';

SUBSTR FuncŃia SUBSTR apare în majoritatea implementărilor SQL, dar

uneori are un nume puŃin diferit. De exemplu, funcŃia se numeşte SUBSTRING în Microsoft SQL Server, Sybase Adaptive Server şi MySQL, dar SUBSTR în Oracle şi D132. FuncŃia returnează o porŃiune a şirului de caractere, în funcŃie de parametrii furnizaŃi, care specifică numele coloanei, poziŃia de început a subşirului în datele coloanei şi lungimea subşirului returnat (numărul de caractere). Deşi este o utilizare mai puŃin obişnuită, funcŃia SUBSTR acceptă şi un şir de caractere literal în locul numelui unei coloane. Iată forma generală a funcŃiei, urmată de un exemplu:

SUBSTR (numele coloanei, poziŃia de început, lungimea subşirului • În tabelul PERSON, unele persoane au al doilea nume în întregime,

alŃii au numai initiale. Afişati numele complet al persoanelor al căror nume de familie începe cu litera „B", sub forma unui singur şir de caractere care conŃine prenumele, iniŃiala şi numele de familie. SELECT NUME_PERSOANA || ' ' || SUBSTR(PRENUME_PERSOANA, 1, 1) || ' . ' || NUME_FAMILIE_PERSOANA AS NUME_INTREG FROM PERSOANA WHERE SUBSTR(NUME_FAMILIE_PERSOANA, 1, 1)='B' ObservaŃi folosirea funcŃiei SUBSTR în clauza WHERE pentru a

elimina din rezultate persoanele al căror nume de familie nu începe cu litera „B". Ar trebui să vă puteŃi deja gândi la alte moduri de a face acest lucru, prin folosirea operatorului LIKE.

Page 266: CURS BD Combinat

18

LENGTH FuncŃia LENGTH returnează lungimea unui şir de caractere.

Microsoft SQL Server şi Sybase Adaptive Server folosesc numele LEN pentru versiunea proprie a acestei funcŃii.

Exemple: • Să se afişeze lungimea titlului pentru filmul a cărui valoare

ID_FILM este 1. Presupunem că folosiŃi o bază de date oracle, DB2 sau MySQL.

• SELECT TITLU_FILM, LENGTH (TITLU_FILM) AS LENGTH FROM FILM WHERE ID_FILM = 1;

• SELECT TITLU_FILM, LENGTH (TITLU_FILM) AS LENGTH FROM FILM WHERE LENGTH (TITLU_FILM) < 10; FunŃii matematice FuncŃiile matematice manipulează valori numerice, în conformitate

cu regulile matematicii.

ROUND FuncŃia ROUND rotunjeşte o valoare la un număr specificat

de zecimale. Valoarea numerică este furnizată prin primul parametru, iar numărul de zecimale prin cel de-al doilea. În continuare este prezentat formatul general al funcŃiei ROUND.

ROUND (expresie numerică, număr de poziŃii zecimale) • Care este costul mediu al unei copii a filmului The Last Samurai,

rotunjit la două zecimale? SELECT ROUND((PRET_VANZARE_VHS + PRET_VANZARE _DVD) / 2, 2) AS AVG_COST FROM FILM WHERE TITLU_FILM = 'The Last Samurai';

Alte funcŃii matematice Tabelul care urmează prezintă funcŃiile matematice cel mai

des întâlnite. Pentru toate, sintaxa generală este aceeaşi: NUME_FUNCTIE (expresie)

Page 267: CURS BD Combinat

19

FuncŃie Descriere ABS Valoarea absolută a unui număr dat COS Cosinusul trigonometric al unui unghi specificat în radiani EXP Valoarea exponenŃială a unui număr dat POWER Ridică un număr la o putere (numărul şi puterea sunt fumizate

ca parametri) SIN Sinusul trigonometric al unui unghi specificat în radiani TAN Tangenta trigonometrică a unui unghi specificat în radiani

FuncŃii de conversie FuncŃiile de conversie transformă date dintr-un tip de date în altul.

CAST FuncŃia CAST transformă date dintr-un tip de date în altul. Iată

sintaxa generală a funcŃiei CAST, urmată de un exemplu: CAST (expresie AS tip de date)

• Afi şati preŃul pentru formatul DVD al filmului The Last Samurai, cu un simbol dolar în faŃa sumei. Valoarea numerică trebuie să fie convertită într-un şir de caractere pentru a putea fi concatenată cu o valoare literală conŃinând simbolul dolar. SELECT '$' || CAST(PRET_VANZARE _DVD AS VARCHAR(6)) AS PRET FROM FILM WHERE TITLU_FILM = 'The Last Samurai'; FuncŃii de agregare şi gruparea rândurilor O funcŃie de agregare (aggregate functions) este o funcŃie care

combină mai multe rânduri de date într-un singur rând. Tabelul următor prezintă funcŃiile de agregare acceptate în majoritatea implementărilor SQL:

FuncŃie Descriere AVG Calculează valoarea medie pentru o coloană sau o

expresie. COUNT Numără valorile dintr-o coloană. MAX Găseşte valoarea maxină dintr-o coloană. MIN Găseşte valoarea minimă dintr-o coloană. SUM Însumează valorile dintr-o coloană. Exemple:

• Care este preŃul mediu al unui DVD?

Page 268: CURS BD Combinat

20

SELECT ROUND(AVG(PRET_VANZARE _DVD),2) AS AVG_PRET FROM FILM;

• Câte filme există în tabelul FILM? SELECT COUNT(*) AS NUM_FILM FROM FILM;

• Câte genuri diferite de filme sunt reprezentate în tabelul FILM? SELECT COUNT(DISTINCT COD_GEN_FILM) AS NUM_GEN FROM FILM;

• Care sunt lungimea minimă şi maximă a titlurilor filmelor? SELECT MIN(LENGTH(TITLU_FILM)) AS MIN_LENGTH, MAX(LENGTH(TITLU_FILM)) AS MAX_LENGTH FROM FILM;

Clauza GROUP BY GROUP BY cere sistemului DBMS să grupeze rândurile selectate

de interogare pe baza valorilor din una sau mai multe coloane şi să aplice funcŃia (sau funcŃiile) de agregare fiecărui grup, returnând un rând pentru fiecare grup din setul de rezultate.

Sistemul DBMS va ordona rândurile selectate de interogare după coloanele din clauza GROUP BY, aşa că grupurile vor fi returnate în ordine ascendentă, exceptând cazul în care se adăugă o clauză ORDER BY care specifică un alt mod de ordonare.

Iată un exemplu: • Afi şati fiecare cod de gen, împreună cu numărul de filme asociate

fiecărui cod. SELECT COD_GEN_FILM AS GEN, COUNT(*) AS COUNT FROM FILM GROUP BY COD_GEN_FILM; Ce se întâmplă dacă scoateŃi clauza GROUP BY din această

interogare? Sistemul DBMS retumează un mesaj de eroare şi, din nefericire, mesajul de eroare este deseori destul de criptic. Functia COUNT(*) este o functie de agregare şi, în absenta clauzei GROUP BY, retumează un singur rând de date.

Exemplele care urmează arată modul general de constituire a subansamblelor virtuale folosind clauza GROUP BY. Fiecare expresie care apare în SELECT trebuie să aibă aceeaşi valoare pentru toate liniile care aparŃin aceleiaşi partiŃii. Numele coloanelor din GROUP BY nu trebuie să figureze obligatoriu în lista de la SELECT.

Clauza WHERE are prioritate fata de GROUP BY. Nu se poate utiliza alias de coloana in clauza GROUP BY.

Page 269: CURS BD Combinat

21

Pentru a returna informatie corespunxatoare fiecarui grup, pot fi utilizate functiile agregat. Acestea pot aparea in clauzele SELECT, ORDER BY si HAVING. Se poate utiliza functie grup in clauza WHERE? Este corect …WHERE AVG(sal) > 200? NU!

Cand se utilizeaza GROUP BY, server-ul sorteaza implicit multimea rezultata in ordinea crescatoare a valorilor coloanelor dupa care se realizeaza gruparea.

Grupurile sunt formate si functiile grup sunt calculate, inainte ca clauza HAVING sa fie aplicata grupurilor.

Exemplu: Să se obŃină numărul de câte ori a fost împrumutată fiecare carte.

SELECT codel, COUNT(*) FROM imprumuta GROUP BY codel;

Exemplu: Pentru fiecare domeniu de carte să se obŃină numărul cărŃilor din

domeniu, media preŃurilor şi numărul total de exemplare.

SELECT coded,COUNT(*), AVG(pret),SUM(nrex) FROM carte GROUP BY coded;

Dacă în comanda SELECT apar atribute coloană (nu funcŃii grup) şi se utilizează clauza GROUP BY atunci aceste coloane trebuie obligatoriu să apară în clauza GROUP BY.

Exemplu: Să se obŃină pentru fiecare autor, media preŃurilor cărŃilor din

bibliotecă. SELECT autor, AVG(pret) FROM carte GROUP BY autor;

Exemplu: Pentru departamentele în care salariul maxim depăşeşte 5000$ să

se obŃină codul acestor departamente şi salariul maxim pe departament.

SELECT deptno, MAX(sal)

FROM emp GROUP BY deptno HAVING MAX(sal)>5000;

Page 270: CURS BD Combinat

22

Exemplu:

SELECT MAX(AVG(pret))

FROM carte GROUP BY autor;

Exemplu: Să se afişeze numele şi salariul celor mai prost plătiŃi angajaŃi

din fiecare departament.

SELECT ename, sal FROM emp WHERE (deptno, sal) IN

(SELECT deptno, MIN(sal) FROM emp GROUP BY deptno);

Exemplu: Să se obŃină pentru fiecare carte, codul său şi numărul de

exemplare care nu au fost încă restituite.

SELECT codel, COUNT(*)

FROM imprumuta

WHERE dataef IS NULL GROUP BY codel;

Exemplu: Să se obŃină numărul cărŃilor împrumutate cel puŃin o dată.

SELECT COUNT(DISTINCT codel)

FROM imprumuta;

Exemplu: Să se afişeze numărul cărŃilor împrumutate cel puŃin de două ori

(pentru fiecare carte împrumutată mai mult decât o dată să se obŃină numărul de câte ori a fost împrumutată).

SELECT COUNT(COUNT(codel))

FROM imprumuta GROUP BY codel HAVING COUNT(*)>1;

Page 271: CURS BD Combinat

23

În cererea anterioară COUNT(codel), reprezintă numărul care arată de câte ori a fost împrumutată fiecare carte, iar COUNT(COUNT(codel)), reprezintă numărul total al cărŃilor împrumutate.

Exemplu:

Pentru fiecare departament codul dep si numarul de angajati.

1 select department_id, count(*) 2 from employees 3* group by department_id SQL> / DEPARTMENT_ID COUNT(*) ------------- ---------- 10 1 20 2 30 6 40 1 50 45 60 5 70 1 80 34 90 3 100 6 110 2

1

12 rows selected.

Pentru departamentele cu mai mult de un angajat se afiseaza codul dep si numarul de angajati. 1 select department_id, coun 2 from employees 3 group by department_id 4* having count(*)>1 SQL> / DEPARTMENT_ID COUNT(*) ------------- ---------- 20 2 30 6 50 45 60 5 80 34 90 3

Page 272: CURS BD Combinat

24

100 6 110 2 8 rows selected.

Se afiseaza numarul departamentelor cu mai mult de un angajat.

1 select count(count(*)) 2 from employees 3 group by department_id 4* having count(*)>1 SQL> / COUNT(COUNT(*)) --------------- 8

Exemplu: Sa se afiseze numărul de cărŃi imprumutate din fiecare domeniu.

SELECT d.intdom, COUNT(*) FROM domeniu d, carte c, imprumuta I WHERE c.codel = i. codel AND c.coded = d.coded GROUP BY intdom;

Exemplu: Lista codurilor cititorilor care au mai mult de 3 cărŃi nerestituite la

termen.

SELECT codec FROM imprumuta WHERE dataef IS NULL AND datares < SYSDATE GROUP BY codec HAVING COUNT(*) > 2;

Exemplu: Pentru fiecare domeniu de carte care conŃine cel puŃin o carte şi

unde preŃul oricărei cărŃi nu depăşeşte o valoare dată, să se obŃină: codul domeniului, numărul cărŃilor din domeniu şi numărul mediu de exemplare.

SELECT coded, COUNT(*), AVG(nrex) FROM carte GROUP BY coded

Page 273: CURS BD Combinat

25

HAVING COUNT(*) >= 1 AND MAX(pret) < &pret_dat;

Exemplu: Codurile domeniilor care nu contin carti.

SELECT coded FROM carte GROUP BY coded HAVING COUNT(*) = 0;

Nu este corect, deoarece se iau in considerare NUMAI codurile domeniilor care apar in tabelul CARTE.

SELECT intdom FROM domeniu d WHERE 0 = (SELECT COUNT(*) FROM carte WHERE coded = d.coded);

Urmatoarea cerere este corecta?

SELECT intdom FROM domeniu d,(SELECT coded, COUNT(*) a FROM carte GROUP BY coded) b WHERE b.coded = d.coded) AND b.a = o;

Exemplu: În ce interogări este necesară utilizarea cuvântului cheie

HAVING?

A. când este necesar să eliminăm linii duble din rezultat;

B. când este necesar să ordonăm mulŃimea rezultat;

C. când este necesar să efectuăm un calcul pe grup;

D. când este necesar să restricŃionăm grupurile de linii returnate.

Operatori pentru interogări compuse Uneori este util să se ruleze interogări multiple şi să se combine

rezultatele într-un singur set de rezultate.

UNION Operatorul UNION adaugă rândurile din setul de înregistrări al

unei interogări la cel al unei alte inregistrări şi, în acelaşi timp, elimină rândurile duplicate, într-un mod similar cu cel al cuvântului cheie

Page 274: CURS BD Combinat

26

DISTINCT. OperaŃia este permisă numai dacă interogările sunt compatibile din punctul de vedere al uniunii, ceea ce înseamnă că au acelaşi număr de coloane şi că tipurile de date ale coloanelor corespondente sunt compatibile.

Iată un exemplu: • Afi şaŃi pe o singură coloană toate valorile nenule pentru taxa de

inchiriere şi taxa de întârziere din tabelul FILM_ÎNCHIRIAT. SELECT INCHIRIAT_FEE AS FEE FROM FILM_INCHIRIAT WHERE INCHIRIAT _FEE IS NOT NULL UNION

SELECT LATE_OR_LOSS_FEE AS FEE FROM FILM_INCHIRIAT WHERE LATE _OR_ LOSS FEE IS NOT NULL;

UNION ALL UNION ALL funcŃionează la fel ca şi operatorul UNION,

exceptând faptul că rândurile duplicate nu sunt eliminate.

INTERSECT Operatorul INTERSECT găseşte valorile selectate dintr-o

interogare, care apar şi într-o altă interogare. În esenŃă, găseşte intersecŃia valorilor din cele două interogări. Totuşi, doar un număr mic de sisteme DBMS (cele mai importance fiind Oracle şi DB2) implementează acest operator. Nu-1 veŃi găsi în Microsoft SQL Server sau MySQL.

Iată un exemplu: • Există în tabelul FILM filme pentru care preŃul pentru DVD este

egal cu preŃul pentru VHS? SELECT INCHIRIAT_FEE AS FEE FROM FILM_ INCHIRIAT WHERE INCHIRIAT _FEE IS NOT NULL INTERSECT SELECT LATE_OR_LOSS_FEE AS FEE FROM FILM_ INCHIRIAT WHERE LATE OR_ LOSS FEE IS NOT NULL

EXCEPT EXCEPT este operatorul standard ANSI/ISO care găseşte

diferenŃele dintre două seturi de rezultate, returnând, în esenŃă, valorile

Page 275: CURS BD Combinat

27

din prima interogare care nu apar în cea de-a doua interogare. Foarte puŃine sisteme DBMS implementează acest operator. În unele implementări, precum Oracle, operatorul se numeşte MINUS, nu EXCEPT.

Page 276: CURS BD Combinat

Cereri multi – relaţie

Comanda SELECT oferă posibilitatea de a consulta informaţii care provin din mai multe tabele. Operatorii care intervin în astfel de cereri pot fi:

operatori pe mulţimi (UNION, UNION ALL, INTERSECT, MINUS);

operatori compunere care implementează diferite tipuri de JOIN.

Există două moduri de realizare a cererilor multi-relaţie:

forma procedurală, în care trebuie indicat drumul de acces la informaţie prin imbricarea de comenzi SELECT;

forma relaţională, în care drumul de acces la informaţie este în sarcina sistemului.

Exemplu: Să se obţină, utilizând aceste două forme, codurile şi titlurile cărţilor împrumutate.

a) Forma procedurală (imbricare de comenzi SELECT): SELECT codel, titlu FROM carte WHERE codel IN (SELECT DISTINCT codel

FROM imprumuta); b) Forma relaţională:

SELECT carte.codel, titlu FROM carte, imprumuta WHERE carte.codel = imprumuta.codel;

Operatori pe mulţimi sau Operatori pentru interogări

compuse (UNION, UNION ALL, INTERSECT, MINUS)

Uneori este util să se ruleze interogări multiple şi să se combine rezultatele

într-un singur set de rezultate.

Operatorii pe mulţimi combină rezultatele obţinute din două sau mai multe

interogări. Cererile care conţin operatori pe mulţimi se numesc cereri compuse.

Există patru operatori pe mulţimi: UNION, UNION ALL, INTERSECT şi

MINUS(în unele implementeri oracle operatorul MINUS se numeşte EXCEPT).

Toţi operatorii pe mulţimi au aceeaşi precedenţă. Dacă o instrucţiune SQL conţine mai mulţi operatori pe mulţimi, server-ul Oracle evaluează cererea de la stânga la dreapta (sau de sus în jos). Pentru a schimba această ordine de evaluare, se pot utiliza paranteze.

Page 277: CURS BD Combinat

În mod implicit, pentru toţi operatorii cu excepţia lui UNION ALL, rezultatul este ordonat crescător după valorile primei coloane din clauza SELECT.

Pentru o cerere care utilizează operatori pe mulţimi, cu excepţia lui UNION ALL, server-ul Oracle elimină liniile duplicat.

În instrucţiunile SELECT asupra cărora se aplică operatori pe mulţimi,

coloanele selectate trebuie să corespundă ca număr ş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 puţin una din cele două cereri sunt de tip VARCHAR2.

Observaţii:

Comenzile SELECT, care intervin în cereri ce conţin operatori pe mulţimi,

trebuie să satisfacă anumite condiţii:

toate comenzile SELECT trebuie să aibă acelaşi număr de coloane;

opţiunea DISTINCT este implicită (excepţie UNION ALL);

numele coloanelor sunt cele din prima comandă SELECT;

dimensiunea coloanei implicit este cea mai mare dintre cele două coloane;

sunt admise combinaţii de forma:

1. SELECT1 UNION SELECT2 INTERSECT SELECT3 şi ordinea de

execuţie este de la stânga la dreapta;

2. SELECT1 UNION (SELECT2 INTERSECT SELECT3) şi ordinea

este dată de paranteze.

UNION

Operatorul UNION adaugă rândurile din setul de înregistrări al unei interogări la cel al unei alte interogări şi, în acelaşi timp, elimină rândurile duplicate, într-un mod similar cu cel al cuvântului cheie DISTINCT.

Operatorul UNION returnează deci toate liniile selectate de două cereri,

eliminând duplicatele. Operaţia este permisă numai dacă interogările sunt

compatibile din punctul de vedere al uniunii, ceea ce înseamnă că au acelaşi număr

de coloane şi că tipurile de date ale coloanelor corespondente sunt compatibile.

Acest operator nu ignoră valorile null şi are precedenţă mai mică decât operatorul

IN.

Page 278: CURS BD Combinat

Exemplu:

Să se afişeze pe o singură coloană toate valorile nenule pentru taxa de

inchiriere şi taxa de întârziere 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 afişeze 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 afişat o singură dată.

SELECT cod_opera

FROM polita_asig

UNION

SELECT cod_opera

FROM securitate;

Uneori, pentru a respecta regula conform căreia expresiile din clauzele

SELECT trebuie să concorde ca număr şi tip de date, se pot utiliza coloane

artificiale şi funcţii de conversie pentru tipurile de date.

Exemplu:

Să se listeze codul operelor de artă, codul şi numele artiştilor.

SELECT cod_opera, cod_artist, TO_CHAR(null) nume

FROM opera

UNION

SELECT TO_NUMBER(null), cod_artist, nume

FROM artist;

UNION ALL

Operatorul UNION ALL funcţionează la fel ca şi operatorul UNION,

exceptând faptul că rândurile duplicate nu sunt eliminate. Precizările făcute asupra operatorului UNION sunt valabile şi în cazul

operatorului UNION ALL. În cererile asupra cărora se aplică UNION ALL nu poate fi utilizat cuvântul cheie DISTINCT.

Page 279: CURS BD Combinat

Exemplu:

Să se determine codul operelor de artă pentru care s-a încheiat o poliţă de asigurare sau pentru care s-a achiziţionat un sistem de securitate. Să se afişeze firma şi data contractării, respectiv a instalării sistemului. Întrucât o operă poate avea mai multe poliţe de asigurare sau mai multe sisteme de securitate

încheiate, respectiv instalate la aceeaşi 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 apărea numai o singură dată într-o cerere compusă.

Dacă se utilizează, clauza trebuie plasată la sfârşitul cererii şi acceptă nume de

coloane, alias-uri sau notaţia poziţională. Numele de coloane şi alias-urile din

clauza ORDER BY trebuie să fie din lista SELECT a primei instrucţiuni.

INTERSECT

Operatorul INTERSECT găseşte valorile selectate dintr-o interogare, care apar şi într-o altă interogare. În esenţă, găseşte intersecţia valorilor din cele două interogări. Acest operator nu ignoră valorile null.

Totuşi, doar un număr mic de sisteme DBMS (cele mai importance fiind

Oracle şi DB2) implementează acest operator. Nu-1 veţi găsi în Microsoft SQL

Server sau MySQL.

Exemplu:

Există în tabelul FILM filme pentru care preţul pentru DVD este egal cu

preţul pentru VHS?

SELECT taxa_inchiriat AS TAXA

FROM FILM_INCHIRIAT

WHERE taxa_inchiriat IS NOT NULL

INTERSECT

SELECT taxa_intarziere AS TAXA

FROM FILM_INCHIRIAT

WHERE taxa_intarziere IS NOT NULL;

Page 280: CURS BD Combinat

Exemplu:

Să se afişeze 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 obţină, utilizând operatorul INTERSECT, codurile cărţilor din care sunt

mai puţin de 15 exemplare şi care au fost împrumutate de cel puţin trei ori.

SELECT codel

FROM carte

WHERE nrex < 15

INTERSECT

SELECT codel

FROM imprumuta

GROUP BY codel

HAVING COUNT(*) > 3;

MINUS

Operatorul MINUS sau EXCEPT găseşte diferenţele dintre două seturi de

rezultate, returnând, în esenţă, valorile din prima interogare care nu apar în cea de-

a doua interogare. Pentru ca operatorul MINUS să funcţioneze, este necesar ca

toate coloanele din clauza WHERE să se afle şi în clauza SELECT. Foarte puţine

sisteme DBMS implementează acest operator. În unele implementări, precum

Oracle, operatorul se numeşte MINUS, nu EXCEPT.

Exemplu:

Să se determine codul şi valoarea operelor de artă al căror preţ nu este de

20 de ori mai mare decât valoarea poliţei de asigurare.

SELECT cod_opera, valoare

Page 281: CURS BD Combinat

FROM opera

MINUS

SELECT cod_opera, valoare*20

FROM polita_asig;

Exemplu:

Să se afişeze codurile cititorilor care nu au împrumutat cărţi.

SELECT codec

FROM cititor

MINUS

SELECT DISTINCT codec

FROM imprumuta;

Operatorii pe mulţimi pot fi utilizaţi în subcereri. Coloanele care apar în

clauza WHERE a interogării trebuie să corespundă, ca număr şi tip de date, celor

din clauza SELECT a subcererii.

Exemplu:

Să se determine codul operelor de artă, codul autorilor şi titlul pentru

operele a căror valoare este mai mare decât 5000 sau pentru cele având valoarea

de 20 de ori mai mare decât cea a poliţei de asigurare.

SELECT cod_opera, cod_artist, titlu

FROM opera

WHERE (cod_opera, valoare)

IN (SELECT cod_opera, valoare

FROM opera

WHERE valoare > 5000

UNION

SELECT cod_opera, valoare*20

FROM polita_asig);

Page 282: CURS BD Combinat

Operaţia de compunere (JOIN)

S-au prezentat până acum instrucţiuni 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 următoare, observaţi valorile afişate pentru coloană FILM_GEN_COD.

Atunci când 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 discuţia despre procesul de normalizare, s-a evitat anomalia de

actualizare – dacă se schimbă descrierea unui gen, nu este nevoie să actualizăm

acea descriere pentru toate filmele asociate genului respectiv în tabelul FILM. În

timpul normalizării, 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 acelaşi nume) din tabelul FILM_GEN. S-a optat pentru

folosirea unui cod mnemonic pentru codurile genurilor.

Tabelul FILM (trei coloane)

FILM_COD FILM_GEN_COD FILM_TITLU

1 Drama Mystic River

2 ActAd The Last Samurai

3 Comedie Something's Gotta Grve

4 ActAd The Italian

5 ActAd Kill Bill: Voi. 1

6 ActAd Pirates of the Caribbean: Trie Curse of the Black Pearl

7 Drama Big Fish

8 ActAd Man on Fire

9 ActAd Master and Commander The Far Side of the World

10 Drama LosI în Translation

11 Rmce Two Weeks Notice

12 Comedie 50 First Dates

13 Comedie Matchstick Men

14 Drama Cold Mountain

15 Drama Road to Perdition

16 Comedie The School of Rock

17 Rmce 13 Going on30

18 Drama Monster

19 ActAd The Day After Tomorrow

20 Forgn Das Boot

Page 283: CURS BD Combinat

Evident, nu puteţi afişa pe pagina web a magazinului de produse video,

tabelul FILM aşa cum este prezentat în figura de mai sus - trebuie să obţineţi

descrierea completă a genurilor din tabelul FILM_GEN. Aceasta este ideea

capitolului de faţă: combinarea datelor din mai multe tabele într-o singură

interogare. Figura următoare prezintă un listing al tabelului FILM_GEN.

Tabelul FILM_GEN

FILM_GEN_COD FILM_GEN_DESCRIERE

ActAd Actiune

Anime Animatie

ChFam Copii şi Familie

Class Clasic

Comedie Comedie

Doc Documentar

Drama Drama

Forgn Strain

Hor Horror

Indep Independent

Music Muzical

Rmce Romance(Romantic, Idila)

SciFi Stiintifico-Fantastic

Sport Sport

Thriller Groaza

Uniuni (join)

O uniune (join) este o operaţie într-o bază de date relaţionale care combină

coloane din două sau mai multe tabele în rezultatele unei singure interogări. O

uniune apare de fiecare dată când clauza FROM a unei instrucţiuni 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;

Page 284: CURS BD Combinat

FILM_ID GEN FILM_TITLU

1 Actiune şi Aventura Mystic River

1 Animatie Mystic River

1 Clasic Mystic River

1 Documentar Mystic River

1 Strain Mystic River

1 Independent Mystic River

1 Groaza Mystic River

1 Sport Mystic River

1 SF Mystic River

1 Musical Mystic River

1 Horror Mystic River

1 Drama Mystic River

1 Comedie Mystic River

1 Copii şi Familie Mystic River

1 Actiune şi Aventura The Last Samurai

2 Thriller The Last Samurai

2 Sport The Last Samurai

2 SF The Last Samurai

2 Romantic The Last Samurai

2 Musical The Last Samurai

2 Independent The Last Samurai

2 Horror The Last Samurai

2 Animatie The Last Samurai

2 Copii şi Familie The Last Samurai

2 Documentar The Last Samurai

2 Strain The Last Samurai

2 Drama The Last Samurai

2 Comedie The Last Samurai

2 Clasic The Last Samurai

.. ... ...............

Setul de rezultate al interogării 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 corespondenţa dintre rândurile celor două tabele. Rezultatul este

cunoscut sub numele de produs cartezian (după numele filozofului şi

matematicianului francez Rene Descartes) şi, în bazele de date relaţionale, este un

set de rezultate obţinut prin uniunea dintre fiecare rând al unui tabel cu fiecare rând

dintr-un alt tabel.

Page 285: CURS BD Combinat

Soluţia este să specificăm cum se va face unirea tabelelor. Trebuie indicat ce

coloane ar trebui să se potrivească pentru a uni două rânduri din cele două tabele,

în mod normal, cele două coloane vor fi cheia primară dintr-un tabel şi cheia

externă din celălalt tabel, dar pot există şi excepţii. Pentru a realiza acest lucru

trebuie să se facă o o uniune standard relaţională, cunoscut şi sub numele de

uniune de egalitate (equijoin).

Join-ul este operaţia de regăsire 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.

Condiţia de join se scrie în clauza WHERE a instrucţiunii SELECT. Într-o

instrucţiune SELECT care uneşte tabele prin operaţia de join, se recomandă ca

numele coloanelor să fie precedate de numele tabelelor pentru claritate şi

pentru îmbunătăţirea timpului de acces la baza de date. Dacă acelaşi nume de

coloană apare în mai mult de două tabele, atunci numele coloanei se prefixează

obligatoriu cu numele tabelului corespunzător. Pentru a realiza un join între n

tabele, va fi nevoie de cel puţin n – 1 condiţii de join.

Equijoin-ul corespunde situaţiei în care valorile de pe coloanele ce apar în

condiţia de join trebuie să fie egale. Un astfel de join mai poartă numele de join

simplu sau inner join. Un nonequijoin este o condiţie de join care conţine alţi

operatori decât operatorul egalitate. Un self join realizează compunerea unui tabel

cu el însuşi.

Uniuni de egalitate (equijoin)

Avem o uniune de egalitale (equijoin), numită şi uniune internă (inner join),

atunci când legăm 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

condiţia 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ă modalităţi de specificare a coloanelor corespondente: folosind

clauza WHERE sau folosind clauza JOIN. Clauza JOIN a fost adăugată relativ

recent în standardul SQL, aşa că programatorii mai vechi sunt obisnuiţi cu metoda

bazată pe clauza WHERE.

Page 286: CURS BD Combinat

Realizarea uniunilor folosind clauza WHERE

Folosirea clauzei WHERE pentru unirea tabelelor seamănă cu folosirea

acesteia pentru eliminărea rândurilor de care nu aveţi nevoie din setul de rezultate.

Totuşi, există unele diferenţe.

În clauza WHERE :

Se compară o coloană cu o altă coloană, nu o coloană cu o constantă sau o

expresie.

Atunci când coloanele din cele două tabele au acelaşi nume (o soluţie

recomandată) trebuie să specificati numele complet al coloanelor (adică numele cu

calificator), astfel încât motorul SQL să ştie care dintre cele două coloane este

referită. Motorul SQL cere să se refere toate coloanele specificate într-o

instrucţiune SQL. Aceasta nu înseamnă numai coloanele din clauza WHERE, ci

din orice alt loc al instrucţunii, inclusiv în lista SELECT. 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.

Observaţi că interogarea selectează coloanele FILM_ID şi FILM_TITLU din

tabelul FILM şi genul corespunzător (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 FILM_GEN FILM_TITLU 1 Drama Mystic River

2 Actiune şi Aventura The Last Samurai

3 Comedie Something's Gotta Give

4 Actiune şi Aventura The Italian Job

5 Actiune şi Aventura Kill Bill Vol. 1

6 Actiune şi Aventura Pirates of the Caribbean

7 Drama Big Fish

8 Actiune şi Aventura Man on Fire

9 Actiune şi Aventura Master and Commander

10 Drama Lost în Translation

11 Romantic Two Weeks Notice

12 Comedie 50 First Dates

Page 287: CURS BD Combinat

13 Comedie Matchstick Men

14 Drama Cold Mountain

15 Drama Road to Perdition

16 Comedie The School of Rock

17 Romantic 13 Going on 30

18 Drama Monster

19 Actiune şi Aventura The Day After Tomorrow

20 Strain Das Boot

Exemplu:

Să se obţină codurile şi titlurile cărţilor împrumutate.

SELECT carte.codel, titlu

FROM carte, imprumuta

WHERE carte.codel = imprumuta.codel;

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 funcţionează la fel ca şi pseudonimele coloanelor din clauza

SELECT, exceptând faptul că nu este folosit cuvântul cheie „AS" (în cele mai

multe implementări SQL) - doar lăsaţi un spaţiu între numele tabelului şi

pseudonim în lista FROM. Deşi unii folosesc mnemonice pentru pseudonimul

tabelelor, este mult mai des întâlnită folosirea secvenţelor de majuscule (adică „A",

„B”,”C” şi aşa mai departe). După ce se asociază un pseudonim unui nume de tabel

în clauza FROM, trebuie să folosiţi pseudonimul în locul numelui de tabel în

întreaga instrucţiune SQL. Folosirea pseudonimelor în clauza SELECT poate părea

puţin ciudată la început deoarece folosiţi un pseudonim înainte de a-l defini (clauza

SELECT precede clauza FROM şi s-ar putea să pară mai simplu să completaţi

clauza FROM înainte de a completa lista de coloane din clauza SELECT atunci

când scrieţi instrucţiunile SQL.

Exemplul următor prezintă instrucţiunea anterioară, după adăugarea

pseudonimelor pentru numele tabelelor. Deşi nu era necesar, pseudonimele au fost

adăugate şi în lista de coloane din clauzele SELECT şi ORDER BY, pentru a va

arăta cum sunt folosite.

Page 288: CURS BD Combinat

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 afişeze informaţii despre operele de artă achiziţionate î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 afişeze informaţii referitoare la operele de artă, artiştii care le-au

creat şi galeriile în care sunt expuse.

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;

S-ar putea ca tabelele legate prin operaţia de compunere să nu aibă coloane

comune (non-equijoin). În acest caz în clauza WHERE nu apare operatorul

egalitate şi sunt folosiţi operatorii: <=, >=, BETWEEN.

Un self join realizează compunerea unui tabel cu el însuşi.

Exemplu:

Să se obţină pentru fiecare salariat numele, salariul şi grila de salarizare (Θ

join).

SELECT e.name, e.sal, s.grade

FROM emp e, salgrade s

WHERE e.sal BETWEEN s.lasal AND s.hisal;

Page 289: CURS BD Combinat

Exemplu:

Să se obţină titlurile şi preţurile cărţilor mai scumpe decât cartea având titlul

“Baze de date”, al cărui autor este POPA (self join).

SELECT x.titlu, x.pret

FROM carte x, carte y

WHERE x.pret > y.pret

AND y.titlu = ’Baze de date’

AND y.autor = POPA;

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 condiţia de legătură scrisă anterior în clauza

WHERE într-o singură clauză. Sintaxa generală a clauzei JOIN pentru o uniune

internă, urmată de câteva exemple.

Sintaxa corespunzătoare standardului SQL3 este următoarea:

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 condiţii similare cu cea din clauza

WHERE .

Clauza USING specifică numele coloanelor folosite pentru legarea

rândurilor. Totuşi, clauza USING acţionează numai atunci când coloanele pe care

se face legătură 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 având acelaşi nume, dar

tipuri de date diferite. Coloanele referite în clauza USING trebuie să nu conţină

calificatori (să nu fie precedate de nume de tabele sau alias-uri) în nici o apariţie a

lor în instrucţiunea SQL. Clauzele NATURAL JOIN şi USING nu pot coexista în

aceeaşi instrucţiune SQL.

Page 290: CURS BD Combinat

JOIN tabel_2 ON tabel_1.nume_coloană = tabel_2.nume_coloană

efectuează un equijoin pe baza condiţiei exprimate în clauza ON. Această clauză

permite specificarea separată a condiţiilor de join, respectiv a celor de căutare sau

filtrare (din clauza WHERE).

Exemple:

• JOIN cu condiţie 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 cuvântul cheie USING (în locul condiţiei ON) o scurtatură

elegantă atunci când coloanele din cele două tabele au acelaşi 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 afişează lista cu copiile filmelor din tabelul FILM_COPY

care nu au fost vândute (coloană DATA_VANZARE conţine o valoare nulă dacă

nu a fost vândută) şi care au fost închiriate (uniune cu tabelul FILM_INCHIRIAT)

dar nu au fost încă returnate (coloană RETUR_DATA conţine o valoare nulă până

la returnarea filmului).

SELECT FILM_ID, COPY_NUMAR, DATA_RETURNARII

FROM FILM_COPY JOIN FILM__INCHIRIAT

USING (FILM_ID, COPY_NUMAR)

Page 291: CURS BD Combinat

WHERE DATA_VANZARE IS NULL

AND RETUR_DATA IS NULL;

FILM _ID COPY_NUMAR DATA_RETURNARII

2 2 02/27/2009

3 2 03/04/2009

5 1 02/27/2009

5 2 02/19/2009

10 1 03/04/2009

17 1 03/04/2009

Instrucţiunile care folosesc clauza JOIN sunt mai scurte. Interogarea

precedentă scrisă folosind condiţii de legătură î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. Instrucţiunea de mai jos

afişează aceleaşi rezultate ca şi instrucţiunea 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 acelaşi

nume din două tabele, în esenţă, toate uniunile de egalitate sunt uniuni naturale.

Totuşi, sintaxa unei uniuni naturale este mult mai simplă, deoarece nu este necesar

să specificaţi o condiţie sau o listă de coloane - se înţelege 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;

Page 292: CURS BD Combinat

Uniunile pot implica mai mult de două tabele. Exemplul următor prezintă o

uniune naturală care obţine 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

filme din tabelul FILM. Folosirea clauzei WHERE permte să se elimine din setul

de rezultate rândurile de care nu avem nevoie.

Exemplul foloseşte 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

rândurile 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 Drama R Sub 17 ani acompaniati de parinti

2 Acţiune si Aventura R Sub 17 ani acompaniati de parinti

3 Comedie PG-13 Cu acordul strict a parintilor

Dacă se foloseşte o implementare SQL care nu acceptă uniunile naturale,

aceeaşi 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;

Page 293: CURS BD Combinat

Exemple la schema galerii de arta

a) Să se determine titlul operelor de artă expuse în galeriile având codul 10

sau 30, respectiv numele şi prenumele artiştilor care le-au realizat.

SELECT titlu, nume, prenume

FROM opera NATURAL JOIN artist

WHERE 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);

Următoarea cerere va returna eroarea „ORA-25154: column part of USING

clause cannot have qualifier“, întrucât 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 afişeze titlurile operelor de artă, firmele la care sunt asigurate şi

descrierea poliţelor de asigurare corespunzătoare.

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 până acum sunt uniuni exclusiv (uniuni

interne), ceea ce înseamnă că singurele rânduri care apar în setul de rezultate sunt

cele pentru care a fost găsită o legătură în toate tabelele unite.

Există situaţii în care se doreşte să includeţi în rezultatele interogării şi

rânduri pentru care nu există o legătură. De exemplu, dacă se doreşte o listă cu

toate genurile de filme, împreună cu toate titlurile asociate cu fiecare gen?

Page 294: CURS BD Combinat

O uniune externă (outer join) - pentru care un nume mai potrivit ar fi uniune

inclusivă - include în setul de rezultate şi rândurile pentru care nu există legături

din cel puţin unul dintre tabele. Atunci când există rânduri fără legături, datele

selectate din tabelul în care nu a fost găsită o legătură primesc valoarea nulă.

Un outer join este utilizat pentru a obţine în rezultat şi înregistrările care nu

satisfac condiţia de join. Operatorul pentru outer join este semnul plus inclus între

paranteze (+), care se plasează în acea parte a condiţiei de join care este deficientă

în informaţie. Efectul acestui operator este de a uni liniile tabelului care nu este

deficient în informaţie şi cărora nu le corespunde nici o linie în celălalt tabel cu o

linie cu valori null. Operatorul (+) poate fi plasat în orice parte a condiţiei de join,

dar nu în ambele părţi.

O condiţie care presupune un outer join nu poate utiliza operatorul IN şi nu

poate fi legată de altă condiţie prin operatorul OR.

Exemplu:

Se presupune că tabelul artist conţine şi artişti care nu au opere expuse în

muzeu. Să se afişeze artiştii şi operele acestora, inclusiv cei care nu au opere

corespunzătoare în tabelul opera.

SELECT a.cod_artist, nume, prenume, cod_opera, titlu

FROM artist a, opera o

WHERE a.cod_artist = o.cod_artist (+);

Există trei tipuri de bază:

Uniune externă către stânga (left outer join). Returnează toate rândurile

din tabelul din stânga (cel specificat primul în clauza JOIN), împreună cu toate

rândurile din tabelul din dreapta pentru care poate fi găsită o legătură.

(asemănatoare interogărilor din tabele aflate in relaţia 1:m)

Uniune externă către dreapta (right outer join). Returnează toate rândurile

din tabelul din dreapta (cel specificat al doilea în clauza JOIN), împreună cu toate

rândurile din tabelul din stânga pentru care poate fi găsită o legătură, în esenţă, o

uniune externă către stânga poale fi rescrisă ca o uniune externă către dreapta

inversând ordinea de specificare a tabelelor şi înlocuind cuvântul cheie LEFT cu

RIGHT.

Uniune externă completă (full outer join). Returnează toate rândurile din

ambele tabele. Acest tip de uniune este cel mai puţin probabil să fie acceptată de

toate implementari;e SQL. Această uniune nu este acelaşi lucru cu un produs

cartezian, care leagă fiecare rând dintr-un tabel cu fiecare rând din celălalt tabel. O

uniune externă completă leagă fiecare rând dintr-un tabel cu zero sau mai multe

rânduri corespondente din celălalt tabel.

Page 295: CURS BD Combinat

Este folosită mai mult pentru tabelele aflate in relaţia m:m

Sintaxa generală pentru o uniune externă este:

nume_tabel {RIGHT | LEFT | FULL} [OUTER] JOIN nume_tabel {

ON condiţie | USING (nume_coloană [ ,nume_coIoană. ..]) }

Exemple de uniuni externe:

• Să se afişeze toate descrierile genurilor de filme, împreună cu filmele

asociate fiecărui gen. În setul de rezultate rândurile 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 cuvântul cheie USING,

modificaţi instrucţiunea astfel încât să utilizeze cuvântul cheie ON, ca în exemplul

care urmează după acesta.

SELECT FILM_GEN_DESCRIERE AS GEN, FILM_TITLU

FROM FILM_GEN LEFT OUTER JOIN FILM USING

(FILM_GEN_COD);

GEN FILM_TITLU

Actiune şi Aventura Kill Bill: Vol. 1

Actiune şi Aventura Man on Fire

Actiune şi Aventura Pirates of the

Caribbean

Actiune şi Aventura Master and

Commander

Actiune şi Aventura The Day After

Tomorrow

Actiune şi Aventura The Last Samurai

Actiune şi Aventura The Italian Job

Anime and

Animation

Copii şi Familie

Clasic

Comedie 50 First Dates

Comedie Matchstick Men

Comedie The School of Rock

Page 296: CURS BD Combinat

Comedie Something's Gotta

Give

Documentar

Drama Big Fiah

Drama Road to Perdition

Drama Mystic River

Drama Monster

Drama Cold Mountain

Drama Lost în Translation

Strain Das Boot

Horror

Independent

Musical

Romantic 13 Going on 30

Romantic Two Weeks Notice

• Interogarea anterioară, rescrisă ca uniune externă către dreapta,

cu condiţie 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 aceleaşi

rezultate ca şi uniunea externă către dreapta din interogarea anterioară. Totuşi, dacă

genurile filmelor ar fi opţionale, uniunea externă completă v-ar fi permis să afişaţi

atât genurile care nu au filme asociate, cât ş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;

• Afişaţi descrierile genurilor care nu au nume asociate. Există şi alte

moduri de a face acest lucru, dar exemplul de faţă foloseşte faptul că rândurile

pentru care nu există legături returnează valori nule pentru a selecta numai genurile

care nu au nume asociate.

Page 297: CURS BD Combinat

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 răspuns la cererile clienţilor, mai mulţi producători de baze de date

relaţionale au introdus uniunile externe inainte de standardizarea clauzei JOIN.

Secţiunile următoare prezintă câteva implementări specifice ale sintaxei uniunii

externe. Aceste soluţii particulare sunt prezentate aici numai pentru că s-ar putea să

le intâlniţi în instrucţiuni SQL mai vechi

Exemplu:

a) Să se afişeze 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 poliţe de asigurare.

SELECT titlu, firma

FROM opera o

LEFT OUTER JOIN polita_asig p ON (o.cod_opera = p.cod_opera);

b) Să se afişeze artiştii (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);

Page 298: CURS BD Combinat

c) Să se afişeze numele şi prenumele artiştilor, precum şi titlurile operelor

create de aceştia. Se vor afişa şi artiştii care nu au opere expuse în cadrul muzeului,

precum şi titlurile operelor al căror autor este necunoscut.

SELECT nume, prenume, titlu

FROM opera o

FULL OUTER JOIN artist a ON (o.cod_artist = a.cod_artist);

Specificarea condiţiilor suplimentare ale unei interogări poate fi făcută atât

în clauza WHERE, cât şi în clauza ON. Următoarea instrucţiune este corectă şi are

acelaşi efect dacă în locul operatorului AND ar apărea clauza WHERE.

SELECT o.titlu, p.firma, p.descriere

FROM opera o

JOIN polita_asig p ON (o.cod_opera = p.cod_opera)

AND o.cod_opera = 180;

Să se obţină titlurile cărţilor şi numele domeniului căruia îi aparţin,

remarcând si situaţiile în care domeniul nu ar avea cărţi (dacă domeniul este

fără cărţi atunci apare null la titlul cărţii).

SELECT titlu, intdom

FROM carte, domeniu

WHERE carte.coded(+) = domeniu.coded;

Exemplu:

Considerăm că tabelele dept şi emp au următorul conţinut:

dept emp

deptno dname empno deptno

1 algebra 101 null

2 analiza 102 null

103 null

105 1

106 1

Interogarea următoare furnizează lista tuturor salariaţilor si informatii

despre departamentele in care lucreaza, inclusiv a celor care nu sunt asignaţi

nici unui departament (right outher join).

SELECT a.deptno, a.dname, b.empno, b.deptno

FROM dept a, emp b

Page 299: CURS BD Combinat

WHERE a.deptno(+) = b.deptno;

Rezultatul cererii anterioare va fi:

a.deptno a.dname b.empno b.deptno

101

102

103

1 algebra 105 1

1 algebra 106 1

Interogarea următoare afişează lista departamentelor, inclusiv a celor

care nu au salariaţi (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 următoare produce ca rezultat departamentele, chiar şi cele

fără funcţionari, şi funcţionarii, chiar şi cei care nu sunt asignaţi 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

Page 300: CURS BD Combinat

c) Să se afişeze numele şi prenumele artiştilor, precum şi titlurile operelor

create de aceştia. Se vor afişa şi artiştii care nu au opere expuse în cadrul muzeului,

precum şi titlurile operelor al căror autor este necunoscut.

SELECT nume, prenume, titlu

FROM opera o

FULL OUTER JOIN artist a ON (o.cod_artist = a.cod_artist);

Specificarea condiţiilor suplimentare ale unei interogări poate fi făcută atât

în clauza WHERE, cât şi în clauza ON. Următoarea instrucţiune este corectă şi are

acelaşi efect dacă în locul operatorului AND ar apărea clauza WHERE.

SELECT o.titlu, p.firma, p.descriere

FROM opera o

JOIN polita_asig p ON (o.cod_opera = p.cod_opera)

AND o.cod_opera = 180;

Uniuni încrucişate (cross joins)

O uniune încrucişată (cross join) nu este altceva decât sintaxa standard

pentru un produs cartezian. Interogarea care unea tabelele FILM şi FILM_GEN şi

obţinea 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 încrucişată:

SELECT FILM_ID, FILM_GEN_DESCRIERE AS GEN, FILM_TITLU

FROM FILM CROSS JOIN FILM_GEN

ORDER BY FILM_ID;

Subinterogări

O caracteristică foarte puternică a limbajului SQL sunt subinterogările

(numite şi selecţii), care, aşa cum sugerează şi numele, se referă la o instrucţiune

SELECT care contine o instrucţiune SELECT subordonată. De obicei,

subinterogările sunt folosite în clauza WHERE, ca modalitate de limitare a

rândurilor returnate în setul de rezultate al interogării externe. Aceasta poate fi o

modalitate foarte flexibilă de selectare a datelor.

Page 301: CURS BD Combinat

O regulă esenţială de sintaxă este ca subinterogarea să fie încadrată de

paranteze.

Orice operaţie efectuată cu o subinterogare poate fi facută şi printr-o uniune.

Subinterogări necorelate

O subinterogare necorelată (noncorrelated subselect) este o subinterogare în

care interogarea internă nu face nici o referire la interogarea externă care o conţine.

Aceasta înseamnă că poate fi rulată mai intâi interogarea internă, apoi setul de

rezultate obţinut poate fi folosit în interogarea externă.

Exemple:

• Afişaţi toate limbile în care nu există nici un film în inventarul magazinului

de produse video.

SELECT LIMBA_COD, LIMBA_NUME

FROM LIMBA

WHERE LIMBA_COD NOT IN

(SELECT DISTINCT LIMBA_COD

FROM FILM_LIMBA)

ORDER BY LIMBA_COD

LIMBA_COD LIMBA_NUME

Ja Japoneza

Ko Coreana

ni Olandeza

ru Rusa

zh Chineza

Interogarea internă returnează o listă cu codurile de limbă asociate

filmelor în tabelul FILM_LIMBA. Cuvântul cheie DISTINCT elimină rândurile

duplicate din setul de rezultate .

Interogarea internă rulată independent, pentru a vă ajuta să înţelegeţi

cum funcţionează:

SELECT DISTINCT LIMBA_COD FROM FILM_LIMBA;

LIMBA_COD

-------------------------------------------

de (Germana)

en (Engleza)

es (Spaniola)

Page 302: CURS BD Combinat

f r (Franceza)

• Proprietarul magazinului vrea să vadă efectul recentei creşteri de preţuri

şi are nevoie de o listă a tranzacţiilor (TRANZACTIE_ID) în care clientul a plătit

mai mult decât taxa medie (INCHIRIAT_TAXA) pentru un film. Iată cum arată

interogarea:

SELECT DISTINCT TRANZACTIE_ID

FROM FILM_INCHIRIAT

WHERE INCHIRIAT_TAXA>

(SELECT AVG(INCHIRIAT_TAXA) FROM FILM_INCHIRIAT)

Interogarea internă calculează media taxelor de închiriere, iar interogarea

externă găseşte apoi toate rândurile din tabelul FILM_INCHIRIAT pentru care

valoarea INCHIRIAT_TAXA depăşeşte media.

Cuvântul cheie DISTINCT elimină tranzacţiile duplicate.

• Rezultatele interogării anterioare ar fi mai utile pentru proprietarul magazinului

dacă ar include şi data tranzacţiei. O modalitate de a realiza acest lucru este şi

adăugăm o uniune cu tabelul CLIENT_TRANZACTIE în interogarea externă.

Totuşi, deoarece tocmai aţi învăţat despre subinterogari, să facem acelaşi lucru

folosind încă o subinterogare. Iată cum arată interogarea:

SELECT TRANZACTIE_ID, TRANZACTIE_DATA AS TRANZ_DATA

FROM CLIENT_TRANZACTIE

WHERE TRANZACTIE_ID IN

(SELECT DISTINCT TRANZACTIE_ID FROM FILM_INCH,

WHERE INCH_TAXA > (SELECT AVG ( INCHIRIAT_TAXA)

FROM FILM_INCHIRIAT)

TRANZACTIE_ID TRANZ_DATA

9 03/01/2005

10 03/01/2005

Subinterogări corelate

O subinterogare corelată (correlated subselect) este o subinterogare în care

interogarea internă referă valorile furnizate de interogarea externă. Aceste

subinterogari sunt mult mai puţin eficiente decât subinterogările necorelate,

Page 303: CURS BD Combinat

deoarece interogarea internă trebuie să fie apelată pentru fiecare rând găsit de

interogarea externă.

Exemplu:

Proprietarul magazinului vrea să transmită prin poştă un cupon valoric

tuturor clienţilor care au plătit mai mult de 15$ pentru o singură tranzacţie de

închiriere.

SELECT DISTINCT CLIENT_CONT_ID

FROM CLIENT_TRANZACTIE A

WHERE 15 < (SELECT SUM (INCHIRIAT_TAXA)

FROM FILM_INCHIRIATB

WHERE A.TRANZACTIE _ID = B.TRANZACTIE_ID)

CLIENT_CONT_ID

2

7

9

Observaţi pseudonimele asociate numelor de tabele din interogările

internă şi externă, precurn şi folosirea acestora în clauza WHERE a interogării

interne. Acesta este elementul de identificare al unei subinterogări corelate.

Interogarea externă selectează o lista de valori CLIENT_CONT_ID distincte din

tabelul CLIENT_TRANZACTIE. Fiecare valoare găsită este transmisă interogării

interne, care este rulată pentru a calcula suma taxelor de închiriere din tranzacţia

respectivă. Dacă suma taxelor de închiriere este mai mare sau egală cu 15, atunci

clauza WHERE din interogarea externă ia valoarea logică „adevărat", iar rândul

CLIENT_ID este adăugat în setul de rezultate.

Vizualizări în linie

Foarte puţine implementări, printre care Oracle, permit folosirea unei

subinterogări în clauza FROM a unei interogări, într-o construcţie numită

vizualizare în linie (inline view). Această construcţie permite care setul de rezultate

al unei interogări să fie tratat ca şi cum ar fi un tabel sau o vizualizare predefinită.

Iată un exemplu:

• Această interogare află numărul maxim de închirieri ale unui singur film;

SELECT MAX(INCHIRIAT_NUMAR) AS MAX_INCHIRIAT_NUMAR

FROM (SELECT FILM_ID, NUMAR(*) AS INCHIRIAT_NUMAR

FROM FILM_INCHIRIAT GROUP BY FILM_ID)

Page 304: CURS BD Combinat

MAX_INCH_NUMAR

5

Interogarea internă calculează numărul de închirieri pentru fiecare valoare

FILM_ID. Interogarea externă selectează valoarea maximă INCHIRIAT_NUMAR

din interogarea internă, tratată ca şi cum ar fi o vizualizare predefinită. Nu există

nici o limită în privinţa modurilor de utilizare a vizualizărilor în linie - puteţi chiar

să le uniţi cu alte tabele sau vizualizări.

Page 305: CURS BD Combinat

Subinterogări (Subcereri)

O caracteristică foarte puternică a limbajului SQL sunt subinterogările

(numite şi selecţii), care, aşa cum sugerează şi numele, se referă la o instrucţiune

SELECT care conţine o instrucţiune SELECT subordonată.

De cele mai multe ori, pentru a implementa anumite interogări, nu este

suficientă o singură cerere SELECT ci sunt necesare subcereri.

Subcererile sunt comenzi SELECT încapsulate în oricare din clauzele ,

SELECT, WHERE, HAVING, FROM, numită instrucţiune „părinte“.

Dacă subcererea urmează clauzei WHERE sau HAVING, ea poate conţine

unul dintre operatorii ALL, ANY, IN (=ANY), EXIST, NOT IN (!=ALL) care sunt

specifici cererilor care întorc mai multe linii (multiple-row subquery) sau unul

dintre operatorii de comparare (=, <, >, >=, <=, <>) care sunt specifici cererilor

care întorc o singură linie (single-row subquery).

Utilizând subcereri, se pot construi interogări complexe pe baza unor

instrucţiuni simple. Subcererile mai sunt numite instrucţiuni SELECT imbricate

sau interioare.

Subcererea returnează o valoare care este utilizată de către instrucţiunea

„părinte“. Utilizarea unei subcereri este echivalentă cu efectuarea a două cereri

secvenţiale şi utilizarea rezultatului cererii interne ca valoare de căutare în cererea

externă (principală).

Subcererile pot fi utilizate în următoarele situaţii:

pentru a furniza valori care intervin în condiţiile din clauzele WHERE,

HAVING şi START WITH ale instrucţiunilor SELECT;

pentru a defini o mulţime de linii care urmează să fie inserată în tabelul

destinaţie al unei instrucţiuni INSERT sau CREATE TABLE;

pentru a defini o mulţime de linii care urmează să fie inserate într-o

vizualizare sau vizualizare materializată, prin intermediul unei

instrucţiuni CREATE VIEW sau CREATE MATERIALIZED VIEW;

pentru a defini una sau mai multe valori care urmează să fie atribuite unor

linii existente într-o instrucţiune UPDATE;

pentru a defini un tabel asupra căruia va opera cererea externă (plasarea

subcererii în clauza FROM sau în instrucţiunile INSERT, UPDATE,

DELETE).

Page 306: CURS BD Combinat

Subcererile trebuie incluse între paranteze şi trebuie plasate în partea dreaptă

a operatorului de comparare. Subcererea nu poate conţine clauza ORDER BY.

De obicei, subinterogările sunt folosite în clauza WHERE, ca modalitate de

limitare a rândurilor returnate în setul de rezultate al interogării externe. Aceasta

poate fi o modalitate foarte flexibilă de selectare a datelor.

O regulă esenţială de sintaxă este ca subinterogarea să fie încadrată de paranteze.

Orice operaţie efectuată cu o subinterogare poate fi făcută şi printr-o uniune.

Exemplu:

Să se obţină numele şi salariul angajaţilor, având salariul minim.

SELECT name, sal

FROM angajati

WHERE sal=(SELECT MIN(sal)

FROM angajati);

Exemplu:

Să se obţină job-ul pentru care salariul mediu este minim. Sa se afiseze si

salariul mediu.

SELECT job, AVG(sal)

FROM angajati

GROUP BY job

HAVING AVG(sal)=(SELECT MIN(AVG(sal))

FROM angajati

GROUP BY job);

Operatorul ANY presupune că este adevărată condiţia dacă comparaţia este

adevărată pentru cel puţin una din valorile returnate. Sunt evidente relaţiile:

< ANY mai mic ca maximul;

> ANY mai mare ca minimul;

= ANY IN.

Pentru operatorul ALL se presupune că este adevărată condiţia, dacă

comparaţia este adevărată pentru toate elementele listei returnate. Pentru operatorul

ALL sunt evidente relaţiile:

< ALL mai mic ca minimul;

> ALL mai mare ca maximul;

! = ALL NOT IN.

Page 307: CURS BD Combinat

Exemplu:

WHERE codec > ALL („C1‟, „C2‟) este superior tuturor elementelor din listă;

WHERE codec > ANY („C1‟, „C2‟) este superior cel puţin unui element din

listă.

Exemplu:

Să se obţină salariaţii al căror salariu este mai mare ca salariile medii din

toate departamentele.

SELECT nume, job

FROM angajati

WHERE sal > ALL(SELECT AVG(sal)

FROM angajati

GROUP BY cod_dep);

Există subcereri care au ca rezultat mai multe coloane (multiple-column

subquery). Aceste interogări au următoarea sintaxă generală:

SELECT col,col,…

FROM tabel

WHERE (col,col,…) IN (SELECT col,col,…

FROM tabel

WHERE condiţie);

Dacă una din valorile returnate de subcerere este valoarea null atunci cererea

nu întoarce nici o linie. Prin urmare, dacă valoarea null poate să facă parte din

rezultatul subcererii nu trebuie utilizat operatorul NOT IN. Problema nu mai apare

dacă se utilizează operatorul IN.

Exemplu:

Să se obţină salariaţii care nu au subordonaţi.

SELECT a.nume FROM angajati a WHERE a.cod_ang NOT IN (SELECT m.mgr

FROM angajati m);

În acest caz, instrucţiunea SQL nu întoarce nici o linie deoarece una din valorile furnizate de subcerere este valoarea null.

Page 308: CURS BD Combinat

Subinterogări necorelate (nesincronizate)

O subinterogare necorelată (noncorrelated subselect) este o subinterogare în

care interogarea internă nu face nici o referire la interogarea externă care o conţine.

Subcererile necorelate returnează o valoare care este utilizată de cererea

externă (cererea principală). Cererile care conţin subcereri necorelate sunt evaluate

în modul următor:

cererea internă este executată prima şi determină o valoare (sau o

mulţime de valori);

cererea externă se execută o singură dată, utilizând valorile returnate de

cererea internă.

În general, o cerere imbricată, necorelată are următoarea formă:

SELECT lista_select

FROM nume_tabel

WHERE expresie operator (SELECT lista_select

FROM nume_tabel);

În această sintaxă, identificatorul operator poate fi de tip:

single-row operator (>, =, >=, <, <>, <=), care poate fi utilizat dacă

subcererea returnează o singură linie;

multiple-row operator (IN, ANY, ALL), care poate fi folosit dacă

subcererea returnează mai mult de o linie.

Operatorul ANY, care este sinonim cu operatorul SOME, determină

compararea unei valori cu fiecare valoare returnată de o subcerere. Astfel, <ANY

are semnificaţia „mai mic decât maximul“; >ANY înseamnă „mai mare decât

minimul“; =ANY este echivalent cu operatorul IN. Operatorul ALL compară o

valoare cu toate valorile returnate de o subcerere. Astfel, <ALL are semnificaţia

„mai mic decât minimul“, iar >ALL este echivalent cu „mai mare decât maximul“.

Operatorul NOT poate fi utilizat în combinaţie cu IN, ANY şi ALL.

În utilizarea unei subcereri se impun anumite reguli.

Subcererea trebuie inclusă între paranteze.

Pentru claritate, subcererea se plasează în partea dreaptă a operatorului de

comparaţie.

Înainte de versiunea Oracle8i, subcererile nu puteau să conţină clauza

ORDER BY. Începând cu Oracle8i, clauza ORDER BY poate fi utilizată şi

este chiar obligatorie în subcerere pentru a efectua analiza top-n (cererea

care efectuează analiza top-n returnează cele mai mari sau cele mai mici

n valori ale unei coloane).

Operatorul folosit trebuie să fie conform cu tipul cererii. Cererea va

Page 309: CURS BD Combinat

genera o eroare dacă este utilizat un operator single-row în faţa unei

subcereri care returnează mai mult de o linie. De asemenea, dacă

subcererea nu returnează nici o linie, apare o eroare.

Server-ul Oracle nu impune nici o limită asupra numărului de subcereri.

Limita acestora depinde de dimensiunea buffer-ului pe care îl utilizează cererea.

Exemple:

• Afişaţi toate limbile în care nu există nici un film în inventarul magazinului de

produse video.

SELECT LIMBA_COD, LIMBA_NUME

FROM LIMBA

WHERE LIMBA_COD NOT IN

(SELECT DISTINCT LIMBA_COD

FROM FILM_LIMBA)

ORDER BY LIMBA_COD

LIMBA_COD LIMBA_NUME

Ja Japoneza

Ko Coreana

ni Olandeza

ru Rusa

zh Chineza

Interogarea internă returnează o listă cu codurile de limbă asociate filmelor în

tabelul FILM_LIMBA. Cuvântul cheie DISTINCT elimină rândurile duplicate din

setul de rezultate .

Interogarea internă rulată independent, pentru a vă ajuta să înţelegeţi cum

funcţionează:

SELECT DISTINCT LIMBA_COD FROM FILM_LIMBA;

LIMBA_COD

-------------------------------------------

de (Germana)

en (Engleza)

es (Spaniola)

f r (Franceza)

Page 310: CURS BD Combinat

• Proprietarul magazinului vrea să vadă efectul recentei creşteri de preţuri şi are

nevoie de o listă a tranzacţiilor (TRANZACTIE_ID) în care clientul a plătit mai

mult decât taxa medie (INCHIRIAT_TAXA) pentru un film. Iată cum arată

interogarea:

SELECT DISTINCT TRANZACTIE_ID

FROM FILM_INCHIRIAT

WHERE INCHIRIAT_TAXA>

(SELECT AVG(INCHIRIAT_TAXA) FROM FILM_INCHIRIAT)

Interogarea internă calculează media taxelor de închiriere, iar interogarea externă

găseşte apoi toate rândurile din tabelul FILM_INCHIRIAT pentru care valoarea

INCHIRIAT_TAXA depăşeşte media.

Cuvântul cheie DISTINCT elimină tranzacţiile duplicate.

• Rezultatele interogării anterioare ar fi mai utile pentru proprietarul magazinului

dacă ar include şi data tranzacţiei. O modalitate de a realiza acest lucru este şi

adăugăm o uniune cu tabelul CLIENT_TRANZACTIE în interogarea externă.

Totuşi, deoarece tocmai aţi învăţat despre subinterogari, să facem acelaşi lucru

folosind încă o subinterogare. Iată cum arată interogarea:

SELECT TRANZACTIE_ID, TRANZACTIE_DATA AS TRANZ_DATA

FROM CLIENT_TRANZACTIE

WHERE TRANZACTIE_ID IN

(SELECT DISTINCT TRANZACTIE_ID FROM FILM_INCH,

WHERE INCH_TAXA > (SELECT AVG ( INCHIRIAT_TAXA)

FROM FILM_INCHIRIAT)

TRANZACTIE_ID TRANZ_DATA

9 03/01/2005

10 03/01/2005

Exemplu(din galeria de arta):

a) Să se afişeze titlul, codul artistului şi valoarea operelor create de artistul

căruia îi aparţine opera având codul 180 şi care se află expuse în aceeaşi galerie cu

operele al căror cod este 100 sau 110. Se presupune că o operă are un singur autor.

SELECT titlu, cod_artist, valoare

FROM opera

WHERE cod_artist = (SELECT cod_artist

Page 311: CURS BD Combinat

FROM opera

WHERE cod_opera = 180)

AND cod_galerie IN (SELECT cod_galerie

FROM opera

WHERE cod_opera IN (100, 110));

b) Să se determine artistul pentru care valoare medie a operelor sale de artă

este minimă.

SELECT cod_artist, AVG(valoare)

FROM opera

GROUP BY cod_artist

HAVING AVG(valoare) = (SELECT MIN(AVG(valoare))

FROM opera

GROUP BY cod_artist);

c) Pentru fiecare artist, să se afişeze titlul şi valoarea celei mai ieftine opere

de artă expuse în muzeu.

SELECT titlu, cod_artist, valoare

FROM opera

WHERE valoare IN (SELECT MIN(valoare)

FROM opera

GROUP BY cod_artist);

d) Să se afişeze operele de artă care nu sunt expuse în galeria având codul

30 şi a căror valoare este mai mică decât a unei opere din galeria 30.

SELECT cod_opera, titlu, valoare

FROM opera

WHERE valoare < ANY (SELECT valoare

FROM opera

WHERE cod_galerie = 30)

AND cod_galerie <> 30;

Dacă operatorul ANY se înlocuieşte cu operatorul ALL, cererea precedentă

returnează operele care nu sunt expuse în galeria 30 şi a căror valoare este mai

mică decât a oricărei opere din galeria respectivă.

e) Să se afişeze cele mai scumpe 3 opere de artă din muzeu.

SELECT ROWNUM "Nr.Crt", titlu, valoare

FROM (SELECT titlu, valoare

FROM opera

ORDER BY valoare DESC)

Page 312: CURS BD Combinat

WHERE ROWNUM <= 3;

Exemplu:

Din punct de vedere logic, următoarea cerere ar trebui să returneze titlurile

operelor care nu sunt expuse în galeriile unde se află lucrările artistului având

codul 60.

SELECT titlu

FROM opera

WHERE cod_galerie NOT IN (SELECT cod_galerie

FROM opera

WHERE cod_artist = 60);

Dacă pentru una dintre opere valoarea coloanei cod_galerie este null,

întreaga cerere nu va returna nici o linie, chiar dacă există înregistrări cu

proprietatea cerută. Justificarea este că toate condiţiile în care unul dintre operanzi

este null au, de asemenea, valoarea null. Prin urmare, ori de câte ori este posibil ca

în rezultatul subcererii să apară valori null, nu trebuie folosit operatorul NOT IN.

Operatorul NOT IN este echivalent cu <>ALL. Dacă se utilizează operatorul IN, nu

mai este nici o problemă dacă în rezultatul subcererii apar valori null. Operatorul

IN este echivalent cu =ANY.

Exemplu: Să se afişeze titlurile operelor care sunt expuse în galeriile unde se află

lucrările artistului având codul 60.

SELECT titlu FROM opera

WHERE cod_galerie IN (SELECT cod_galerie

FROM opera WHERE cod_artist = 60);

Pentru a evita obţinerea de valori null în rezultatul unei cereri care utilizează

operatorul NOT IN, se poate specifica o condiţie în subcerere:

SELECT titlu

FROM opera

WHERE cod_galerie NOT IN (SELECT cod_galerie FROM opera

WHERE cod_artist = 60

AND cod_galerie IS NOT NULL);

Page 313: CURS BD Combinat

Subcereri (Subinterogări) corelate (incuibarite sau sincronizate)

O subinterogare corelată (correlated subselect) este o subinterogare în care

interogarea internă referă valorile furnizate de interogarea externă.

Subcererile corelate sunt utilizate pentru procesarea linie cu linie a

interogărilor. O subcerere este corelată dacă face referinţă la o coloană dintr-un

tabel specificat în instrucţiunea „părinte“. O astfel de subcerere este evaluată o dată

pentru fiecare linie procesată de instrucţiunea „părinte“, care poate fi SELECT,

UPDATE sau DELETE.

Subcererile corelate permit compararea valorilor unei linii cu date

determinate pe baza acestor valori.

Cererile corelate se execută astfel:

cererea externă determină o linie candidat;

cererea internă este executată utilizând valoarea liniei candidat;

valorile rezultate din cererea internă sunt utilizate pentru calificarea sau

descalificarea liniei candidat;

paşii precedenţi se repetă până când nu mai există linii candidat.

Forma generală a unei subcereri corelate este următoarea:

SELECT nume_coloană_1[, nume_coloană_2 …]

FROM nume_tabel_1 extern

WHERE expresie operator

(SELECT nume_coloană_1 [, nume_coloană_2 …]

FROM nume_tabel_2

WHERE expresie_1 = extern.expresie_2);

Exemplu:

Proprietarul magazinului vrea să transmită prin poştă un cupon valoric

tuturor clienţilor care au plătit mai mult de 15$ pentru o singură tranzacţie de

închiriere.

SELECT DISTINCT CLIENT_CONT_ID

FROM CLIENT_TRANZACTIE A

WHERE 15 < (SELECT SUM (INCHIRIAT_TAXA)

FROM FILM_INCHIRIATB

WHERE A.TRANZACTIE _ID = B.TRANZACTIE_ID)

CLIENT_CONT_ID

Page 314: CURS BD Combinat

2

7

9

Observaţi pseudonimele asociate numelor de tabele din interogările internă

şi externă, precurn şi folosirea acestora în clauza WHERE a interogării interne.

Acesta este elementul de identificare al unei subinterogări corelate. Interogarea

externă selectează o lista de valori CLIENT_CONT_ID distincte din tabelul

CLIENT_TRANZACTIE. Fiecare valoare găsită este transmisă interogării interne,

care este rulată pentru a calcula suma taxelor de închiriere din tranzacţia

respectivă. Dacă suma taxelor de închiriere este mai mare sau egală cu 15, atunci

clauza WHERE din interogarea externă ia valoarea logică „adevărat", iar rândul

CLIENT_ID este adăugat în setul de rezultate.

Vizualizări în linie

Foarte puţine implementări, printre care Oracle, permit folosirea unei subinterogări

în clauza FROM a unei interogări, într-o construcţie numită vizualizare în linie

(inline view). Această construcţie permite care setul de rezultate al unei interogări

să fie tratat ca şi cum ar fi un tabel sau o vizualizare predefinită. Iată un exemplu:

• Această interogare află numărul maxim de închirieri ale unui singur film;

SELECT MAX(INCHIRIAT_NUMAR) AS MAX_INCHIRIAT_NUMAR

FROM (SELECT FILM_ID, NUMAR(*) AS INCHIRIAT_NUMAR

FROM FILM_INCHIRIAT GROUP BY FILM_ID)

MAX_INCH_NUMAR

5

Interogarea internă calculează numărul de închirieri pentru fiecare valoare

FILM_ID. Interogarea externă selectează valoarea maximă INCHIRIAT_NUMAR

din interogarea internă, tratată ca şi cum ar fi o vizualizare predefinită. Nu există

nici o limită în privinţa modurilor de utilizare a vizualizărilor în linie - puteţi chiar

să le uniţi cu alte tabele sau vizualizări.

Exemplu de subcereri corelate pentru galeria de arta):

a) Să se afişeze informaţii despre operele de artă a căror valoare depăşeşte

valoarea medie a celor expuse în aceeaşi galerie.

Page 315: CURS BD Combinat

SELECT titlu, valoare, cod_galerie

FROM opera o

WHERE valoare > (SELECT AVG(valoare)

FROM opera

WHERE cod_galerie = o.cod_galerie);

b) Să se afişeze codul, numele şi prenumele artiştilor care au cel puţin două

opere de artă expuse în muzeu.

SELECT cod_artist, nume, prenume

FROM artist a

WHERE 2 <= (SELECT COUNT(*)

FROM opera

WHERE cod_artist = a.cod_artist);

Server-ul Oracle evaluează subcererea corelată precedentă urmând

succesiunea de paşi prezentată în continuare.

1) Selectează o linie din tabelul specificat în cererea externă (aceasta va fi

linia candidat curentă).

2) Reţine valoarea coloanei referite în subcerere din această linie candidat

(în cazul subcererii de mai sus, coloana referită în subcerere este

a.cod_artist).

3) Efectuează subcererea, considerând condiţia acesteia ca facând referinţă

la valoarea liniei candidat din cererea externă (în exemplul precedent,

funcţia COUNT(*) este evaluată pe baza valorii lui a.cod_artist

determinată la pasul 2).

4) Evaluează clauza WHERE a cererii externe pe baza rezultatelor returnate

de cererea internă la pasul 3. Adică, se determină dacă linia candidat este

selectată în rezultatul cererii (în exemplul precedent, numărul de opere

ale unui artist, evaluat de subcerere, este comparat cu 2 în clauza WHERE

a cererii externe, iar dacă această condiţie este satisfăcută, linia

corespunzătoare artistului respectiv va face parte din rezultat).

5) Procedura se repetă pentru următoarele linii candidat din tabel, până când

sunt procesate toate liniile tabelului.

Operatorul EXISTS

În instrucţiunile SELECT imbricate, este permisă utilizarea oricărui operator

logic. Pentru a testa dacă valoarea recuperată de cererea externă există în mulţimea

valorilor regăsite de cererea internă corelată, se poate utiliza operatorul EXISTS.

Dacă subcererea returnează cel puţin o linie, operatorul returnează valoarea TRUE.

În caz contrar, va fi returnată valoarea FALSE.

Page 316: CURS BD Combinat

Operatorul EXISTS asigură că nu mai este continuată căutarea în cererea

internă după ce aceasta regăseşte o linie.

Exemplu: a) Să se determine codul, numele şi prenumele artiştilor care au cel puţin o

operă de artă expusă în muzeu.

SELECT cod_artist, nume, prenume FROM artist a WHERE EXISTS (SELECT 'x' FROM opera WHERE cod_artist = a.cod_artist);

Întrucât nu este necesar ca instrucţiunea SELECT interioară să returneze o anumită valoare, se poate selecta o constantă. De altfel, din punct de vedere al performanţei, selectarea unei constante asigură mai multă rapiditate decât selectarea unei coloane.

Ca alternativă a lui EXISTS, poate fi utilizat operatorul IN. Exemplul precedent poate fi rezolvat prin instrucţiunea următoare:

SELECT cod_artist, nume, prenume FROM artist WHERE cod_artist IN (SELECT cod_artist FROM opera);

b) Să se determine operele care nu sunt menţionate în nici o sursă bibliografică.

SELECT cod_opera, titlu FROM opera o WHERE NOT EXISTS (SELECT 'x' FROM mentionata_in

WHERE cod_opera = o.cod_opera);

Acest exemplu poate fi rezolvat şi printr-o subcerere necorelată, utilizând

operatorul NOT IN:

SELECT cod_opera, titlu

FROM opera

WHERE cod_opera NOT IN (SELECT cod_opera

FROM ment_in

WHERE cod_opera IS NOT NULL);

Page 317: CURS BD Combinat

Clauza WITH

Cu ajutorul clauzei WITH se poate defini un bloc de cerere înainte ca acesta să fie utilizat într-o interogare. Clauza permite reutilizarea aceluiaşi bloc de cerere într-o instrucţiune SELECT complexă. Acest lucru este util atunci când o cerere face referinţă de mai multe ori la acelaşi bloc de cerere, care conţine operaţii join şi funcţii agregat. Folosind clauza WITH, server-ul Oracle regăseşte rezultatele unui bloc de cerere şi le stochează în spaţiul tabel temporar al utilizatorului, ceea ce poate determina îmbunătăţirea performanţelor.

Exemplu: Utilizând clauza WITH, să se scrie o cerere care afişează numele artiştilor şi

valoarea totală a operelor acestora. Se vor considera artiştii a căror valoare totală a operelor este mai mare decât media valorilor totale ale operelor tuturor artiştilor.

WITH val_artist AS (SELECT nume, SUM(valoare) AS total FROM opera o, artist a WHERE o.cod_artist = a.cod_artist GROUP BY nume), val_medie AS (SELECT SUM(total)/COUNT(*) AS medie FROM val_artist) SELECT * FROM val_artist WHERE total > (SELECT medie FROM val_medie) ORDER BY nume;

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 stocării temporare a rezultatelor clauzei WITH.

Observaţii:

Clauza WITH poate fi folosită numai pentru instrucţiuni SELECT.

Un nume de cerere este vizibil tuturor blocurilor din clauza WITH definite ulterior (inclusiv subcererilor acestora). De asemenea, un nume de cerere este vizibil cererii principale şi subcererilor acesteia.

Când un nume de cerere coincide cu numele unui tabel, numele blocului de cerere are precedenţă asupra numelui tabelului.

Clauza WITH poate conţine mai mult decât o singură cerere. În acest caz, cererile sunt separate prin virgule.

Page 318: CURS BD Combinat

2.4.4. Funcţii grup şi clauza GROUP BY Clauza GROUP BY este utilizată pentru a diviza liniile unui tabel în grupuri.

Pentru a returna informaţia corespunzătoare fiecărui astfel de grup, pot fi utilizate funcţiile agregat. Ele pot apărea în clauzele SELECT, ORDER BY şi HAVING. Server-ul Oracle aplică aceste funcţii fiecărui grup de linii şi returnează un singur rezultat pentru fiecare mulţime.

Dintre funcţiile grup definite în sistemul Oracle, se pot enumera: AVG,

SUM, MAX, MIN, COUNT, STDDEV, VARIANCE, DENSE_RANK, RANK, FIRST,

LAST, GROUP_ID, GROUPING, GROUPING_ID etc. Tipurile de date ale

argumentelor funcţiilor grup pot fi CHAR, VARCHAR2, NUMBER sau DATE.

Funcţiile AVG, SUM, STDDEV şi VARIANCE operează numai asupra valorilor

numerice. Funcţiile MAX şi MIN pot opera asupra valorilor numerice, caracter sau

de tip dată calendaristică.

Toate funcţiile grup, cu excepţia lui COUNT(*), ignoră valorile null.

COUNT(expresie) returnează numărul de linii pentru care expresia dată nu are

valoarea null. Funcţia COUNT returnează un număr mai mare sau egal cu zero şi

nu întoarce niciodată valoarea null.

Când este utilizată clauza GROUP BY, server-ul sortează implicit mulţimea

rezultată în ordinea crescătoare a valorilor coloanelor după care se realizează

gruparea.

În clauza GROUP BY a unei cereri se pot utiliza operatorii ROLLUP şi

CUBE. Aceştia sunt disponibili începând cu versiunea Oracle8i.

Operatorul ROLLUP

Operatorul ROLLUP produce o mulţime care conţine liniile obţinute în urma

grupării obişnuite şi linii pentru subtotaluri. Acest operator furnizează valori

agregat şi superagregat corespunzătoare expresiilor din clauza GROUP BY.

Operatorul ROLLUP poate fi folosit pentru extragerea de statistici şi informaţii

totalizatoare din mulţimile rezultate. Acest operator poate fi util la generarea de

rapoarte, diagrame şi grafice.

Operatorul ROLLUP creează grupări prin deplasarea într-o singură direcţie,

de la dreapta la stânga, de-a lungul listei de coloane specificate în clauza GROUP

BY. Apoi, se aplică funcţia agregat acestor grupări. Dacă sunt specificate n expresii

în operatorul ROLLUP, numărul de grupări generate va fi n + 1. Liniile care se

bazează pe valoarea primelor n expresii se numesc linii obişnuite, iar celelalte se

numesc linii superagregat.

Dacă în clauza GROUP BY sunt specificate n coloane, pentru a produce

subtotaluri fără operatorul ROLLUP ar fi necesare n + 1 instrucţiuni SELECT

Page 319: CURS BD Combinat

conectate prin UNION ALL. Aceasta ar face execuţia cererii ineficientă deoarece

fiecare instrucţiune SELECT determină accesarea tabelului. Operatorul ROLLUP

determină rezultatele efectuând un singur acces la tabel şi este util atunci când sunt

implicate multe coloane în producerea subtotalurilor.

Exemplu:

Să se afişeze codurile de galerii mai mici decât 50, iar pentru fiecare dintre

acestea şi pentru fiecare autor care are opere expuse în galerie, să se listeze

valoarea totală a lucrărilor sale. De asemenea, se cere valoarea totală a operelor

expuse în fiecare galerie. Rezultatul va conţine şi valoarea totală a operelor din

galeriile având codul mai mic decât 50, indiferent de codul autorului.

SELECT cod_galerie, cod_artist, SUM(valoare)

FROM opera

WHERE cod_galerie < 50

GROUP BY ROLLUP(cod_galerie, cod_artist);

Instrucţiunea precedentă va avea un rezultat de forma:

COD_GALERIE COD_ARTIST SUM(VALOARE)

10 50 14000

10 60 10000

10 24000

40 50 8080

40 8080

32080

În rezultatul prezentat anterior se pot distinge 3 tipuri de linii. 1) Prima linie reprezintă suma operelor artistului care are codul 50, expuse

în galeria având codul 10. În mod similar se interpretează a doua şi a patra linie din rezultat.

2) Linia a treia şi a cincea din rezultat conţin valoarea totală a operelor din galeria al cărei cod este 10, respectiv 40. Aceste linii se disting prin faptul că valoarea coloanei cod_artist este null.

3) Ultima linie conţine suma valorilor tuturor operelor din galeriile al căror cod este 10 sau 40. Valoarea afişată este obţinută prin însumarea valorilor de pe a treia, respectiv a cincea linie. Întrucât această linie corespunde totalului general, ea conţine valoarea null pe toate coloanele, cu excepţia

Page 320: CURS BD Combinat

câmpului SUM(valoare).

Operatorul CUBE

Operatorul CUBE grupează liniile selectate pe baza valorilor tuturor combinaţiilor posibile ale expresiilor specificate şi returnează câte o linie totalizatoare pentru fiecare grup. Acest operator este folosit pentru a produce mulţimi de rezultate care sunt utilizate în rapoarte. În vreme ce ROLLUP produce subtotalurile doar pentru o parte dintre combinaţiile posibile, operatorul CUBE produce subtotaluri pentru toate combinaţiile posibile de grupări specificate în clauza GROUP BY, precum şi un total general.

Dacă există n coloane sau expresii în clauza GROUP BY, vor exista 2n

combinaţii posibile superagregat. Din punct de vedere matematic, aceste combinaţii formează un cub n-dimensional, de aici provenind numele operatorului. Pentru producerea de subtotaluri fără ajutorul operatorului CUBE ar fi necesare 2

n

instrucţiuni SELECT conectate prin UNION ALL.

Exemplu:

Să se afişeze valoarea totală a operelor de artă ale unui autor, expuse în

cadrul fiecărei galerii având codul mai mic decât 50. De asemenea, să se afişeze valoarea totală a operelor din fiecare galerie având codul mai mic decât 50, valoarea totală a operelor fiecărui autor indiferent de galerie şi valoarea totală a operelor din galeriile având codul mai mic decât 50.

SELECT cod_galerie, cod_artist, SUM(valoare)

FROM opera

WHERE cod_galerie < 50

GROUP BY CUBE(cod_galerie, cod_artist);

Instrucţiunea precedentă va genera un rezultat de forma următoare:

COD_GALERIE COD_ARTIST SUM(VALOARE)

10 50 14000

10 60 10000

10 24000

40 50 8080

40 8080

50 22080

60 10000

Page 321: CURS BD Combinat

32080

În plus faţă de rezultatul corespunzător operaţiei ROLLUP, operatorul CUBE

a produs linii care reprezintă suma valorilor operelor pentru fiecare artist care a

expus în galerii având codul mai mic decât 50. Aceste linii se disting prin faptul că

valoarea coloanei cod_galerie este null.

Funcţia GROUPING

Funcţia GROUPING poate fi utilizată alături de operatorii CUBE şi

ROLLUP pentru a arăta modul cum a fost obţinută o valoare totalizatoare. Această

funcţie acceptă un singur argument, care trebuie să fie una dintre expresiile

specificate în clauza GROUP BY.

O valoare null a expresiei din argumentul funcţiei GROUPING poate

proveni din tabelul de bază (valoare null stocată) sau poate fi o valoare null creată

de operaţia ROLLUP sau CUBE ca rezultat al unei funcţii grup asupra expresiei

respective.

Funcţia GROUPING returnează valoarea 0 sau 1. Valoarea 0 returnată de

funcţia GROUPING pe baza unei expresii poate indica fie că expresia a fost

utilizată pentru calculul valorii agregat, fie că valoarea null a expresiei este o

valoare null stocată. Valoarea 1 returnată de funcţia GROUPING pe baza unei

expresii poate indica fie că expresia nu a fost utilizată pentru calculul valorii

agregat, fie că valoarea null a expresiei este creată de ROLLUP sau CUBE ca

rezultat al grupării.

Valorile returnate de funcţia GROUPING sunt utile pentru:

determinarea nivelului de agregare al unui subtotal dat, adică a grupului sau grupurilor pe care se bazează subtotalul respectiv;

identificarea provenienţei unei valori null a unei expresii calculate, dintr-una din liniile mulţimii rezultat.

Exemplu:

SELECT cod_galerie, cod_artist, SUM(valoare), GROUPING(cod_galerie), GROUPING(cod_artist) FROM opera WHERE cod_galerie < 50 GROUP BY ROLLUP(cod_galerie, cod_artist);

COD_GALERIE COD_ARTIST SUM

(VALOARE) GROUPING

(COD_GALERIE) GROUPING

(COD_ARTIST)

10 50 14000 0 0

Page 322: CURS BD Combinat

10 60 10000 0 0

10 24000 0 1

40 50 8080 0 0

40 8080 0 1

32080 1 1

Pe prima linie din acest rezultat, valoarea totalizatoare reprezintă suma valorilor operelor artistului având codul 50, în cadrul galeriei 10. Pentru a calcula această valoare au fost luate în considerare coloanele cod_galerie şi cod_artist. Prin urmare, expresiile GROUPING(cod_galerie) şi GROUPING(cod_artist) au valoarea 0 pentru prima linie din rezultat.

Pe linia a treia se află valoarea totală a operelor din galeria având codul 10. Această valoare a fost calculată luând în considerare doar coloana cod_galerie, astfel încât GROUPING (cod_galerie) şi GROUPING(cod_artist) au valorile 0, respectiv 1.

Pe ultima linie din rezultat se află valoarea totală a operelor din galeriile având codul mai mic decât 50. Nici una dintre coloanele cod_galerie şi cod_artist nu au intervenit în calculul acestui total, prin urmare valorile corespunzătoare expresiilor GROUPING(cod_galerie) şi GROUPING(cod_artist) sunt 0.

Clauza GROUPING SETS

GROUPING SETS reprezintă o extensie a clauzei GROUP BY care permite specificarea unor grupări multiple de date. Utilizarea acestei opţiuni facilitează analiza datelor în mai multe dimensiuni.

Această extensie, apărută în sistemul Oracle9i, permite scrierea unei singure instrucţiuni SELECT pentru a specifica grupări diferite (care pot conţine operatorii ROLLUP şi CUBE), în loc de mai multe instrucţiuni SELECT combinate prin operatorul UNION ALL. De altfel, reuniunea rezultatelor mai multor cereri este ineficientă întrucât necesită mai multe parcurgeri ale aceloraşi date.

Operatorii ROLLUP şi CUBE pot fi consideraţi cazuri particulare de mulţimi

de grupări. Au loc următoarele echivalenţe:

CUBE(a, b, c) GROUPING SETS

((a, b, c), (a, b), (a, c), (b, c), (a),

(b), (c), ())

ROLLUP(a, b,

c)

GROUPING SETS

((a, b, c), (a, b), (a), ())

Exemplu:

Considerând galeriile al căror cod este mai mic decât 50, să se calculeze

media valorilor operelor:

Page 323: CURS BD Combinat

pentru fiecare galerie şi, în cadrul acesteia, pentru fiecare artist;

pentru fiecare artist şi, în cadrul acestuia, pentru anii de achiziţie

corespunzători.

SELECT cod_galerie, cod_artist, TO_CHAR(data_achizitiei, 'yyyy') "an achizitie", AVG(valoare) "Valoare medie" FROM opera WHERE cod_galerie < 50 GROUP BY GROUPING SETS ((cod_galerie, cod_artist), (cod_artist, TO_CHAR(data_achizitiei, 'yyyy')));

Mulţimea rezultat este constituită din valorile medii pentru fiecare dintre cele două grupuri şi are forma următoare:

COD_GALERIE COD_ARTIST an a Valoare medie

10 50 3500

10 60 2500

40 50 2020

50 2000 2380

50 2002 2300

60 2001 2000

60 2003 3000

Exemplul precedent poate fi rezolvat şi prin următoarea instrucţiune compusă:

SELECT cod_galerie, cod_artist, NULL "an achizitie", AVG(valoare) "Valoare medie" FROM opera GROUP BY cod_galerie, cod_artist UNION ALL SELECT NULL, cod_artist, TO_CHAR(data_achizitiei, 'yyyy'), AVG(valoare) FROM opera

GROUP BY cod_artist, TO_CHAR(data_achizitiei, 'yyyy');

În absenţa unui optimizor care analizează blocurile de cerere şi generează

planul de execuţie, cererea precedentă va parcurge de două ori tabelul de bază

(opera), ceea ce poate fi ineficient. Din acest motiv, este recomandată utilizarea

Page 324: CURS BD Combinat

extensiei GROUPING SETS.

Concatenarea grupărilor

Concatenarea grupărilor reprezintă o modalitate concisă de a genera

combinaţii de grupări. Acestea se specifică prin enumerarea mulţimilor de grupări

(grouping sets) şi a operaţiilor ROLLUP, CUBE separate prin virgulă. De exemplu,

expresia GROUP BY GROUPING SETS(a, b), GROUPING SETS(c, d) defineşte

grupările (a, c), (a, d), (b, c), (b, d).

Concatenarea mulţimilor de grupări este utilă atât pentru uşurinţa dezvoltării

cererilor, cât şi pentru aplicaţii. Codul SQL generat de aplicaţiile OLAP implică

deseori concatenarea mulţimilor de grupări, în care fiecare astfel de mulţime

defineşte grupările necesare pentru o dimensiune.

Exemplu:

Să se determine media valorilor operelor luând în considerare următoarele

grupări: (cod_galerie, cod_artist, an_achizitie), (cod_galerie, cod_artist),

(cod_galerie, an_achizitie), (cod_galerie).

SELECT cod_galerie, cod_artist,

TO_CHAR(data_achizitiei, 'yyyy') an_achizitie,

AVG(valoare)

FROM opera

GROUP BY cod_galerie, ROLLUP(cod_artist),

CUBE(TO_CHAR(data_achizitiei, 'yyyy'));

Page 325: CURS BD Combinat

PROBLEME-SUBCERERI

De cele mai multe ori, pentru a implementa anumite interogări, nu este

suficientă o singură cerere SELECT ci sunt necesare subcereri. Subcererile sunt

comenzi SELECT încapsulate în oricare din clauzele SELECT, WHERE, HAVING,

FROM.

Dacă subcererea urmează clauzei WHERE sau HAVING, ea poate conţine

unul dintre operatorii ALL, ANY, IN (=ANY), EXIST, NOT IN (!=ALL) care sunt

specifici cererilor care întorc mai multe linii (multiple-row subquery) sau unul

dintre operatorii de comparare (=, <, >, >=, <=, <>) care sunt specifici cererilor

care întorc o singură linie (single-row subquery).

Subcererile trebuie incluse între paranteze şi trebuie plasate în partea dreaptă

a operatorului de comparare. Subcererea nu poate conţine clauza ORDER BY.

Exemplu: Să se obţină numele salariaţilor, salariile, codul departamentului în care

lucrează şi salariul mediu pe departament pentru toţi angajaţii care au salariul mai mare ca media salariilor din departamentul în care lucrează (folosirea subcererii în clauza FROM).

SELECT a.nume, a.sal, a.cod_dep, b.salavg FROM angajati a, (SELECT dept ,avg(sal) salavg

FROM angajati GROUP BY cod_dep) b

WHERE a. cod_dep =b. cod_dep AND a.sal>b.salavg

Exemplu: Să se obţină lista celor mai scumpe cărţi.

SELECT titlu FROM carte WHERE pret = (SELECT MAX(pret)

FROM carte);

Exemplu: Să se obţină lista scriitorilor care au în bibliotecă un număr de exemplare mai mare decât numărul mediu al cărţilor din bibliotecă.

SELECT DISTINCT autor FROM carte

Page 326: CURS BD Combinat

WHERE nrex > (SELECT AVG(nrex) FROM carte);

Exemplu: Să se obţină informaţii despre cărţile al căror preţ depăşeşte media preţurilor cărţilor ce aparţin aceluiaşi domeniu

SELECT * FROM carte c WHERE pret > (SELECT AVG(pret)

FROM carte WHERE coded = c.coded);

Exemplu: Să se obţină lista cititorilor care au împrumutat cel puţin o carte.

SELECT nume FROM cititor WHERE codec IN (SELECT DISTINCT codec

FROM imprumuta);

Exemplu: Să se obţină codurile cititorilor care nu au împrumutat niciodată cărţi.

SELECT codec FROM cititor WHERE codec NOT IN (SELECT DISTINCT codec FROM imprumuta);

Exemplu: Să se obţină lista cititorilor care sunt în întârziere cu predarea cărţilor.

SELECT nume FROM cititor WHERE codec IN (SELECT DISTINCT codec

FROM imprumuta WHERE dataef IS NULL AND dares<SYSDATE);

Exemplu: Să se obţină numele cititorilor care au împrumutat cel puţin o carte scrisă de ZOLA.

SELECT nume FROM cititor WHERE codec IN

(SELECT DISTINCT codec

Page 327: CURS BD Combinat

FROM imprumuta WHERE codel IN

(SELECT codel FROM carte WHERE autor=‟ZOLA‟));

Exemplu: Să se obţină numele cititorilor care nu au împrumutat nici o carte scrisă de ZOLA.

SELECT nume FROM cititor WHERE codec NOT IN

(SELECT DISTINCT codec FROM imprumuta WHERE codel IN

(SELECT codel FROM carte

WHERE autor=‟ZOLA‟));

Operatorul IN poate fi înlocuit cu = ANY (un element este în listă dacă şi numai dacă este egal cu un element al listei), iar operatorul NOT IN poate fi înlocuit prin !=ALL.

Exemplu: Să se obţină codurile cititorilor care au împrumutat o carte de algebră.

SELECT DISTINCT codec FROM imprumuta WHERE codel IN (SELECT codel FROM carte WHERE coded= (SELECT coded FROM domeniu

WHERE intdom=‟ALGEBRA‟));

Exemplu: Să se obţină cititorii care au împrumutat numai cărţi scrise de „ZOLA‟.

SELECT nume FROM cititor WHERE codec NOT IN

(SELECT DISTINCT codec FROM imprumuta WHERE codel NOT IN

Page 328: CURS BD Combinat

(SELECT codel FROM carte WHERE autor=‟ZOLA‟));

Exemplu:

Să se obţină numele cititorilor care au împrumutat cel puţin o carte de

informatică (procedural).

SELECT nume FROM cititor WHERE codec IN (SELECT DISTINCT codec FROM imprumuta WHERE codel IN

(SELECT codel FROM carte WHERE coded=

(SELECT coded FROM domeniu WHERE intdom= ‟INFORMATICA‟)));

Exemplu: Să se obţină numele cititorilor şi titlurile cărţilor de informatică împrumutate de aceşti cititori (relational).

SELECT nume, titlu FROM cititor, carte, imprumuta, domeniu WHERE imprumuta.codel = carte.codel AND carte.coded = domeniu.coded AND imprumuta.codec = cititor.codec AND intdom = ‟INFORMATICA‟;

Subcererile pot fi executate corelat (cu sincronizare) sau încuibărit (fără

sincronizare).

Subcererile fără sincronizare sunt caracterizate de faptul că se execută

cererea cea mai interioară care întoarce un rezultat ce este transmis cererii de nivel

superior, care întoarce un rezultat s.a.m.d.

Subcererile cu sincronizare sunt caracterizate de faptul că evaluarea

subcererii face referinţă la o coloană a cererii principale, iar evaluarea cererii

interioare se face pentru fiecare linie a cererii (principale) care o conţine.

Page 329: CURS BD Combinat

Exemplu:

Să se obţină, utilizând sincronizarea subcererii cu cererea principală, titlurile

cărţilor care au toate exemplarele împrumutate (se selectează un titlu din carte şi

pentru acest titlu se numără câte exemplare sunt împrumutate).

SELECT titlu

FROM carte

WHERE nrex=(SELECT COUNT(*)

FROM imprumuta

WHERE codel = carte.codel

AND dataef IS NULL);

Exemplu:

Să se obţină codurile cititorilor şi codul ultimei cărţi împrumutate.

SELECT codec, codel

FROM imprumuta i

WHERE dataim>=ALL (SELECT dataim

FROM imprumuta

WHERE codec=i.codec);

Pentru această interogare, clauza WHERE putea fi scrisă şi sub forma:

WHERE dataim=(SELECT MAX(dataim)

FROM imprumuta

WHERE codec=i.codec);

Exemplu:

Să se obţină lista codurilor cărţilor împrumutate şi codul primului cititor care

a împrumutat aceste cărti.

SELECT codel,codec

FROM imprumuta i

WHERE dataim<=ALL (SELECT dataim

FROM imprumuta

WHERE i.codel=codel);

Exemplu:

Să se obţină codurile cărţilor din care cel puţin un exemplar este împrumutat.

SELECT codel

FROM carte

WHERE EXISTS

(SELECT codel

FROM imprumuta

Page 330: CURS BD Combinat

WHERE codel = carte.codel

AND dataef IS NULL);

Operatorul WHERE EXISTS (subcerere) presupune că predicatul este

adevărat dacă subcererea întoarce cel puţin un tuplu, iar WHERE NOT EXISTS

(subcerere) presupune că predicatul este adevărat dacă subcererea nu întoarce nici

un tuplu. EXISTS şi NOT EXISTS cer sincronizarea subcererii.

Exemplu:

Să se obţină titlurile cărţilor care sunt momentan împrumutate.

Soluţia 1 (cu sincronizare):

SELECT titlu

FROM carte

WHERE EXISTS

(SELECT *

FROM imprumuta

WHERE codel = carte.codel

AND dataef IS NULL);

Soluţia 2 (fără sincronizare):

SELECT titlu

FROM carte

WHERE codel IN

(SELECT DISTINCT codel

FROM imprumuta

WHERE dataef IS NULL);

Exemplu:

Să se obţină codurile cărţilor care nu au fost împrumutate niciodată.

Soluţia 1 (cu sincronizare) SELECT codel FROM carte WHERE NOT EXISTS

(SELECT codel FROM imprumuta WHERE codel = carte.codel);

Soluţia 2 (fără sincronizare)

SELECT codel FROM carte WHERE codel NOT IN

(SELECT DISTINCT codel

Page 331: CURS BD Combinat

FROM imprumuta);

Exemplu:

Să se obţină lista salariaţilor având salariul minim în departamentul în care

lucrează.

SELECT ename,sal

FROM emp e

WHERE sal=(SELECT MIN(sal)

FROM emp

WHERE deptno=e.deptno);

Exemplu:

Să se obţină numele primilor trei salariaţi având retribuţia maximă (ideea

rezolvării este de a verifica dacă numărul salariaţilor care au leafa mai mare decât

leafa salariatului considerat, este mai mic decât 3).

SELECT ename

FROM emp a

WHERE 3>(SELECT COUNT(*)

FROM emp

WHERE sal > a.sal);

Exemplu:

Să se obţină numele cititorilor care au împrumutat cel puţin aceleaşi cărţi ca

şi cititorul având codul C19 (ideea problemei este de a selecta cititorii pentru care

este vidă lista cărţilor împrumutatede C19 mai puţin lista cărţilor împrumutate de

acei cititori).

SELECT nume

FROM cititor

WHERE NOT EXISTS

(SELECT codel

FROM imprumuta

WHERE codec=‟C19‟

MINUS

SELECT codel

FROM imprumuta

WHERE codec= cititor.codec);

Dacă problema era modificată în sensul că „cel puţin”este înlocuit prin „cel

mult” atunci trebuiau inversate interogările legate prin MINUS.

Page 332: CURS BD Combinat

Exemplu: Să se obţină codurile cititorilor care au împrumutat aceleaşi cărţi ca şi

cititorul având un cod specificat.

Rezolvarea problemei se bazează pe ideea: A = B A B şi B A (A-

B) = şi (B-A) = A-B şi B-A nu furnizează nici un tuplu rezultat.

SELECT codec FROM imprumuta i WHERE NOT EXISTS

(SELECT codel FROM imprumuta WHERE codec=i.codec

MINUS SELECT codel FROM imprumuta WHERE codec=‟&ccc‟)

AND NOT EXISTS (SELECT codel FROM imprumuta WHERE codec=‟&ccc‟

MINUS SELECT codel FROM imprumuta WHERE codec=i.codec)

AND codec!=‟&ccc‟);

Ultimul operator (AND), asigură să nu apară în rezultat cititorul specificat.

În cazul formei relaţionale de rezolvare a cererii, drumul de acces la informaţie este în sarcina SGBD-lui şi prin urmare nu mai apar cereri imbricate.

Exemplu: Să se obţină numele cititorilor care au împrumutat cel puţin o carte.

Soluţia 1 (forma relaţională): SELECT DISTINCT nume FROM cititor,imprumuta WHERE cititor.codec=imprumuta.codec;

Soluţia 2 (forma procedurală): SELECT nume FROM cititor WHERE codec IN

(SELECT DISTINCT codec FROM imprumuta);

Page 333: CURS BD Combinat

Exemplu: Să se obţină numele cititorilor care au împrumutat cel puţin două cărţi.

Soluţia 1 (forma relaţională): SELECT nume FROM cititor, imprumuta WHERE cititor.codec=imprumuta.codec GROUP BY nume HAVING COUNT(*)>1;

Soluţia 2 (forma procedurală): SELECT nume FROM cititor WHERE codec IN

(SELECT codec FROM imprumuta GROUP BY codec HAVING COUNT(*)>1);

Exemplu:

Să se afişeze numele, prenumele, salariul lucrătorilor, codurile publicaţiilor

la care lucrează şi salariul mediu pe publicaţie pentru toţi angajaţii care au salariul

mai mare decât media salariului pe publicaţia respectivă.

SELECT s.nume, s.prenume, s.salariu,

p.nr_publicatie, a.salariu_mediu

FROM salariat s, publicatie p,

(SELECT p1.nr_publicatie,AVG(salariu) salariu_mediu

FROM publicatie p1, salariat s1

WHERE p1.cod_salariat = s1.cod_salariat

GROUP BY p1.nr_publicatie) a

WHERE p.nr_publicatie = a.nr_publicatie

AND s.cod_salariat = p.cod_salariat

AND s.salariu > a.salariu_mediu;

Exemplu: Să se obţină numele salariaţilor care nu cunosc nici o limbă străină.

SELECT nume, prenume FROM salariat WHERE NOT EXISTS (SELECT * FROM limba WHERE limba.cod_salariat = salariat.cod_salariat AND limba_cun IS NOT NULL);

Exemplu:

Page 334: CURS BD Combinat

Să se afişeze graficienii care au întârziat să predea frame-urile.

a) cu sincronizare:

SELECT nume, prenume

FROM salariat

WHERE EXISTS

(SELECT *

FROM realizeaza r

WHERE salariat.cod_salariat=r.cod_salariat

AND data_lim < SYSDATE);

b) fără sincronizare:

SELECT nume, prenume

FROM salariat

WHERE cod_salariat IN

(SELECT DISTINCT cod_salariat

FROM realizeaza

WHERE data_lim < SYSDATE);

Exemplu:

Să se determine revistele coordonate de redactori şefi care nu cunosc limba

în care sunt scrise. Se ştie că în urma inspectării vizuale a rezultatului interogării se

poate decide schimbarea redactorilor şefi ai revistelor respective, de aceea se

doreşte blocarea înregistrărilor găsite.

SELECT p.nr_publicatie

FROM salariat s, publicatie p

WHERE s.cod_salariat = p.cod_salariat

AND p.limba NOT IN

(SELECT limba_cun

FROM limba

WHERE limba.cod_salariat = s.cod_salariat)

FOR UPDATE OF p.cod_salariat;

Page 335: CURS BD Combinat

Subinterogări

O caracteristică foarte puternică a limbajului SQL sunt subinterogările

(numite şi selecţii), care, aşa cum sugerează şi numele, se referă la o instrucţiune

SELECT care conţine o instrucţiune SELECT subordonată.

De cele mai multe ori, pentru a implementa anumite interogări, nu este

suficientă o singură cerere SELECT ci sunt necesare subcereri.

Subcererile sunt comenzi SELECT încapsulate în oricare din clauzele ,

SELECT, WHERE, HAVING, FROM, numită instrucţiune „părinte“.

Dacă subcererea urmează clauzei WHERE sau HAVING, ea poate conţine

unul dintre operatorii ALL, ANY, IN (=ANY), EXIST, NOT IN (!=ALL) care sunt

specifici cererilor care întorc mai multe linii (multiple-row subquery) sau unul

dintre operatorii de comparare (=, <, >, >=, <=, <>) care sunt specifici cererilor

care întorc o singură linie (single-row subquery).

Utilizând subcereri, se pot construi interogări complexe pe baza unor

instrucţiuni simple. Subcererile mai sunt numite instrucţiuni SELECT imbricate

sau interioare.

Subcererea returnează o valoare care este utilizată de către instrucţiunea

„părinte“. Utilizarea unei subcereri este echivalentă cu efectuarea a două cereri

secvenţiale şi utilizarea rezultatului cererii interne ca valoare de căutare în cererea

externă (principală).

Subcererile pot fi utilizate în următoarele situaţii:

pentru a furniza valori care intervin în condiţiile din clauzele WHERE,

HAVING şi START WITH ale instrucţiunilor SELECT;

pentru a defini o mulţime de linii care urmează să fie inserată în tabelul

destinaţie al unei instrucţiuni INSERT sau CREATE TABLE;

pentru a defini o mulţime de linii care urmează să fie inserate într-o

vizualizare sau vizualizare materializată, prin intermediul unei

instrucţiuni CREATE VIEW sau CREATE MATERIALIZED VIEW;

pentru a defini una sau mai multe valori care urmează să fie atribuite unor

linii existente într-o instrucţiune UPDATE;

pentru a defini un tabel asupra căruia va opera cererea externă (plasarea

subcererii în clauza FROM sau în instrucţiunile INSERT, UPDATE,

DELETE).

Page 336: CURS BD Combinat

Subcererile trebuie incluse între paranteze şi trebuie plasate în partea dreaptă

a operatorului de comparare. Subcererea nu poate conţine clauza ORDER BY.

De obicei, subinterogările sunt folosite în clauza WHERE, ca modalitate de

limitare a rândurilor returnate în setul de rezultate al interogării externe. Aceasta

poate fi o modalitate foarte flexibilă de selectare a datelor.

O regulă esenţială de sintaxă este ca subinterogarea să fie încadrată de paranteze.

Orice operaţie efectuată cu o subinterogare poate fi făcută şi printr-o uniune.

Subinterogări necorelate

O subinterogare necorelată (noncorrelated subselect) este o subinterogare în

care interogarea internă nu face nici o referire la interogarea externă care o conţine.

Subcererile necorelate returnează o valoare care este utilizată de cererea

externă (cererea principală). Cererile care conţin subcereri necorelate sunt evaluate

în modul următor:

cererea internă este executată prima şi determină o valoare (sau o

mulţime de valori);

cererea externă se execută o singură dată, utilizând valorile returnate de

cererea internă.

În general, o cerere imbricată, necorelată are următoarea formă:

SELECT lista_select

FROM nume_tabel

WHERE expresie operator (SELECT lista_select

FROM nume_tabel);

În această sintaxă, identificatorul operator poate fi de tip:

single-row operator (>, =, >=, <, <>, <=), care poate fi utilizat dacă

subcererea returnează o singură linie;

multiple-row operator (IN, ANY, ALL), care poate fi folosit dacă

subcererea returnează mai mult de o linie.

Operatorul ANY, care este sinonim cu operatorul SOME, determină

compararea unei valori cu fiecare valoare returnată de o subcerere. Astfel, <ANY

are semnificaţia „mai mic decât maximul“; >ANY înseamnă „mai mare decât

minimul“; =ANY este echivalent cu operatorul IN. Operatorul ALL compară o

valoare cu toate valorile returnate de o subcerere. Astfel, <ALL are semnificaţia

„mai mic decât minimul“, iar >ALL este echivalent cu „mai mare decât maximul“.

Operatorul NOT poate fi utilizat în combinaţie cu IN, ANY şi ALL.

În utilizarea unei subcereri se impun anumite reguli.

Subcererea trebuie inclusă între paranteze.

Page 337: CURS BD Combinat

Pentru claritate, subcererea se plasează în partea dreaptă a operatorului de

comparaţie.

Înainte de versiunea Oracle8i, subcererile nu puteau să conţină clauza

ORDER BY. Începând cu Oracle8i, clauza ORDER BY poate fi utilizată şi

este chiar obligatorie în subcerere pentru a efectua analiza top-n (cererea

care efectuează analiza top-n returnează cele mai mari sau cele mai mici

n valori ale unei coloane).

Operatorul folosit trebuie să fie conform cu tipul cererii. Cererea va

genera o eroare dacă este utilizat un operator single-row în faţa unei

subcereri care returnează mai mult de o linie. De asemenea, dacă

subcererea nu returnează nici o linie, apare o eroare.

Server-ul Oracle nu impune nici o limită asupra numărului de subcereri.

Limita acestora depinde de dimensiunea buffer-ului pe care îl utilizează cererea.

Exemple:

• Afişaţi toate limbile în care nu există nici un film în inventarul magazinului de

produse video.

SELECT LIMBA_COD, LIMBA_NUME

FROM LIMBA

WHERE LIMBA_COD NOT IN

(SELECT DISTINCT LIMBA_COD

FROM FILM_LIMBA)

ORDER BY LIMBA_COD

LIMBA_COD LIMBA_NUME

Ja Japoneza

Ko Coreana

ni Olandeza

ru Rusa

zh Chineza

Interogarea internă returnează o listă cu codurile de limbă asociate filmelor în

tabelul FILM_LIMBA. Cuvântul cheie DISTINCT elimină rândurile duplicate din

setul de rezultate .

Interogarea internă rulată independent, pentru a vă ajuta să înţelegeţi cum

funcţionează:

Page 338: CURS BD Combinat

SELECT DISTINCT LIMBA_COD FROM FILM_LIMBA;

LIMBA_COD

-------------------------------------------

de (Germana)

en (Engleza)

es (Spaniola)

f r (Franceza)

• Proprietarul magazinului vrea să vadă efectul recentei creşteri de preţuri şi are

nevoie de o listă a tranzacţiilor (TRANZACTIE_ID) în care clientul a plătit mai

mult decât taxa medie (INCHIRIAT_TAXA) pentru un film. Iată cum arată

interogarea:

SELECT DISTINCT TRANZACTIE_ID

FROM FILM_INCHIRIAT

WHERE INCHIRIAT_TAXA>

(SELECT AVG(INCHIRIAT_TAXA) FROM FILM_INCHIRIAT)

Interogarea internă calculează media taxelor de închiriere, iar interogarea externă

găseşte apoi toate rândurile din tabelul FILM_INCHIRIAT pentru care valoarea

INCHIRIAT_TAXA depăşeşte media.

Cuvântul cheie DISTINCT elimină tranzacţiile duplicate.

• Rezultatele interogării anterioare ar fi mai utile pentru proprietarul magazinului

dacă ar include şi data tranzacţiei. O modalitate de a realiza acest lucru este şi

adăugăm o uniune cu tabelul CLIENT_TRANZACTIE în interogarea externă.

Totuşi, deoarece tocmai aţi învăţat despre subinterogari, să facem acelaşi lucru

folosind încă o subinterogare. Iată cum arată interogarea:

SELECT TRANZACTIE_ID, TRANZACTIE_DATA AS TRANZ_DATA

FROM CLIENT_TRANZACTIE

WHERE TRANZACTIE_ID IN

(SELECT DISTINCT TRANZACTIE_ID FROM FILM_INCH,

WHERE INCH_TAXA > (SELECT AVG ( INCHIRIAT_TAXA)

FROM FILM_INCHIRIAT)

TRANZACTIE_ID TRANZ_DATA

9 03/01/2005

10 03/01/2005

Page 339: CURS BD Combinat

Exemplu(din galeria de arta):

a) Să se afişeze titlul, codul artistului şi valoarea operelor create de artistul

căruia îi aparţine opera având codul 180 şi care se află expuse în aceeaşi galerie cu

operele al căror cod este 100 sau 110. Se presupune că o operă are un singur autor.

SELECT titlu, cod_artist, valoare

FROM opera

WHERE cod_artist = (SELECT cod_artist

FROM opera

WHERE cod_opera = 180)

AND cod_galerie IN (SELECT cod_galerie

FROM opera

WHERE cod_opera IN (100, 110));

b) Să se determine artistul pentru care valoare medie a operelor sale de artă

este minimă.

SELECT cod_artist, AVG(valoare)

FROM opera

GROUP BY cod_artist

HAVING AVG(valoare) = (SELECT MIN(AVG(valoare))

FROM opera

GROUP BY cod_artist);

c) Pentru fiecare artist, să se afişeze titlul şi valoarea celei mai ieftine opere

de artă expuse în muzeu.

SELECT titlu, cod_artist, valoare

FROM opera

WHERE valoare IN (SELECT MIN(valoare)

FROM opera

GROUP BY cod_artist);

d) Să se afişeze operele de artă care nu sunt expuse în galeria având codul

30 şi a căror valoare este mai mică decât a unei opere din galeria 30.

SELECT cod_opera, titlu, valoare

FROM opera

WHERE valoare < ANY (SELECT valoare

FROM opera

WHERE cod_galerie = 30)

AND cod_galerie <> 30;

Dacă operatorul ANY se înlocuieşte cu operatorul ALL, cererea precedentă

Page 340: CURS BD Combinat

returnează operele care nu sunt expuse în galeria 30 şi a căror valoare este mai

mică decât a oricărei opere din galeria respectivă.

e) Să se afişeze cele mai scumpe 3 opere de artă din muzeu.

SELECT ROWNUM "Nr.Crt", titlu, valoare

FROM (SELECT titlu, valoare

FROM opera

ORDER BY valoare DESC)

WHERE ROWNUM <= 3;

Exemplu:

Din punct de vedere logic, următoarea cerere ar trebui să returneze titlurile

operelor care nu sunt expuse în galeriile unde se află lucrările artistului având

codul 60.

SELECT titlu

FROM opera

WHERE cod_galerie NOT IN (SELECT cod_galerie

FROM opera

WHERE cod_artist = 60);

Dacă pentru una dintre opere valoarea coloanei cod_galerie este null,

întreaga cerere nu va returna nici o linie, chiar dacă există înregistrări cu

proprietatea cerută. Justificarea este că toate condiţiile în care unul dintre operanzi

este null au, de asemenea, valoarea null. Prin urmare, ori de câte ori este posibil ca

în rezultatul subcererii să apară valori null, nu trebuie folosit operatorul NOT IN.

Operatorul NOT IN este echivalent cu <>ALL. Dacă se utilizează operatorul IN, nu

mai este nici o problemă dacă în rezultatul subcererii apar valori null. Operatorul

IN este echivalent cu =ANY.

Exemplu:

Să se afişeze titlurile operelor care sunt expuse în galeriile unde se află lucrările artistului având codul 60.

SELECT titlu

FROM opera WHERE cod_galerie IN (SELECT cod_galerie

FROM opera

WHERE cod_artist = 60);

Pentru a evita obţinerea de valori null în rezultatul unei cereri care utilizează

operatorul NOT IN, se poate specifica o condiţie în subcerere:

SELECT titlu FROM opera

Page 341: CURS BD Combinat

WHERE cod_galerie NOT IN (SELECT cod_galerie

FROM opera WHERE cod_artist = 60

AND cod_galerie IS NOT NULL);

Subcereri (Subinterogări) corelate

O subinterogare corelată (correlated subselect) este o subinterogare în care

interogarea internă referă valorile furnizate de interogarea externă.

Subcererile corelate sunt utilizate pentru procesarea linie cu linie a

interogărilor. O subcerere este corelată dacă face referinţă la o coloană dintr-un

tabel specificat în instrucţiunea „părinte“. O astfel de subcerere este evaluată o dată

pentru fiecare linie procesată de instrucţiunea „părinte“, care poate fi SELECT,

UPDATE sau DELETE.

Subcererile corelate permit compararea valorilor unei linii cu date

determinate pe baza acestor valori.

Cererile corelate se execută astfel:

cererea externă determină o linie candidat;

cererea internă este executată utilizând valoarea liniei candidat;

valorile rezultate din cererea internă sunt utilizate pentru calificarea sau

descalificarea liniei candidat;

paşii precedenţi se repetă până când nu mai există linii candidat.

Forma generală a unei subcereri corelate este următoarea:

SELECT nume_coloană_1[, nume_coloană_2 …]

FROM nume_tabel_1 extern

WHERE expresie operator

(SELECT nume_coloană_1 [, nume_coloană_2 …]

FROM nume_tabel_2

WHERE expresie_1 = extern.expresie_2);

Exemplu:

Proprietarul magazinului vrea să transmită prin poştă un cupon valoric

tuturor clienţilor care au plătit mai mult de 15$ pentru o singură tranzacţie de

închiriere.

SELECT DISTINCT CLIENT_CONT_ID

Page 342: CURS BD Combinat

FROM CLIENT_TRANZACTIE A

WHERE 15 < (SELECT SUM (INCHIRIAT_TAXA)

FROM FILM_INCHIRIATB

WHERE A.TRANZACTIE _ID = B.TRANZACTIE_ID)

CLIENT_CONT_ID

2

7

9

Observaţi pseudonimele asociate numelor de tabele din interogările internă

şi externă, precurn şi folosirea acestora în clauza WHERE a interogării interne.

Acesta este elementul de identificare al unei subinterogări corelate. Interogarea

externă selectează o lista de valori CLIENT_CONT_ID distincte din tabelul

CLIENT_TRANZACTIE. Fiecare valoare găsită este transmisă interogării interne,

care este rulată pentru a calcula suma taxelor de închiriere din tranzacţia

respectivă. Dacă suma taxelor de închiriere este mai mare sau egală cu 15, atunci

clauza WHERE din interogarea externă ia valoarea logică „adevărat", iar rândul

CLIENT_ID este adăugat în setul de rezultate.

Vizualizări în linie

Foarte puţine implementări, printre care Oracle, permit folosirea unei subinterogări

în clauza FROM a unei interogări, într-o construcţie numită vizualizare în linie

(inline view). Această construcţie permite care setul de rezultate al unei interogări

să fie tratat ca şi cum ar fi un tabel sau o vizualizare predefinită. Iată un exemplu:

• Această interogare află numărul maxim de închirieri ale unui singur film;

SELECT MAX(INCHIRIAT_NUMAR) AS MAX_INCHIRIAT_NUMAR

FROM (SELECT FILM_ID, NUMAR(*) AS INCHIRIAT_NUMAR

FROM FILM_INCHIRIAT GROUP BY FILM_ID)

MAX_INCH_NUMAR

5

Interogarea internă calculează numărul de închirieri pentru fiecare valoare

FILM_ID. Interogarea externă selectează valoarea maximă INCHIRIAT_NUMAR

din interogarea internă, tratată ca şi cum ar fi o vizualizare predefinită. Nu există

nici o limită în privinţa modurilor de utilizare a vizualizărilor în linie - puteţi chiar

să le uniţi cu alte tabele sau vizualizări.

Page 343: CURS BD Combinat

Exemplu de subcereri corelate pentru galeria de arta):

a) Să se afişeze informaţii despre operele de artă a căror valoare depăşeşte

valoarea medie a celor expuse în aceeaşi galerie.

SELECT titlu, valoare, cod_galerie

FROM opera o

WHERE valoare > (SELECT AVG(valoare)

FROM opera

WHERE cod_galerie = o.cod_galerie);

b) Să se afişeze codul, numele şi prenumele artiştilor care au cel puţin două

opere de artă expuse în muzeu.

SELECT cod_artist, nume, prenume

FROM artist a

WHERE 2 <= (SELECT COUNT(*)

FROM opera

WHERE cod_artist = a.cod_artist);

Server-ul Oracle evaluează subcererea corelată precedentă urmând

succesiunea de paşi prezentată în continuare.

1) Selectează o linie din tabelul specificat în cererea externă (aceasta va fi

linia candidat curentă).

2) Reţine valoarea coloanei referite în subcerere din această linie candidat

(în cazul subcererii de mai sus, coloana referită în subcerere este

a.cod_artist).

3) Efectuează subcererea, considerând condiţia acesteia ca facând referinţă

la valoarea liniei candidat din cererea externă (în exemplul precedent,

funcţia COUNT(*) este evaluată pe baza valorii lui a.cod_artist

determinată la pasul 2).

4) Evaluează clauza WHERE a cererii externe pe baza rezultatelor returnate

de cererea internă la pasul 3. Adică, se determină dacă linia candidat este

selectată în rezultatul cererii (în exemplul precedent, numărul de opere

ale unui artist, evaluat de subcerere, este comparat cu 2 în clauza WHERE

a cererii externe, iar dacă această condiţie este satisfăcută, linia

corespunzătoare artistului respectiv va face parte din rezultat).

5) Procedura se repetă pentru următoarele linii candidat din tabel, până când

sunt procesate toate liniile tabelului.

Page 344: CURS BD Combinat

Operatorul EXISTS

În instrucţiunile SELECT imbricate, este permisă utilizarea oricărui operator

logic. Pentru a testa dacă valoarea recuperată de cererea externă există în mulţimea

valorilor regăsite de cererea internă corelată, se poate utiliza operatorul EXISTS.

Dacă subcererea returnează cel puţin o linie, operatorul returnează valoarea TRUE.

În caz contrar, va fi returnată valoarea FALSE.

Operatorul EXISTS asigură că nu mai este continuată căutarea în cererea

internă după ce aceasta regăseşte o linie.

Exemplu: a) Să se determine codul, numele şi prenumele artiştilor care au cel puţin o

operă de artă expusă în muzeu.

SELECT cod_artist, nume, prenume FROM artist a WHERE EXISTS (SELECT 'x' FROM opera WHERE cod_artist = a.cod_artist);

Întrucât nu este necesar ca instrucţiunea SELECT interioară să returneze o anumită valoare, se poate selecta o constantă. De altfel, din punct de vedere al performanţei, selectarea unei constante asigură mai multă rapiditate decât selectarea unei coloane.

Ca alternativă a lui EXISTS, poate fi utilizat operatorul IN. Exemplul precedent poate fi rezolvat prin instrucţiunea următoare:

SELECT cod_artist, nume, prenume FROM artist WHERE cod_artist IN (SELECT cod_artist FROM opera);

b) Să se determine operele care nu sunt menţionate în nici o sursă bibliografică.

SELECT cod_opera, titlu FROM opera o WHERE NOT EXISTS (SELECT 'x' FROM mentionata_in

WHERE cod_opera = o.cod_opera);

Acest exemplu poate fi rezolvat şi printr-o subcerere necorelată, utilizând

operatorul NOT IN:

SELECT cod_opera, titlu

FROM opera

Page 345: CURS BD Combinat

WHERE cod_opera NOT IN (SELECT cod_opera

FROM ment_in

WHERE cod_opera IS NOT NULL);

Instrucţiuni LMD corelate

Subcererile corelate pot fi utilizate pentru actualizarea sau ştergerea de

înregistrări dintr-un tabel pe baza liniilor altui tabel. Forma generală a unei

instrucţiuni corelate UPDATE, respectiv DELETE, este următoarea:

UPDATE nume_tabel_1 alias_1

SET nume_coloană = (SELECT expresie

FROM nume_tabel_2 alias_2

WHERE alias_1.nume_coloană =

alias_2.nume_coloană);

DELETE FROM nume_tabel_1 alias_1

WHERE expresie operator

(SELECT expresie

FROM nume_tabel_2 alias_2

WHERE alias_1.nume_coloană =

alias_2.nume_coloană);

Exemplu:

Se presupune că valorile operelor sunt mărite cu 20% din costul ultimei

poliţe de asigurare încheiate. Să se actualizeze corespunzător valoarea operelor

care beneficiază de cel puţin o poliţă de asigurare.

UPDATE opera

SET valoare = (SELECT opera.valoare +

polita_asig.valoare*0.20

FROM polita_asig

WHERE cod_opera = opera.cod_opera

AND semnat_contract =

(SELECT MAX(semnat_contract)

FROM polita_asig

WHERE cod_opera = opera.cod_opera))

WHERE opera.cod_opera IN (SELECT DISTINCT cod_opera

FROM polita_asig);

Exemplu:

Pentru fiecare autor care are mai mult de 10 creaţii expuse în muzeu, să se

Page 346: CURS BD Combinat

şteargă ultima operă creată de acesta.

DELETE FROM opera o1 WHERE cod_artist = (SELECT cod_artist FROM opera o2 WHERE cod_artist = o1.cod_artist AND data_crearii = (SELECT MAX(data_crearii) FROM opera WHERE cod_artist = o2.cod_artist) AND 10 > (SELECT COUNT(*) FROM opera WHERE cod_artist = o2.cod_artist));

Clauza WITH

Cu ajutorul clauzei WITH se poate defini un bloc de cerere înainte ca acesta să fie utilizat într-o interogare. Clauza permite reutilizarea aceluiaşi bloc de cerere într-o instrucţiune SELECT complexă. Acest lucru este util atunci când o cerere face referinţă de mai multe ori la acelaşi bloc de cerere, care conţine operaţii join şi funcţii agregat. Folosind clauza WITH, server-ul Oracle regăseşte rezultatele unui bloc de cerere şi le stochează în spaţiul tabel temporar al utilizatorului, ceea ce poate determina îmbunătăţirea performanţelor.

Exemplu: Utilizând clauza WITH, să se scrie o cerere care afişează numele artiştilor şi

valoarea totală a operelor acestora. Se vor considera artiştii a căror valoare totală a operelor este mai mare decât media valorilor totale ale operelor tuturor artiştilor.

WITH val_artist AS (SELECT nume, SUM(valoare) AS total FROM opera o, artist a WHERE o.cod_artist = a.cod_artist GROUP BY nume), val_medie AS (SELECT SUM(total)/COUNT(*) AS medie FROM val_artist) SELECT * FROM val_artist WHERE total > (SELECT medie FROM val_medie) ORDER BY nume;

Intern, clauza WITH este tratată ca o vizualizare inline (subcerere în clauza

Page 347: CURS BD Combinat

FROM) sau ca un tabel temporar. Optimizorul alege decizia adecvată pe baza costului sau beneficiului stocării temporare a rezultatelor clauzei WITH.

Observaţii:

Clauza WITH poate fi folosită numai pentru instrucţiuni SELECT.

Un nume de cerere este vizibil tuturor blocurilor din clauza WITH definite ulterior (inclusiv subcererilor acestora). De asemenea, un nume de cerere este vizibil cererii principale şi subcererilor acesteia.

Când un nume de cerere coincide cu numele unui tabel, numele blocului de cerere are precedenţă asupra numelui tabelului.

Clauza WITH poate conţine mai mult decât o singură cerere. În acest caz, cererile sunt separate prin virgule.

Subcereri scalare

Subcererile scalare în SQL returnează valoarea unei singure coloane corespunzătoare unei linii. Dacă subcererea returnează 0 linii, valoarea subcererii scalare este null. Dacă subcererea returnează mai mult de o linie, server-ul generează o eroare.

Subcererile scalare erau acceptate în Oracle8i doar în anumite cazuri, cum ar fi clauzele FROM şi WHERE ale instrucţiunii SELECT sau clauza VALUES a instrucţiunii INSERT. Utilitatea subcererilor scalare a fost extinsă în Oracle9i. Astfel, ele pot apărea în:

condiţiile şi expresiile care fac parte din DECODE sau CASE;

toate clauzele instrucţiunii SELECT, cu excepţia lui GROUP BY;

în partea stângă a operatorului, în clauzele SET şi WHERE ale instrucţiunii UPDATE.

Subcererile scalare nu sunt permise în următoarele situaţii:

ca valori implicite pentru coloane sau ca expresii hash pentru grupări;

în clauza RETURNING a instrucţiunilor LMD;

în clauza GROUP BY, constrângerile de tip CHECK, condiţiile WHEN;

în instrucţiunile care nu sunt legate de cereri, cum ar fi CREATE PROFILE.

Exemplu: Să se afişeze codul, titlul operelor şi numele artistului doar dacă acesta este

Brâncuşi. În caz contrar, se va afişa şirul „alt artist“.

SELECT cod_opera, titlu, (CASE WHEN cod_artist = (SELECT cod_artist FROM artist WHERE nume = 'Brancusi')

Page 348: CURS BD Combinat

THEN 'Brancusi' ELSE 'Alt artist' END) artist FROM opera; 2.4.4. Funcţii grup şi clauza GROUP BY

Clauza GROUP BY este utilizată pentru a diviza liniile unui tabel în grupuri.

Pentru a returna informaţia corespunzătoare fiecărui astfel de grup, pot fi utilizate funcţiile agregat. Ele pot apărea în clauzele SELECT, ORDER BY şi HAVING. Server-ul Oracle aplică aceste funcţii fiecărui grup de linii şi returnează un singur rezultat pentru fiecare mulţime.

Dintre funcţiile grup definite în sistemul Oracle, se pot enumera: AVG,

SUM, MAX, MIN, COUNT, STDDEV, VARIANCE, DENSE_RANK, RANK, FIRST,

LAST, GROUP_ID, GROUPING, GROUPING_ID etc. Tipurile de date ale

argumentelor funcţiilor grup pot fi CHAR, VARCHAR2, NUMBER sau DATE.

Funcţiile AVG, SUM, STDDEV şi VARIANCE operează numai asupra valorilor

numerice. Funcţiile MAX şi MIN pot opera asupra valorilor numerice, caracter sau

de tip dată calendaristică.

Toate funcţiile grup, cu excepţia lui COUNT(*), ignoră valorile null.

COUNT(expresie) returnează numărul de linii pentru care expresia dată nu are

valoarea null. Funcţia COUNT returnează un număr mai mare sau egal cu zero şi

nu întoarce niciodată valoarea null.

Când este utilizată clauza GROUP BY, server-ul sortează implicit mulţimea

rezultată în ordinea crescătoare a valorilor coloanelor după care se realizează

gruparea.

În clauza GROUP BY a unei cereri se pot utiliza operatorii ROLLUP şi

CUBE. Aceştia sunt disponibili începând cu versiunea Oracle8i.

Operatorul ROLLUP

Operatorul ROLLUP produce o mulţime care conţine liniile obţinute în urma

grupării obişnuite şi linii pentru subtotaluri. Acest operator furnizează valori

agregat şi superagregat corespunzătoare expresiilor din clauza GROUP BY.

Operatorul ROLLUP poate fi folosit pentru extragerea de statistici şi informaţii

totalizatoare din mulţimile rezultate. Acest operator poate fi util la generarea de

rapoarte, diagrame şi grafice.

Operatorul ROLLUP creează grupări prin deplasarea într-o singură direcţie,

de la dreapta la stânga, de-a lungul listei de coloane specificate în clauza GROUP

BY. Apoi, se aplică funcţia agregat acestor grupări. Dacă sunt specificate n expresii

Page 349: CURS BD Combinat

în operatorul ROLLUP, numărul de grupări generate va fi n + 1. Liniile care se

bazează pe valoarea primelor n expresii se numesc linii obişnuite, iar celelalte se

numesc linii superagregat.

Dacă în clauza GROUP BY sunt specificate n coloane, pentru a produce

subtotaluri fără operatorul ROLLUP ar fi necesare n + 1 instrucţiuni SELECT

conectate prin UNION ALL. Aceasta ar face execuţia cererii ineficientă deoarece

fiecare instrucţiune SELECT determină accesarea tabelului. Operatorul ROLLUP

determină rezultatele efectuând un singur acces la tabel şi este util atunci când sunt

implicate multe coloane în producerea subtotalurilor.

Exemplu:

Să se afişeze codurile de galerii mai mici decât 50, iar pentru fiecare dintre

acestea şi pentru fiecare autor care are opere expuse în galerie, să se listeze

valoarea totală a lucrărilor sale. De asemenea, se cere valoarea totală a operelor

expuse în fiecare galerie. Rezultatul va conţine şi valoarea totală a operelor din

galeriile având codul mai mic decât 50, indiferent de codul autorului.

SELECT cod_galerie, cod_artist, SUM(valoare)

FROM opera

WHERE cod_galerie < 50

GROUP BY ROLLUP(cod_galerie, cod_artist);

Instrucţiunea precedentă va avea un rezultat de forma:

COD_GALERIE COD_ARTIST SUM(VALOARE)

10 50 14000

10 60 10000

10 24000

40 50 8080

40 8080

32080

În rezultatul prezentat anterior se pot distinge 3 tipuri de linii. 1) Prima linie reprezintă suma operelor artistului care are codul 50, expuse

în galeria având codul 10. În mod similar se interpretează a doua şi a patra linie din rezultat.

2) Linia a treia şi a cincea din rezultat conţin valoarea totală a operelor din galeria al cărei cod este 10, respectiv 40. Aceste linii se disting prin faptul că valoarea coloanei cod_artist este null.

3) Ultima linie conţine suma valorilor tuturor operelor din galeriile al căror

Page 350: CURS BD Combinat

cod este 10 sau 40. Valoarea afişată este obţinută prin însumarea valorilor de pe a treia, respectiv a cincea linie. Întrucât această linie corespunde totalului general, ea conţine valoarea null pe toate coloanele, cu excepţia câmpului SUM(valoare).

Operatorul CUBE

Operatorul CUBE grupează liniile selectate pe baza valorilor tuturor combinaţiilor posibile ale expresiilor specificate şi returnează câte o linie totalizatoare pentru fiecare grup. Acest operator este folosit pentru a produce mulţimi de rezultate care sunt utilizate în rapoarte. În vreme ce ROLLUP produce subtotalurile doar pentru o parte dintre combinaţiile posibile, operatorul CUBE produce subtotaluri pentru toate combinaţiile posibile de grupări specificate în clauza GROUP BY, precum şi un total general.

Dacă există n coloane sau expresii în clauza GROUP BY, vor exista 2n

combinaţii posibile superagregat. Din punct de vedere matematic, aceste combinaţii formează un cub n-dimensional, de aici provenind numele operatorului. Pentru producerea de subtotaluri fără ajutorul operatorului CUBE ar fi necesare 2

n

instrucţiuni SELECT conectate prin UNION ALL.

Exemplu: Să se afişeze valoarea totală a operelor de artă ale unui autor, expuse în

cadrul fiecărei galerii având codul mai mic decât 50. De asemenea, să se afişeze valoarea totală a operelor din fiecare galerie având codul mai mic decât 50, valoarea totală a operelor fiecărui autor indiferent de galerie şi valoarea totală a operelor din galeriile având codul mai mic decât 50.

SELECT cod_galerie, cod_artist, SUM(valoare)

FROM opera

WHERE cod_galerie < 50

GROUP BY CUBE(cod_galerie, cod_artist);

Instrucţiunea precedentă va genera un rezultat de forma următoare:

COD_GALERIE COD_ARTIST SUM(VALOARE)

10 50 14000

10 60 10000

10 24000

40 50 8080

40 8080

50 22080

60 10000

Page 351: CURS BD Combinat

32080

În plus faţă de rezultatul corespunzător operaţiei ROLLUP, operatorul CUBE

a produs linii care reprezintă suma valorilor operelor pentru fiecare artist care a

expus în galerii având codul mai mic decât 50. Aceste linii se disting prin faptul că

valoarea coloanei cod_galerie este null.

Funcţia GROUPING

Funcţia GROUPING poate fi utilizată alături de operatorii CUBE şi

ROLLUP pentru a arăta modul cum a fost obţinută o valoare totalizatoare. Această

funcţie acceptă un singur argument, care trebuie să fie una dintre expresiile

specificate în clauza GROUP BY.

O valoare null a expresiei din argumentul funcţiei GROUPING poate

proveni din tabelul de bază (valoare null stocată) sau poate fi o valoare null creată

de operaţia ROLLUP sau CUBE ca rezultat al unei funcţii grup asupra expresiei

respective.

Funcţia GROUPING returnează valoarea 0 sau 1. Valoarea 0 returnată de

funcţia GROUPING pe baza unei expresii poate indica fie că expresia a fost

utilizată pentru calculul valorii agregat, fie că valoarea null a expresiei este o

valoare null stocată. Valoarea 1 returnată de funcţia GROUPING pe baza unei

expresii poate indica fie că expresia nu a fost utilizată pentru calculul valorii

agregat, fie că valoarea null a expresiei este creată de ROLLUP sau CUBE ca

rezultat al grupării.

Valorile returnate de funcţia GROUPING sunt utile pentru:

determinarea nivelului de agregare al unui subtotal dat, adică a grupului sau grupurilor pe care se bazează subtotalul respectiv;

identificarea provenienţei unei valori null a unei expresii calculate, dintr-una din liniile mulţimii rezultat.

Exemplu:

SELECT cod_galerie, cod_artist, SUM(valoare), GROUPING(cod_galerie), GROUPING(cod_artist) FROM opera WHERE cod_galerie < 50 GROUP BY ROLLUP(cod_galerie, cod_artist);

COD_GALERIE COD_ARTIST SUM

(VALOARE) GROUPING

(COD_GALERIE) GROUPING

(COD_ARTIST)

10 50 14000 0 0

Page 352: CURS BD Combinat

10 60 10000 0 0

10 24000 0 1

40 50 8080 0 0

40 8080 0 1

32080 1 1

Pe prima linie din acest rezultat, valoarea totalizatoare reprezintă suma valorilor operelor artistului având codul 50, în cadrul galeriei 10. Pentru a calcula această valoare au fost luate în considerare coloanele cod_galerie şi cod_artist. Prin urmare, expresiile GROUPING(cod_galerie) şi GROUPING(cod_artist) au valoarea 0 pentru prima linie din rezultat.

Pe linia a treia se află valoarea totală a operelor din galeria având codul 10. Această valoare a fost calculată luând în considerare doar coloana cod_galerie, astfel încât GROUPING (cod_galerie) şi GROUPING(cod_artist) au valorile 0, respectiv 1.

Pe ultima linie din rezultat se află valoarea totală a operelor din galeriile având codul mai mic decât 50. Nici una dintre coloanele cod_galerie şi cod_artist nu au intervenit în calculul acestui total, prin urmare valorile corespunzătoare expresiilor GROUPING(cod_galerie) şi GROUPING(cod_artist) sunt 0.

Clauza GROUPING SETS

GROUPING SETS reprezintă o extensie a clauzei GROUP BY care permite specificarea unor grupări multiple de date. Utilizarea acestei opţiuni facilitează analiza datelor în mai multe dimensiuni.

Această extensie, apărută în sistemul Oracle9i, permite scrierea unei singure instrucţiuni SELECT pentru a specifica grupări diferite (care pot conţine operatorii ROLLUP şi CUBE), în loc de mai multe instrucţiuni SELECT combinate prin operatorul UNION ALL. De altfel, reuniunea rezultatelor mai multor cereri este ineficientă întrucât necesită mai multe parcurgeri ale aceloraşi date.

Operatorii ROLLUP şi CUBE pot fi consideraţi cazuri particulare de mulţimi

de grupări. Au loc următoarele echivalenţe:

CUBE(a, b, c) GROUPING SETS

((a, b, c), (a, b), (a, c), (b, c), (a),

(b), (c), ())

ROLLUP(a, b,

c)

GROUPING SETS

((a, b, c), (a, b), (a), ())

Exemplu:

Considerând galeriile al căror cod este mai mic decât 50, să se calculeze

media valorilor operelor:

Page 353: CURS BD Combinat

pentru fiecare galerie şi, în cadrul acesteia, pentru fiecare artist;

pentru fiecare artist şi, în cadrul acestuia, pentru anii de achiziţie

corespunzători.

SELECT cod_galerie, cod_artist, TO_CHAR(data_achizitiei, 'yyyy') "an achizitie", AVG(valoare) "Valoare medie" FROM opera WHERE cod_galerie < 50 GROUP BY GROUPING SETS ((cod_galerie, cod_artist), (cod_artist, TO_CHAR(data_achizitiei, 'yyyy')));

Mulţimea rezultat este constituită din valorile medii pentru fiecare dintre cele două grupuri şi are forma următoare:

COD_GALERIE COD_ARTIST an a Valoare medie

10 50 3500

10 60 2500

40 50 2020

50 2000 2380

50 2002 2300

60 2001 2000

60 2003 3000

Exemplul precedent poate fi rezolvat şi prin următoarea instrucţiune compusă:

SELECT cod_galerie, cod_artist, NULL "an achizitie", AVG(valoare) "Valoare medie" FROM opera GROUP BY cod_galerie, cod_artist UNION ALL SELECT NULL, cod_artist, TO_CHAR(data_achizitiei, 'yyyy'), AVG(valoare) FROM opera

GROUP BY cod_artist, TO_CHAR(data_achizitiei, 'yyyy');

În absenţa unui optimizor care analizează blocurile de cerere şi generează

planul de execuţie, cererea precedentă va parcurge de două ori tabelul de bază

(opera), ceea ce poate fi ineficient. Din acest motiv, este recomandată utilizarea

Page 354: CURS BD Combinat

extensiei GROUPING SETS.

Coloane compuse

O coloană compusă este o colecţie de coloane care sunt tratate unitar în

timpul calculelor asupra grupurilor. Pentru a specifica o coloană compusă, aceasta

se include între paranteze. În operaţia ROLLUP(a, (b, c), d), coloanele b şi c

formează o coloană compusă şi sunt tratate unitar.

În general, coloanele compuse sunt utile pentru operaţiile ROLLUP, CUBE

şi GROUPING SETS. De exemplu, în CUBE sau ROLLUP coloanele compuse pot

determina eliminarea agregării de pe anumite niveluri.

Clauza GROUP BY ROLLUP(a, (b, c)) este echivalentă cu următoarea

instrucţiune compusă (în care se precizează doar forma clauzelor GROUP BY):

GROUP BY a, b, c UNION ALL

GROUP BY a UNION ALL

GROUP BY ( )

Astfel, (b, c) sunt tratate unitar şi operaţia ROLLUP nu va fi efectuată asupra

grupurilor în care coloanele b şi c nu apar simultan. Acest lucru este similar

situaţiei în care este definit un alias x pentru (b, c), iar specificaţia clauzei GROUP

BY este GROUP BY ROLLUP(a, x).

În instrucţiunea precedentă, GROUP BY () reprezintă instrucţiunea SELECT

cu valori null pentru coloanele a şi x. Această clauză este folosită pentru generarea

totalurilor generale:

SELECT null, null, coloană_agregat

FROM nume_tabel

GROUP BY ();

Următorul tabel prezintă câteva specificaţii care utilizează operatorii

ROLLUP, CUBE, GROUPING SETS, împreună cu instrucţiunile compuse

echivalente acestora:

GROUP BY ROLLUP(a, b, c) GROUP BY a, b, c UNION

ALL

GROUP BY a, b UNION

ALL

GROUP BY a

GROUP BY CUBE( (a, b), c) GROUP BY a, b, c UNION

ALL

GROUP BY a, b UNION

Page 355: CURS BD Combinat

ALL

GROUP BY c UNION ALL

GROUP BY()

GROUP BY GROUPING SETS(a, b,

c)

GROUP BY a UNION ALL

GROUP BY b UNION ALL

GROUP BY c

GROUP BY GROUPING SETS

(a, b, (b, c) )

GROUP BY a UNION ALL

GROUP BY b UNION ALL

GROUP BY b, c

GROUP BY GROUPING SETS( (a, b,

c) )

GROUP BY a, b, c

GROUP BY GROUPING SETS(a,

(b), ())

GROUP BY a UNION ALL

GROUP BY b UNION ALL

GROUP BY ()

GROUP BY GROUPING SETS (a,

ROLLUP(b, c))

GROUP BY a UNION ALL

GROUP BY ROLLUP(b, c)

Exemplu:

Să se afişeze următoarele informaţii:

valoarea medie a operelor de artă din fiecare galerie;

valoarea medie a operelor de artă pentru fiecare galerie, iar în cadrul

acesteia pentru fiecare artist şi fiecare an de achiziţie;

media generală a tuturor valorilor operelor de artă.

SELECT cod_galerie, cod_artist,

TO_CHAR(data_achizitiei, 'yyyy') "an achizitie",

AVG(valoare) "Valoare medie"

FROM opera

GROUP BY ROLLUP

(cod_galerie,

(cod_artist, TO_CHAR(data_achizitiei, 'yyyy')));

Exemplul precedent poate fi rezolvat utilizând cererea compusă prezentată

mai jos. Folosirea coloanelor compuse este recomandată pentru asigurarea unei

execuţii eficiente.

SELECT cod_galerie, cod_artist,

TO_CHAR(data_achizitiei, 'yyyy'),

AVG(valoare) "Valoare medie"

FROM opera

Page 356: CURS BD Combinat

GROUP BY cod_galerie, cod_artist,

TO_CHAR(data_achizitiei, 'yyyy')

UNION ALL

SELECT cod_galerie, TO_NUMBER(null), TO_CHAR(null),

AVG(valoare) "Valoare medie"

FROM opera

GROUP BY cod_galerie

UNION ALL

SELECT TO_NUMBER(null), TO_NUMBER(null), TO_CHAR(null),

AVG(valoare) "Valoare medie"

FROM opera

GROUP BY ();

Concatenarea grupărilor

Concatenarea grupărilor reprezintă o modalitate concisă de a genera

combinaţii de grupări. Acestea se specifică prin enumerarea mulţimilor de grupări

(grouping sets) şi a operaţiilor ROLLUP, CUBE separate prin virgulă. De exemplu,

expresia GROUP BY GROUPING SETS(a, b), GROUPING SETS(c, d) defineşte

grupările (a, c), (a, d), (b, c), (b, d).

Concatenarea mulţimilor de grupări este utilă atât pentru uşurinţa dezvoltării

cererilor, cât şi pentru aplicaţii. Codul SQL generat de aplicaţiile OLAP implică

deseori concatenarea mulţimilor de grupări, în care fiecare astfel de mulţime

defineşte grupările necesare pentru o dimensiune.

Exemplu:

Să se determine media valorilor operelor luând în considerare următoarele

grupări: (cod_galerie, cod_artist, an_achizitie), (cod_galerie, cod_artist),

(cod_galerie, an_achizitie), (cod_galerie).

SELECT cod_galerie, cod_artist,

TO_CHAR(data_achizitiei, 'yyyy') an_achizitie,

AVG(valoare)

FROM opera

GROUP BY cod_galerie, ROLLUP(cod_artist),

CUBE(TO_CHAR(data_achizitiei, 'yyyy'));

Funcţii analitice

Funcţiile analitice calculează o valoare agregat pe baza unui grup de

înregistrări. Ele diferă de funcţiile agregat prin faptul că, pentru fiecare grup, pot fi

returnate mai multe linii rezultat.

Page 357: CURS BD Combinat

Aceste funcţii reprezintă ultimul set de operaţii efectuat la procesarea unei

interogări, înaintea clauzei ORDER BY. Din acest motiv, o funcţie analitică poate

apărea numai în lista SELECT sau în clauza ORDER BY.

Exemplu:

Pentru fiecare operă de artă, să se afle numărul de creaţii ale căror valori

sunt cu cel mult 1000 mai mici şi cu cel mult 2000 mai mari decât valoarea operei

respective.

SELECT titlu, valoare,

COUNT(*) OVER (ORDER BY valoare

RANGE BETWEEN 1000 PRECEDING

AND 2000 FOLLOWING) AS nr_dom

FROM opera;

Cuvântul cheie OVER indică faptul că funcţia operează pe mulţimea de

rezultate a cererii, adică după evaluarea celorlalte clauze. Opţiunea RANGE

defineşte, pentru fiecare linie, o „fereastră“ (o mulţime de linii). Funcţia analitică

va fi aplicată tuturor liniilor din această mulţime.

2.4.5. Interogări ierarhice

Interogările ierarhice permit regăsirea datelor pe baza unei relaţii ierarhice

care există între liniile tabelului. O bază de date relaţională nu stochează

înregistrările în mod ierarhic. Dacă există o relaţie ierarhică între liniile unui tabel,

un proces de parcurgere a unui arbore (tree walking) permite construirea ierarhiei.

O cerere ierarhică este o metodă de raportare, în ordine, a ramurilor arborelui.

În tabelul opera, se poate imagina o structură arborescentă pe baza valorilor

echivalente ale anilor corespunzători coloanelor data_crearii şi data_achizitiei.

Relaţia „părinte-copil“ a unei structuri arborescente permite controlul

direcţiei în care este parcursă ierarhia şi stabilirea rădăcinii ierarhiei.

Clauzele instrucţiunii SELECT care intervin în formularea unei cereri

ierarhice sunt START WITH şi CONNECT BY. Acestea au fost prezentate împreună

cu instrucţiunea SELECT, la începutul acestui capitol.

Pseudocoloana LEVEL poate fi utilă într-o cerere ierarhică. Aceasta

determină lungimea drumului de la rădăcină la un nod.

Operatorul PRIOR face referinţă la linia „părinte“. Plasarea acestui operator

determină direcţia interogării, dinspre „părinte“ spre „copil“ (top-down) sau invers

(bottom-up). Traversarea top-down, respectiv bottom-up a arborelui se realizează

prin specificări de forma următoare:

Page 358: CURS BD Combinat

CONNECT BY PRIOR cheie_parinte = cheie_copil;

CONNECT BY PRIOR cheie_copil = cheie_parinte;

Operatorul PRIOR poate fi plasat în faţa oricărui membru al condiţiei

specificate în clauza CONNECT BY.

Liniile „părinte“ ale interogării sunt identificate prin clauza START WITH.

Pentru a găsi liniile „copil“, server-ul evaluează expresia din dreptul operatorului

PRIOR pentru linia „părinte“, şi cealaltă expresie pentru fiecare linie a tabelului.

Înregistrările pentru care condiţia este adevărată vor fi liniile „copil“. Spre

deosebire de START WITH, în clauza CONNECT BY nu pot fi utilizate subcereri.

Exemplu:

a) Să se afişeze codul, titlul, data creării şi data achiziţiei operelor, astfel

încât fiecare operă să fie urmată de cele achiziţionate în anul creării sale. Prima

linie afişată va fi cea corespunzătoare operei având codul 110.

SELECT cod_opera, titlu, data_crearii, data_achizitiei

FROM opera

START WITH cod_opera = 110

CONNECT BY PRIOR TO_CHAR(data_crearii, 'yyyy') =

TO_CHAR(data_achizitiei, 'yyyy');

b) Se cer aceleaşi informaţii ca la punctul a), cu deosebirea că prima linie

afişată va fi cea corespunzătoare operei având valoarea maximă.

SELECT 'In anul in care a fost creata "'|| titlu ||

' " s-a achizitionat "' ||

PRIOR titlu || '"' "traversare bottom-up "

FROM opera

START WITH valoare = (SELECT MAX(valoare)

FROM opera)

CONNECT BY PRIOR TO_CHAR(data_achizitiei, 'yyyy') =

TO_CHAR(data_crearii, 'yyyy');

c) Să se afişeze codul, titlul, data creării şi data achiziţiei operelor, astfel

încât fiecare operă să fie urmată de cele achiziţionate în anul creării sale. Se vor

considera doar operele a căror valoare este mai mare decât 7000. Prima linie afişată

va fi cea corespunzătoare operei create cel mai recent.

SELECT cod_opera, titlu, data_crearii, data_achizitiei,

valoare

FROM opera

START WITH data_crearii = (SELECT MAX(data_crearii)

FROM opera)

Page 359: CURS BD Combinat

CONNECT BY PRIOR TO_CHAR(data_crearii, 'yyyy') =

TO_CHAR(data_achizitiei, 'yyyy')

AND valoare > 7000;

În clauza CONNECT BY, coloana data_crearii este evaluată pentru linia

„părinte“, iar coloanele data_achizitiei şi valoare sunt evaluate pentru linia

„copil“.

d) Să se afişeze ierarhia sub forma unui raport, folosindu-se indentări.

Fiecare linie a tabelului va fi considerată drept rădăcină.

SELECT LEVEL,

LPAD(titlu, LENGTH(titlu) + (LEVEL * 2) - 2, '_')

succesiune

FROM opera

CONNECT BY PRIOR TO_CHAR(data_crearii, 'yyyy') =

TO_CHAR(data_achizitiei, 'yyyy');

Exemplu:

a) Să se afişeze codul, titlul, data creării şi data achiziţiei operelor de artă

expuse în muzeu, astfel încât fiecare operă să fie urmată de cele achiziţionate în

anul creării acesteia. Prima linie afişată va fi cea corespunzătoare operei pictorului

Nicolae Grigorescu, achiziţionată cel mai recent. Rezultatul nu va conţine operele

create în anul 1970, dar va conţine operele achiziţionate în acest an.

WITH opera_ng AS

(SELECT cod_opera, data_achizitiei

FROM opera

WHERE cod_artist = (SELECT cod_artist

FROM artist

WHERE INITCAP(nume) = 'Grigorescu'

AND INITCAP(prenume) = 'Nicolae'))

SELECT cod_opera, titlu, data_crearii, data_achizitiei

FROM opera

WHERE TO_CHAR(data_crearii, 'yyyy') != 1970

START WITH (cod_opera, data_achizitiei) IN

(SELECT cod_opera, data_achizitiei

FROM opera_ng

WHERE data_achizitiei =

(SELECT MAX(data_achizitiei)

FROM opera_ng))

CONNECT BY PRIOR TO_CHAR(data_crearii, 'yyyy') =

Page 360: CURS BD Combinat

TO_CHAR(data_achizitiei, 'yyyy');

b) Să se afişeze informaţiile solicitate la punctul a), cu deosebirea că prima

linie listată este cea al cărei cod este 110. Se vor elimina din rezultat liniile

corespunzătoare operelor create sau achiziţonate în anul 1970.

SELECT cod_opera, titlu, data_crearii, data_achizitiei

FROM opera

START WITH cod_opera = 110

CONNECT BY PRIOR TO_CHAR(data_crearii, 'yyyy') =

TO_CHAR(data_achizitiei, 'yyyy')

AND TO_CHAR(data_crearii, 'yyyy') != 1970;

Curs6_IP

Subcereri

De cele mai multe ori, pentru a implementa anumite interogări, nu este

suficientă o singură cerere SELECT ci sunt necesare subcereri. Subcererile sunt

comenzi SELECT încapsulate în oricare din clauzele SELECT, WHERE, HAVING,

FROM.

Dacă subcererea urmează clauzei WHERE sau HAVING, ea poate conţine

unul dintre operatorii ALL, ANY, IN (=ANY), EXIST, NOT IN (!=ALL) care sunt

specifici cererilor care întorc mai multe linii (multiple-row subquery) sau unul

dintre operatorii de comparare (=, <, >, >=, <=, <>) care sunt specifici cererilor

care întorc o singură linie (single-row subquery).

Subcererile trebuie incluse între paranteze şi trebuie plasate în partea dreaptă

a operatorului de comparare. Subcererea nu poate conţine clauza ORDER BY.

Exemplu:

Să se obţină numele şi salariul angajaţilor, având salariul minim.

SELECT ename, sal

FROM emp

WHERE sal=(SELECT MIN(sal)

FROM emp);

Exemplu:

Page 361: CURS BD Combinat

Să se obţină job-ul pentru care salariul mediu este minim. Sa se afiseze si

salariul mediu.

SELECT job, AVG(sal)

FROM emp

GROUP BY job

HAVING AVG(sal)=(SELECT MIN(AVG(sal))

FROM emp

GROUP BY job);

Operatorul ANY presupune că este adevărată condiţia dacă comparaţia este

adevărată pentru cel puţin una din valorile returnate. Sunt evidente relaţiile:

< ANY mai mic ca maximul;

> ANY mai mare ca minimul;

= ANY IN.

Pentru operatorul ALL se presupune că este adevărată condiţia, dacă

comparaţia este adevărată pentru toate elementele listei returnate. Pentru operatorul

ALL sunt evidente relaţiile:

< ALL mai mic ca minimul;

> ALL mai mare ca maximul;

! = ALL NOT IN.

Exemplu:

WHERE codec > ALL („C1‟, „C2‟) este superior tuturor elementelor din listă;

WHERE codec > ANY („C1‟, „C2‟) este superior cel puţin unui element din

listă.

Exemplu:

Să se obţină salariaţii al căror salariu este mai mare ca salariile medii din

toate departamentele.

SELECT ename, job

FROM emp

WHERE sal > ALL(SELECT AVG(sal)

FROM emp

GROUP BY deptno);

Există subcereri care au ca rezultat mai multe coloane (multiple-column

subquery). Aceste interogări au următoarea sintaxă generală:

SELECT col,col,…

Page 362: CURS BD Combinat

FROM tabel

WHERE (col,col,…) IN (SELECT col,col,…

FROM tabel

WHERE condiţie);

Exemplu:

Să se obţină numele, numărul departamentului, salariul şi comisionul tuturor

funcţionarilor ale căror salarii şi comisioane coincid cu salariile şi comisioanele

unor salariaţi din departamentul 7.

SELECT ename, deptno, sal, com

FROM emp

WHERE (sal,NVL(com,-1)) IN

(SELECT sal,NVL(com,-1)

FROM emp

WHERE deptno = 7);

Rezultatul acestei interogări este diferit de rezultatul următoarei interogări:

SELECT ename, deptno, sal, com

FROM emp

WHERE sal IN (SELECT sal

FROM emp

WHERE deptno=7)

AND NVL(com,-1) IN (SELECT NVL(com,-1)

FROM emp

WHERE deptno=7);

Dacă una din valorile returnate de subcerere este valoarea null atunci cererea

nu întoarce nici o linie. Prin urmare, dacă valoarea null poate să facă parte din

rezultatul subcererii nu trebuie utilizat operatorul NOT IN. Problema nu mai apare

dacă se utilizează operatorul IN.

Exemplu:

Să se obţină salariaţii care nu au subordonaţi.

SELECT e.ename FROM emp e WHERE e.empno NOT IN (SELECT m.mgr

FROM emp m);

În acest caz, instrucţiunea SQL nu întoarce nici o linie deoarece una din valorile furnizate de subcerere este valoarea null.

Page 363: CURS BD Combinat

Exemplu: Să se obţină numele salariaţilor, salariile, codul departamentului în care

lucrează şi salariul mediu pe departament pentru toţi angajaţii care au salariul mai mare ca media salariilor din departamentul în care lucrează (folosirea subcererii în clauza FROM).

SELECT a.ename,a.sal,a.deptno,b.salavg FROM emp a,(SELECT deptno,avg(sal) salavg

FROM emp GROUP BY deptno) b

WHERE a.deptno=b.deptno AND a.sal>b.salavg

Exemplu: Să se obţină lista celor mai scumpe cărţi.

SELECT titlu FROM carte WHERE pret = (SELECT MAX(pret)

FROM carte);

Exemplu: Să se obţină lista scriitorilor care au în bibliotecă un număr de exemplare mai mare decât numărul mediu al cărţilor din bibliotecă.

SELECT DISTINCT autor FROM carte WHERE nrex > (SELECT AVG(nrex)

FROM carte);

Exemplu: Să se obţină informaţii despre cărţile al căror preţ depăşeşte media preţurilor cărţilor ce aparţin aceluiaşi domeniu

SELECT * FROM carte c WHERE pret > (SELECT AVG(pret)

FROM carte WHERE coded = c.coded);

Exemplu: Să se obţină lista cititorilor care au împrumutat cel puţin o carte.

SELECT nume FROM cititor WHERE codec IN (SELECT DISTINCT codec

FROM imprumuta);

Page 364: CURS BD Combinat

Exemplu: Să se obţină codurile cititorilor care nu au împrumutat niciodată cărţi.

SELECT codec FROM cititor WHERE codec NOT IN (SELECT DISTINCT codec FROM imprumuta);

Exemplu: Să se obţină lista cititorilor care sunt în întârziere cu predarea cărţilor.

SELECT nume FROM cititor WHERE codec IN (SELECT DISTINCT codec

FROM imprumuta WHERE dataef IS NULL AND dares<SYSDATE);

Exemplu: Să se obţină numele cititorilor care au împrumutat cel puţin o carte scrisă de ZOLA.

SELECT nume FROM cititor WHERE codec IN

(SELECT DISTINCT codec FROM imprumuta WHERE codel IN

(SELECT codel FROM carte WHERE autor=‟ZOLA‟));

Exemplu: Să se obţină numele cititorilor care nu au împrumutat nici o carte scrisă de ZOLA.

SELECT nume FROM cititor WHERE codec NOT IN

(SELECT DISTINCT codec FROM imprumuta WHERE codel IN

(SELECT codel FROM carte

WHERE autor=‟ZOLA‟));

Page 365: CURS BD Combinat

Operatorul IN poate fi înlocuit cu = ANY (un element este în listă dacă şi numai dacă este egal cu un element al listei), iar operatorul NOT IN poate fi înlocuit prin !=ALL.

Exemplu: Să se obţină codurile cititorilor care au împrumutat o carte de algebră.

SELECT DISTINCT codec FROM imprumuta WHERE codel IN (SELECT codel FROM carte WHERE coded= (SELECT coded FROM domeniu

WHERE intdom=‟ALGEBRA‟));

Exemplu: Să se obţină cititorii care au împrumutat numai cărţi scrise de „ZOLA‟.

SELECT nume FROM cititor WHERE codec NOT IN

(SELECT DISTINCT codec FROM imprumuta WHERE codel NOT IN

(SELECT codel FROM carte WHERE autor=‟ZOLA‟));

Exemplu:

Să se obţină numele cititorilor care au împrumutat cel puţin o carte de

informatică (procedural).

SELECT nume FROM cititor WHERE codec IN (SELECT DISTINCT codec FROM imprumuta WHERE codel IN

(SELECT codel FROM carte WHERE coded=

(SELECT coded

Page 366: CURS BD Combinat

FROM domeniu WHERE intdom= ‟INFORMATICA‟)));

Exemplu: Să se obţină numele cititorilor şi titlurile cărţilor de informatică împrumutate de aceşti cititori (relational).

SELECT nume, titlu FROM cititor, carte, imprumuta, domeniu WHERE imprumuta.codel = carte.codel AND carte.coded = domeniu.coded AND imprumuta.codec = cititor.codec AND intdom = ‟INFORMATICA‟;

Subcererile pot fi executate corelat (cu sincronizare) sau încuibărit (fără

sincronizare).

Subcererile fără sincronizare sunt caracterizate de faptul că se execută

cererea cea mai interioară care întoarce un rezultat ce este transmis cererii de nivel

superior, care întoarce un rezultat s.a.m.d.

Subcererile cu sincronizare sunt caracterizate de faptul că evaluarea

subcererii face referinţă la o coloană a cererii principale, iar evaluarea cererii

interioare se face pentru fiecare linie a cererii (principale) care o conţine.

Exemplu:

Să se obţină, utilizând sincronizarea subcererii cu cererea principală, titlurile

cărţilor care au toate exemplarele împrumutate (se selectează un titlu din carte şi

pentru acest titlu se numără câte exemplare sunt împrumutate).

SELECT titlu

FROM carte

WHERE nrex=(SELECT COUNT(*)

FROM imprumuta

WHERE codel = carte.codel

AND dataef IS NULL);

Exemplu:

Să se obţină codurile cititorilor şi codul ultimei cărţi împrumutate.

SELECT codec, codel

FROM imprumuta i

WHERE dataim>=ALL (SELECT dataim

FROM imprumuta

WHERE codec=i.codec);

Page 367: CURS BD Combinat

Pentru această interogare, clauza WHERE putea fi scrisă şi sub forma:

WHERE dataim=(SELECT MAX(dataim)

FROM imprumuta

WHERE codec=i.codec);

Exemplu:

Să se obţină lista codurilor cărţilor împrumutate şi codul primului cititor care

a împrumutat aceste cărti.

SELECT codel,codec

FROM imprumuta i

WHERE dataim<=ALL (SELECT dataim

FROM imprumuta

WHERE i.codel=codel);

Exemplu:

Să se obţină codurile cărţilor din care cel puţin un exemplar este împrumutat.

SELECT codel

FROM carte

WHERE EXISTS

(SELECT codel

FROM imprumuta

WHERE codel = carte.codel

AND dataef IS NULL);

Operatorul WHERE EXISTS (subcerere) presupune că predicatul este

adevărat dacă subcererea întoarce cel puţin un tuplu, iar WHERE NOT EXISTS

(subcerere) presupune că predicatul este adevărat dacă subcererea nu întoarce nici

un tuplu. EXISTS şi NOT EXISTS cer sincronizarea subcererii.

Exemplu:

Să se obţină titlurile cărţilor care sunt momentan împrumutate.

Soluţia 1 (cu sincronizare):

SELECT titlu

FROM carte

WHERE EXISTS

(SELECT *

FROM imprumuta

WHERE codel = carte.codel

AND dataef IS NULL);

Soluţia 2 (fără sincronizare):

Page 368: CURS BD Combinat

SELECT titlu

FROM carte

WHERE codel IN

(SELECT DISTINCT codel

FROM imprumuta

WHERE dataef IS NULL);

Exemplu:

Să se obţină codurile cărţilor care nu au fost împrumutate niciodată.

Soluţia 1 (cu sincronizare) SELECT codel FROM carte WHERE NOT EXISTS

(SELECT codel FROM imprumuta WHERE codel = carte.codel);

Soluţia 2 (fără sincronizare)

SELECT codel FROM carte WHERE codel NOT IN

(SELECT DISTINCT codel

FROM imprumuta);

Exemplu:

Să se obţină lista salariaţilor având salariul minim în departamentul în care

lucrează.

SELECT ename,sal

FROM emp e

WHERE sal=(SELECT MIN(sal)

FROM emp

WHERE deptno=e.deptno);

Exemplu:

Să se obţină numele primilor trei salariaţi având retribuţia maximă (ideea

rezolvării este de a verifica dacă numărul salariaţilor care au leafa mai mare decât

leafa salariatului considerat, este mai mic decât 3).

SELECT ename

FROM emp a

WHERE 3>(SELECT COUNT(*)

FROM emp

Page 369: CURS BD Combinat

WHERE sal > a.sal);

Exemplu:

Să se obţină numele cititorilor care au împrumutat cel puţin aceleaşi cărţi ca

şi cititorul având codul C19 (ideea problemei este de a selecta cititorii pentru care

este vidă lista cărţilor împrumutatede C19 mai puţin lista cărţilor împrumutate de

acei cititori).

SELECT nume

FROM cititor

WHERE NOT EXISTS

(SELECT codel

FROM imprumuta

WHERE codec=‟C19‟

MINUS

SELECT codel

FROM imprumuta

WHERE codec= cititor.codec);

Dacă problema era modificată în sensul că „cel puţin”este înlocuit prin „cel

mult” atunci trebuiau inversate interogările legate prin MINUS.

Exemplu: Să se obţină codurile cititorilor care au împrumutat aceleaşi cărţi ca şi

cititorul având un cod specificat.

Rezolvarea problemei se bazează pe ideea: A = B A B şi B A (A-

B) = şi (B-A) = A-B şi B-A nu furnizează nici un tuplu rezultat.

SELECT codec FROM imprumuta i WHERE NOT EXISTS

(SELECT codel FROM imprumuta WHERE codec=i.codec

MINUS SELECT codel FROM imprumuta WHERE codec=‟&ccc‟)

AND NOT EXISTS (SELECT codel FROM imprumuta WHERE codec=‟&ccc‟

Page 370: CURS BD Combinat

MINUS SELECT codel FROM imprumuta WHERE codec=i.codec)

AND codec!=‟&ccc‟);

Ultimul operator (AND), asigură să nu apară în rezultat cititorul specificat.

În cazul formei relaţionale de rezolvare a cererii, drumul de acces la informaţie este în sarcina SGBD-lui şi prin urmare nu mai apar cereri imbricate.

Exemplu: Să se obţină numele cititorilor care au împrumutat cel puţin o carte.

Soluţia 1 (forma relaţională): SELECT DISTINCT nume FROM cititor,imprumuta WHERE cititor.codec=imprumuta.codec;

Soluţia 2 (forma procedurală): SELECT nume FROM cititor WHERE codec IN

(SELECT DISTINCT codec FROM imprumuta);

Exemplu: Să se obţină numele cititorilor care au împrumutat cel puţin două cărţi.

Soluţia 1 (forma relaţională): SELECT nume FROM cititor, imprumuta WHERE cititor.codec=imprumuta.codec GROUP BY nume HAVING COUNT(*)>1;

Soluţia 2 (forma procedurală): SELECT nume FROM cititor WHERE codec IN

(SELECT codec FROM imprumuta GROUP BY codec HAVING COUNT(*)>1);

Exemplu:

Să se afişeze numele, prenumele, salariul lucrătorilor, codurile publicaţiilor

la care lucrează şi salariul mediu pe publicaţie pentru toţi angajaţii care au salariul

mai mare decât media salariului pe publicaţia respectivă.

Page 371: CURS BD Combinat

SELECT s.nume, s.prenume, s.salariu,

p.nr_publicatie, a.salariu_mediu

FROM salariat s, publicatie p,

(SELECT p1.nr_publicatie,AVG(salariu) salariu_mediu

FROM publicatie p1, salariat s1

WHERE p1.cod_salariat = s1.cod_salariat

GROUP BY p1.nr_publicatie) a

WHERE p.nr_publicatie = a.nr_publicatie

AND s.cod_salariat = p.cod_salariat

AND s.salariu > a.salariu_mediu;

Exemplu: Să se obţină numele salariaţilor care nu cunosc nici o limbă străină.

SELECT nume, prenume FROM salariat WHERE NOT EXISTS (SELECT * FROM limba WHERE limba.cod_salariat = salariat.cod_salariat AND limba_cun IS NOT NULL);

Exemplu:

Să se afişeze graficienii care au întârziat să predea frame-urile.

a) cu sincronizare:

SELECT nume, prenume

FROM salariat

WHERE EXISTS

(SELECT *

FROM realizeaza r

WHERE salariat.cod_salariat=r.cod_salariat

AND data_lim < SYSDATE);

b) fără sincronizare:

SELECT nume, prenume

FROM salariat

WHERE cod_salariat IN

(SELECT DISTINCT cod_salariat

FROM realizeaza

WHERE data_lim < SYSDATE);

Exemplu:

Page 372: CURS BD Combinat

Să se determine revistele coordonate de redactori şefi care nu cunosc limba

în care sunt scrise. Se ştie că în urma inspectării vizuale a rezultatului interogării se

poate decide schimbarea redactorilor şefi ai revistelor respective, de aceea se

doreşte blocarea înregistrărilor găsite.

SELECT p.nr_publicatie

FROM salariat s, publicatie p

WHERE s.cod_salariat = p.cod_salariat

AND p.limba NOT IN

(SELECT limba_cun

FROM limba

WHERE limba.cod_salariat = s.cod_salariat)

FOR UPDATE OF p.cod_salariat;

Clauza WITH

Cu ajutorul clauzei WITH se poate defini un bloc de cerere înainte ca acesta

să fie utilizat într-o interogare. Clauza permite reutilizarea aceluiaşi bloc de cerere

într-o instrucţiune SELECT complexă. Utilizând clauza WITH, să se scrie o cerere care afişează numele artiştilor şi

valoarea totală a operelor acestora. Se vor considera artiştii a căror valoare totală a operelor este mai mare decât media valorilor operelor tuturor artiştilor.

WITH val_artist AS (SELECT nume, SUM(valoare) AS total FROM opera o, artist a WHERE o.cod_artist = a.cod_artist GROUP BY nume), val_medie AS (SELECT SUM(total)/COUNT(*) AS medie FROM val_artist) SELECT * FROM val_artist WHERE total > (SELECT medie FROM val_medie) ORDER BY nume;

Subcereri scalare

Subcererile scalare în SQL returnează valoarea unei singure coloane corespunzătoare unei linii. Dacă subcererea returnează 0 linii, valoarea subcererii scalare este null. Dacă subcererea returnează mai mult de o linie, server-ul generează o eroare.

Subcererile scalare erau acceptate în Oracle8i doar în anumite cazuri, cum ar fi clauzele FROM şi WHERE ale instrucţiunii SELECT sau clauza VALUES a instrucţiunii INSERT. Utilitatea subcererilor scalare a fost extinsă în Oracle9i.

Page 373: CURS BD Combinat

Astfel, ele pot apărea în:

condiţiile şi expresiile care fac parte din DECODE sau CASE;

toate clauzele instrucţiunii SELECT, cu excepţia lui GROUP BY; în partea stângă a operatorului, în clauzele SET şi WHERE ale

instrucţiunii UPDATE.

Exemplu: Să se afişeze codul, titlul operelor şi numele artistului doar dacă acesta este

Brâncuşi. În caz contrar, se va afişa şirul „alt artist“.

SELECT cod_opera, titlu, (CASE WHEN cod_artist = (SELECT cod_artist FROM artist WHERE nume = 'Brancusi') THEN 'Brancusi' ELSE 'Alt artist' END) artist FROM opera;

Operatorul ROLLUP

Operatorul ROLLUP produce o mulţime care conţine liniile obţinute în urma

grupării obişnuite şi linii pentru subtotaluri. Acest operator furnizează valori

agregat şi superagregat corespunzătoare expresiilor din clauza GROUP BY.

Operatorul ROLLUP creează grupări prin deplasarea într-o singură direcţie,

de la dreapta la stânga, de-a lungul listei de coloane specificate în clauza GROUP

BY. Apoi, se aplică funcţia agregat acestor grupări. Dacă sunt specificate n expresii

în operatorul ROLLUP, numărul de grupări generate va fi n + 1. Liniile care se

bazează pe valoarea primelor n expresii se numesc linii obişnuite, iar celelalte se

numesc linii superagregat.

Daca in clauza GROUP BY sunt specificate n coloane, atunci pentru a

produce subtotaluri in n dimensiuni ar fi necesare n+1 operatii SELECT legate prin

UNION ALL. Aceasta ar fi total ineficient, deoarece fiecare SELECT ar implica o

parcurgere a tabelului. Operatorul ROLLUP are nevoie de o singura parcurgere a

tabelului.

Exemplu:

Să se afişeze codurile de galerii mai mici decât 50, iar pentru fiecare dintre

acestea şi pentru fiecare autor care are opere expuse în galerie, să se listeze

valoarea totală a lucrărilor sale. De asemenea, se cere valoarea totală a operelor

expuse în fiecare galerie. Rezultatul va conţine şi valoarea totală a operelor din

galeriile având codul mai mic decât 50, indiferent de codul autorului.

Page 374: CURS BD Combinat

SELECT cod_galerie, cod_artist, SUM(valoare)

FROM opera

WHERE cod_galerie < 50

GROUP BY ROLLUP(cod_galerie, cod_artist);

Instrucţiunea precedentă va avea un rezultat de forma:

COD_GALERIE COD_ARTIST SUM(VALOARE)

10 50 14000

10 60 10000

10 24000

40 50 8080

40 8080

32080

Operatorul CUBE

Operatorul CUBE grupează liniile selectate pe baza valorilor tuturor

combinaţiilor posibile ale expresiilor specificate şi returnează câte o linie

totalizatoare pentru fiecare grup. El produce subtotaluri pentru toate combinaţiile

posibile de grupări specificate în GROUP BY, precum şi un total general.

Daca exista n coloane sau expresii in clauza GROUP BY, vor exista 2n

combinatii posibile superagregat. Matematic, aceste combinatii formeaza un cub

n-dimensional.

Pentru producerea de subtotaluri fara ajutorul operatorului CUBE ar fi

necesare 2n instructiuni SELECT legate prin UNION ALL.

Exemplu:

Să se afişeze valoarea totală a operelor de artă ale unui autor, expuse în

cadrul fiecărei galerii având codul mai mic decât 50. De asemenea, să se afişeze

valoarea totală a operelor din fiecare galerie având codul mai mic decât 50,

valoarea totală a operelor fiecărui autor indiferent de galerie şi valoarea totală a

operelor din galeriile având codul mai mic decât 50.

SELECT cod_galerie, cod_artist, SUM(valoare)

FROM opera

WHERE cod_galerie < 50

GROUP BY CUBE(cod_galerie, cod_artist);

COD_GALERIE COD_ARTIST SUM(VALOARE)

Page 375: CURS BD Combinat

10 50 14000

10 60 10000

10 24000

40 50 8080

40 8080

50 22080

60 10000

32080

Funcţia GROUPING

Aceasta funcţie este utilă pentru:

determinarea nivelului de agregare al unui subtotal dat, adică a grupului

sau grupurilor pe care se bazează subtotalul respectiv;

identificarea provenienţei unei valori null a unei expresii calculate, dintr-

una din liniile mulţimii rezultat.

Functia returnează valoarea 0 sau 1. Valoarea 0 poate indica fie că expresia a

fost utilizată pentru calculul valorii agregat, fie că valoarea null a expresiei este o

valoare null stocată.

Valoarea 1 poate indica fie că expresia nu a fost utilizată pentru calculul

valorii agregat, fie că valoarea null a expresiei este o valoare creată de ROLLUP

sau CUBE ca rezultat al grupării.

Exemplu:

SELECT cod_galerie, cod_artist, SUM(valoare),

GROUPING(cod_galerie), GROUPING(cod_artist)

FROM opera

WHERE cod_galerie < 50

GROUP BY ROLLUP(cod_galerie, cod_artist);

COD_GALERIE COD_ARTIST SUM

(VALOARE) GROUPING

(COD_GALERIE) GROUPING

(COD_ARTIST)

10 50 14000 0 0

10 60 10000 0 0

10 24000 0 1

Page 376: CURS BD Combinat

40 50 8080 0 0

40 8080 0 1

32080 1 1

Pe prima linie din acest rezultat, valoarea totalizatoare reprezintă suma valorilor operelor artistului având codul 50, în cadrul galeriei 10. Pentru a calcula această valoare au fost luate în considerare coloanele cod_galerie şi cod_artist. Prin urmare, expresiile GROUPING(cod_galerie) şi GROUPING(cod_artist) au valoarea 0 pentru prima linie din rezultat.

Pe linia a treia se află valoarea totală a operelor din galeria având codul 10. Această valoare a fost calculată luând în considerare doar coloana cod_galerie, astfel încât GROUPING (cod_galerie) şi GROUPING(cod_artist) au valorile 0, respectiv 1.

Pe ultima linie din rezultat se află valoarea totală a operelor din galeriile având codul mai mic decât 50. Nici una dintre coloanele cod_galerie şi cod_artist nu au intervenit în calculul acestui total, prin urmare valorile corespunzătoare expresiilor GROUPING(cod_galerie) şi GROUPING(cod_artist) sunt 0.

Clauza GROUPING SETS

GROUPING SETS reprezintă o extensie a clauzei GROUP BY care permite

specificarea unor grupări multiple de date. Această extensie, apărută în sistemul Oracle9i, permite scrierea unei singure

instrucţiuni SELECT pentru a specifica grupări diferite (care pot conţine operatorii ROLLUP şi CUBE), în loc de mai multe instrucţiuni SELECT combinate prin operatorul UNION ALL. De altfel, reuniunea rezultatelor mai multor cereri este ineficientă întrucât necesită mai multe parcurgeri ale aceloraşi date.

Operatorii ROLLUP şi CUBE pot fi consideraţi cazuri particulare de mulţimi

de grupări. Au loc următoarele echivalenţe:

CUBE(a, b, c) GROUPING SETS

((a, b, c), (a, b), (a, c), (b, c), (a), (b), (c),

())

ROLLUP(a, b,

c)

GROUPING SETS

((a, b, c), (a, b), (a), ())

Exemplu:

Considerând galeriile al căror cod este mai mic decât 50, să se calculeze

Page 377: CURS BD Combinat

media valorilor operelor:

pentru fiecare galerie şi, în cadrul acesteia, pentru fiecare artist;

pentru fiecare artist şi, în cadrul acestuia, pentru anii de achiziţie

corespunzători.

SELECT cod_galerie, cod_artist, TO_CHAR(data_achizitiei, 'yyyy') "an achizitie", AVG(valoare) "Valoare medie" FROM opera WHERE cod_galerie < 50 GROUP BY GROUPING SETS ((cod_galerie, cod_artist), (cod_artist, TO_CHAR(data_achizitiei, 'yyyy')));

Mulţimea rezultat este constituită din valorile medii pentru fiecare dintre cele două grupuri ((cod_galerie, cod_artist) si (cod_artist, an_achizitie)) şi are forma următoare:

COD_GALERIE COD_ARTIST An achizitie Valoare medie

10 50 3500

10 60 2500

40 50 2020

50 2000 2380

50 2002 2300

60 2001 2000

60 2003 3000

Exemplul precedent poate fi rezolvat şi prin următoarea instrucţiune compusă:

SELECT cod_galerie, cod_artist, NULL "An achizitie", AVG(valoare) "Valoare medie" FROM opera GROUP BY cod_galerie, cod_artist UNION ALL SELECT NULL, cod_artist, TO_CHAR(data_achizitiei, 'yyyy'), AVG(valoare) FROM opera

GROUP BY cod_artist, TO_CHAR(data_achizitiei, 'yyyy');

În absenţa unui optimizor care analizează blocurile de cerere şi generează

planul de execuţie, cererea precedentă va parcurge de două ori tabelul de bază

Page 378: CURS BD Combinat

(opera), ceea ce poate fi ineficient. Din acest motiv, este recomandată utilizarea

extensiei GROUPING SETS.

Page 379: CURS BD Combinat

Limbajul de manipulare a datelor – DML

În aceast curs se prezintă instrucţiunile DML (Data Manipulation

Language), o parte a limbajului SQL folosită pentru intreţinerea datelor stocate în

tabele relaţionale ale bazei de date.

Limbajul DML este format din trei comenzi SQL:

INSERT Adaugă noi rânduri într-un table al bazei de date.

UPDATE Actualizeaza rândurile existente intr-un table al bazei de date.

DELETE Sterge rânduri dintr-un tabel al bazei de date

Instrucţiunile DML individuale afectează datele dintr-un singur tabel. Este

posibil ca într-o instrucţiune DML să referiţi şi o vizualizare care conţine date din

mai multe tabele (adică o vizualizare care conţine o uniune de tabele), dar, în acest

caz, instrucţiunea DML poate referi numai coloane dintr-un singur tabel al

vizualizării. Cu alte cuvinte, atunci cand o instrucţiune DML foloseşte o

vizualizare, toate coloanele vizualizării referite în instrucţiunea DML trebuie să

corespundă unor coloane dintr-un singur tabel fizic al bazei de date.

Sistemul SGBD nu va efectua în baza de date nici o modificare care încalcă

una din restricţii.

La formarea instructiunilor DML, trebuie să se ţină seama de urmatoarele

aspecte referitoare la restricţiile tabelului modificat:

Restricţii de tip cheie primară

Atunci când inseraţi un nou rând într-un tabel, cheia primară a noului rând

trebuie sa fie unică în întregul tabel.Cand modificati valoarea unei chei primare

(ceea ce se intampla rareori), noua valoare trebuie să fie unică în întregul tabel.

Restricţii de unicitate

Ca şi în cazul cheilor primare, coloanele pe care a fost definită o restricţie de

unicitate trebuie sa aibă valori unice în întregul tabel.

Restricţii NOT NULL

O valoare nula (null) este o modalitate specială prin care sistemul SGBD

tratează valoarea unei coloane pentru a indica faptul ca valoarea coloanei

respective nu este cunoscută. O valoare nula nu este acelasi lucru un un spatiu

Page 380: CURS BD Combinat

liber, un sir vid sau valoarea zero – este o valoare speciala care nu este egala cu

nimic altceva.

În cazul instrucţiunilor INSERT, trebuie specificate valori pentru toate

coloanele cu restricţii NOT NULL.

În cazul instrucţiunilor UPDATE nu se pot inlocui valorile unei coloane cu

valori nule dacă pe coloana respectivă este definită p restricţie NOT NULL.

Dacă instrucţiunea DML referă o vizualizare , nu se poate sa o folosim intr-

o instrucţiune INSERT dacă una dintre coloanele tabelului cu o restricţie NOT

NULL(obligatorii) lipseşte din definirea vizualizării.

Restricţii referenţiale

Nu se poate insera sau actualiza valoarea unei chei externe decât dacă există

deja rândul părinte corespondent care conţine valoarea cheii în coloana cheii

primare. In sens invers, nu se poate şterge un rând părinte dacă există rânduri

subordonate care referă valoarea din rândul părinte, decât dacă restricţia a fost

definită cu opţiunea ON DELETE CASCADE. In general inserările în tabele

trebuie făcute ierarhic (mai intai randurile parinte, apoi randurile copii), iar

ştergerile trebuie făcute în ordine inversă (copiii inaintea părinţilor).

Restrictii de verificare (CHECK) O instructiune INSERT sau UPDATE

nu poate stoca într-o coloana o valoare care încalcă o restricţie CHECK definită

pentru coloana respectivă.

Instrucţiunea INSERT

Instrucţiunea INSERT este folosită pentru inserarea noilor rânduri de date în

tabele sau tabele de bază al unei vizualizări. Instrucţiunea are două forme de bază:

una în care valorile coloanelor sunt specificate chiar în instrucţiune şi alta în care

valorile sunt selectate dintr-un tabel sau o vizualizare, folosind o subinterogare.

Inserarea unui singur rand de date folosind clauza Values

Instrucţiunea INSERT care foloseşte o clauză VALUES poate crea un

singur rând la fiecare rulare, deoarece valorile pentru rândul de date respective sunt

specificate chiar în instrucţiune.

Page 381: CURS BD Combinat

Sintaxa generală a instrucţiunii este următoarea:

INSERT INTO nume_tabel_sau_vizualizare

[(lista_de_coloane)]

VALUES (lista_de_valori);

Sau

INSERT INTO nume_tabel / nume_view [(col1[, col2[,…]])]

VALUES (expresia1[, expresia2[,…]]) / subcerere;

expresia1, expresia2, reprezintă expresii a căror evaluare este atribuită

coloanelor precizate (se inserează o linie);

subcerere, reprezintă o interogare (se inserează una sau mai multe

linii).

Clauza VALUES specifică valorile ce vor fi introduse în tabel sau

vizualizare. Pentru a insera mai multe linii prin aceeaşi instrucţiune INSERT, în

locul acestei clauze se va preciza o subcerere.

Exemple pentru baza de date FILM

Diagrama ERD a bazei de date FILM(prezentare parţială)

FILM

FILM_ID <pk>

MPAA_RATING FILM_COD_GEN <fk1> FILM_GEN

MPAA_COD_RATING <pk> MPAA_COD_RATING <fk2> FILM_COD_GEN <pk>

MPAA_DESCRIERE_RATING FILM_NUME FILM_DESCRIERE_GEN

RETAIL_PRET_VHS

RETAIL_PRET_DVD

AN_PRODUS

FILM_COPII

FILM_ID <pk, fk>>

NUMAR_COPIE <pk>

DATA_CUMPARARE

DATA_VANZARE

FORMAT_MEDIA

Page 382: CURS BD Combinat

Se poate remarcă următoarele:

Lista de coloane este opţională, dar dacă este inclusă trebuie să fie

încadrată în paranteze rotunde.

Dacă lista de coloane este omisă, trebuie specificată o valoare pentru

fiecare coloană din tabel, în ordinea în care sunt definite coloanele în tabel. Este

bine ca întotdeauna să includeţi lista de coloane, deoarece omiterea acesteia face ca

instrucţiunea INSERT să fie dependentă de definiţia tabelului. Dacă o coloană este

modificată sau în tabel este adăugată o nouă coloană, chiar şi opţională, probabil

instrucţiunea INSERT va eşua la următoarea rulare.

Dacă lista de coloane este specificată, lista de valori trebuie să conţin

o valoare pentru fiecare coloană din listă, în aceeaşi ordine. Cu alte cuvinte, între

lista de coloane şi lista de valori trbuie să existe o corespondenţa unu-la-unu. Orice

coloana care lipseşte din listă va primi o valoare nulă, presupunund că valorile nule

sunt acceptate în coloana respectivă.

În clauza VALUES, valorile de tip caracter şi dată calendaristică

trebuie incluse între apostrofuri. Nu se recomandă includerea între apostrofuri a

valorilor numerice, întrucât aceasta ar determina conversii implicite la tipul

NUMBER.

Pentru introducerea de valori speciale în tabel, pot fi utilizate funcţii.

Adăugarea unei linii care va conţine valori null se poate realiza în

mod:

- implicit, prin omiterea numelui coloanei din lista de coloane;

- explicit, prin specificarea în lista de valori a cuvântului cheie null

sau a şirului vid în cazul şirurilor de caractere sau datelor

calendaristice.

Exemplul următor conţine două instrucţiuni INSERT, una care creează un

nou rând în tabelul FILM, cu o listă opţională de coloane, din care este omisă

coloana RETAIL_PRET_VHS, şi alta care creează un rând în tabelul FILM_COPII

pentru acelaşi tip, dar fără lista opţională de coloane.

INSERT INTO FILM

(FILM_ID, FILM_COD_GEN, MPAA_RATING_COD, FILM_NUME,

PRET_INCHIRIAT_DVD, AN_PRODUCERE)

VALUES (21,‟Drama‟,‟PG-13‟,‟Ray‟, 29.95, ‟2004‟);

INSERT INTO FILM_COPII

VALUES (21, 1, ‟2005-04-01‟, NULL, ‟V‟);

Page 383: CURS BD Combinat

Exemplu baza galeria de arta

GALERIE

cod_galerie# SALA

cod_sala#

cod_galerie#

OPERA

cod_opera#

AUTOR

cod_autor#

ARTIST

cod_artist#

SECURITATE cod_opera#

sistem#

POLITA_ASIG

cod_polita#

SPECIALIST

cod_specialist#

EXPOZITIE

cod_expo#

ORGANIZATOR

cod_organizator#

1 inclusa_in M(1)

1

cuprinsa_in

M(1)

1 creata_de M(1)

protejata_prin 1 M(0)

1 asigurata_de M(0)

SURSA_BIBLIO

cod_sursa#

tip

ARTICOL

CARTE

M(1)

studiaza

M(0)

M(1) organizata_de M(1)

M(0)

M(1)

mentionata_in

M(1)

M(0)

figureaza_in

M(1)

editata_de

M(1)

Page 384: CURS BD Combinat

Să se adauge prin metoda explicită, respectiv prin metoda implicită, două

înregistrări în tabelul artist, precizând numai codul, numele şi prenumele artistului.

ARTIST(cod_artist#, nume, prenume, an_nastere, an_moarte,

nationalitate, observatii);

INSERT INTO artist

(cod_artist, nume, prenume)

VALUES (50, 'Grigorescu', 'Nicolae');

INSERT INTO artist

VALUES (70, 'Andreescu', 'Ion', NULL, NULL, NULL, NULL);

în galeria creată anterior şi care a fost achiziţionată la 20 ianuarie 2009.

Exemplu:

Următoarea instrucţiune va genera eroarea „ORA-01400: cannot insert

NULL into …“, întrucât se încearcă inserarea unei linii în tabelul opera fără a

preciza valoarea cheii primare.

INSERT INTO opera

(titlu, data_achizitiei)

VALUES ('Flori de camp', SYSDATE);

Exemplu BD CARTE

Să se insereze în tabelul carte toate cărţile din tabelul carte_info,

presupunând că tabelul carte_info a fost deja creat. De asemenea, să se introducă o

nouă carte căreia i se cunoaşte codul (c34), titlul (algebra) şi preţul (500).

INSERT INTO carte

(codel, titlu, autor, nrex, pret, coded)

VALUES (‟c34‟,‟algebra‟, null, null, 50, null);

Exemplu:

INSERT INTO carte

(codel, nrex)

VALUES ('c25', 25);

Page 385: CURS BD Combinat

inserare prin parametrizare

INSERT INTO domeniu

VALUES ('&cod', '&dendom'); inserare prin parametrizare

Inserări masive folosind instrucţiunea SELECT internă

Aşa cum se observă, este nevoie de foarte mult cod pentru a insera în tabel

un singur rând de date folosind o instrucţiune INSERT cu clauza VALUES.

O altă soluţie, care poate fi folosită pentru a insera rânduri multiple într-un

tabel , este forma care foloseşte o instrucţiune SELECT internă. Această formă este

utilă şi pentru stabilirea următoarei valori disponibile pentru o cheie primară cu

valori secvenţiale. De asemenea , poate fi folosită atunci când creaţi un tabel

temporar pentru testare şi vreţi să-l populaţi cu toate datele dintr-un alt tabel.

Sintaxa generală a instrucţiunii este

INSERT INTO nume_tabel_sau_vizualizare

[(lista_de_coloane)]

SELECT instructiune_select;

Se remarcă următoarele:

Lista de coloane este opţională, dar dacă este inclusă trebuie să fie încadrată

în paranteze.

Dacă lista de coloane este omisă, instrucţiune SELECT internă trebuie să

furnizeze o valoare pentru fiecare coloană din tabel, în ordinea în care sunt definite

coloanele în tabel. Este bine ca întotdeauna să includeţi lista de coloane, deoarece

omiterea acesteia face ca instrucţiunea INSERT să fie dependentă de definiţia

tabelului. Dacă o coloană este modificată sau în tabel este adăugată o nouă

coloană, chiar şi opţională, probabil instrucţiunea INSERT va eşua la următoarea

rulare.

Dacă lista de coloane este specificată, instrucţiune SELECT internă să

furnizeze o valoare pentru fiecare coloană din lista de valori, în aceeaşi ordine. Cu

alte cuvinte, între lista de coloane şi setul de rezultate al instrucţiunii SELECT

trebuie să existe o corespondenţa unu-la-unu. Orice coloană care lipseşte din listă

va primi o valoare nulă, presupunund că valorile nule sunt acceptate în coloana

respectivă.

Cuvântul cheie NULL poate fi folosit în instrucţiunea SELECT pentru

specificarea unei valori nule pentru o coloană.

Page 386: CURS BD Combinat

Ca exemplu, să presupunem că toate filmele sunt acum disponibile şi în

limba franceză. Tabelul FILM_LIMBA conţine rânduri pentru limba franceză

pentru o parte din filme, aşa că acum vrem să le adăugăm numai pe cele care

lipsesc. Instrucţiunea INSERT care va rezolva această problemă este:

INSERT INTO FILM_LIMBA

(FILM_ID, COD_LIMBA)

SELECT FILM_ID, ‟fr‟

FROM FILM

WHERE FILM_ID NOT IN

( SELECT FILM_ID FROM FILM_LIMBA

WHERE COD_LIMBA =‟fr‟ );

INSERT INTO carte

SELECT *

FROM carte_info;

Exemplu:

Presupunând că tabelul salariat a fost completat cu datele tuturor

salariaţilor editurii, să se completeze tabelele grafician, tehnoredactor şi

redactor_sef, în concordanţă cu datele conţinute în tabelul salariat (nu pot exista

graficieni, tehnoredactori sau redactori şefi care să nu fie salariaţi!).

INSERT INTO grafician (cod_salariat)

SELECT cod_salariat

FROM salariat

WHERE job = ‟grafician‟;

INSERT INTO tehnoredactor (cod_salariat)

SELECT cod_salariat

FROM salariat

WHERE job = ‟tehnoredactor‟;

INSERT INTO redactor_sef (cod_salariat)

SELECT cod_salariat

FROM salariat

WHERE job = ‟redactor_sef‟;

Page 387: CURS BD Combinat

NU Inserări multitabel

O inserare multitabel presupune introducerea de linii calculate pe baza

rezultatelor unei subcereri, în unul sau mai multe tabele. Acest tip de inserare,

introdus de Oracle9i, este util în mediul data warehouse. Astfel, datele extrase

dintr-un sistem sursă, pot fi transformate utilizând instrucţiuni INSERT multitabel,

spre a fi încărcate în obiectele bazei de date.

Pentru o astfel de inserare, în versiunile anterioare lui Oracle9i erau

necesare n operaţii independente INSERT INTO…SELECT…, unde n reprezintă

numărul tabelelor destinaţie. Aceasta presupunea n procesări ale aceleiaşi surse de

date şi, prin urmare, creşterea de n ori a timpului necesar procesului.

Sintaxa clauzei inserare_multi_tabel este următoarea:

{ALL INTO…[VALUES…] [INTO…[VALUES…] …] | inserare_condiţionată} subcerere

Clauza inserare_condiţionată are forma următoare:

[ALL | FIRST] WHEN condiţie THEN INTO…[VALUES…] [INTO…[VALUES…] …] [WHEN condiţie THEN INTO…[VALUES…]

[INTO…[VALUES…] …] …] [ELSE INTO…[VALUES…] [INTO…[VALUES…] …] …]

Pentru a efectua o inserare multitabel necondiţionată, sistemul va executa câte o instrucţiune INSERT…INTO pentru fiecare linie returnată de subcerere.

Utilizând clauza inserare_condiţionată, decizia inserării unei linii depinde de condiţia specificată prin intermediul opţiunii WHEN. Expresiile prezente în aceste condiţii trebuie să facă referinţă la coloane returnate de subcerere. O instrucţiune de inserare multitabel poate conţine maxim 127 clauze WHEN.

Specificarea opţiunii ALL determină evaluarea tuturor condiţiilor din clauzele WHEN. Pentru cele a căror valoare este TRUE, se inserează înregistrarea specificată în opţiunea INTO corespunzătoare.

Opţiunea FIRST determină inserarea corespunzătoare primei clauze WHEN a cărei condiţie este evaluată TRUE. Toate celelalte clauze WHEN sunt ignorate.

Dacă nici o condiţie din clauzele WHEN nu este TRUE, atunci sistemul execută clauza INTO corespunzătoare opţiunii ELSE, iar dacă aceasta nu există, nu efectuează nici o acţiune.

Inserările multitabel pot fi efectuate numai asupra tabelelor, nu şi asupra vizualizărilor sau vizualizărilor materializate. De asemenea, acest tip de inserare nu se poate efectua asupra tabelelor distante. Subcererea dintr-o instrucţiune

Page 388: CURS BD Combinat

corespunzătoare unei inserări multitabel nu poate utiliza o secvenţă.

Exemplu: Se presupune că licitaţiile pentru achiziţionarea operelor de artă au loc

numai în zilele de miercuri. Fie tabelul opera_intrare (data_inceput, sapt_1, sapt_2, sapt_3, sapt_4), în care data_inceput reprezintă data primei zile de

miercuri din lună, iar sapt_i furnizează valoarea operelor achiziţionate în săptămâna respectivă. Considerând că în fiecare săptămână se achiziţionează o singură lucrare, să se insereze liniile corespunzătoare în tabelul opera.

INSERT ALL INTO opera (cod_opera, valoare, data_achizitiei) VALUES (secv_cod_opera.NEXT_VALUE, sapt_1, data_inceput) INTO opera (cod_opera, valoare, data_achizitiei) VALUES (secv_cod_opera.NEXT_VALUE, sapt_2,

data_inceput + 7)

INTO opera (cod_opera, valoare, data_achizitiei)

VALUES (secv_cod_opera.NEXT_VALUE, sapt_3,

data_inceput + 14)

INTO opera (cod_opera, valoare, data_achizitiei)

VALUES (secv_cod_opera.NEXT_VALUE, sapt_4,

data_inceput + 21)

SELECT data_inceput, sapt_1, sapt_2, sapt_3, sapt_4

FROM opera_intrare;

Exemplu:

Se consideră trei tabele care conţin informaţii referitoare la galerii, în funcţie

de numărul operelor găzduite de către acestea. Tabelele se numesc galerie_mica,

galerie_medie, galerie_mare după cum numărul de opere este mai mic decât 30,

cuprins între 31 şi 100, respectiv mai mare decât 101. Se presupune că structura

fiecăruia dintre tabele este alcătuită din coloanele cod_galerie, nume,

număr_opere. Să se insereze înregistrări în aceste tabele.

INSERT ALL

WHEN nr_opere <= 30 THEN

INTO galerie_mica

WHEN nr_opere > 30 AND nr_opere <= 100 THEN

INTO galerie_medie

WHEN nr_opere > 100 THEN

INTO galerie_mare

SELECT g.cod_galerie, nume_galerie, nr_opere

FROM galerie g, (SELECT cod_galerie, count(*) nr_opere

FROM opera

Page 389: CURS BD Combinat

GROUP BY cod_galerie) x

WHERE g.cod_galerie = x.cod_galerie;

Acelaşi rezultat se obţine prin utilizarea clauzei ELSE, astfel:

INSERT ALL

WHEN nr_opere <= 30 THEN

INTO galerie_mica

WHEN nr_opere > 30 AND nr_opere <= 100 THEN

INTO galerie_medie

ELSE

INTO galerie_mare

SELECT g.cod_galerie, nume_galerie, nr_opere

FROM galerie g, (SELECT cod_galerie, count(*) nr_opere

FROM opera

GROUP BY cod_galerie) x

WHERE g.cod_galerie = x.cod_galerie;

Exemplu:

Se consideră un tabel, galerie_g, având aceeaşi structură ca şi cele din

exemplul precedent. În acesta vor fi reţinute galeriile al căror nume începe cu litera

„G“. Se presupune că, dacă o galerie se încadrează în acest tabel, ea nu mai trebuie

să apară şi în cele referitoare la numărul de opere găzduite. Să se insereze

înregistrări în tabelele galerie_g, galerie_mica, galerie_medie, galerie_mare.

INSERT FIRST

WHEN UPPER(nume_galerie) LIKE 'G%' THEN

INTO galerie_g

WHEN nr_opere <= 30 THEN

INTO galerie_mica

WHEN nr_opere > 30 AND nr_opere <= 100 THEN

INTO galerie_medie

WHEN nr_opere > 100 THEN

INTO galerie_mare

SELECT g.cod_galerie, nume_galerie, nr_opere

FROM galerie g, (SELECT cod_galerie, count(*) nr_opere

FROM opera

GROUP BY cod_galerie) x

WHERE g.cod_galerie = x.cod_galerie;

Page 390: CURS BD Combinat

Comanda UPDATE

Instrucţiunea UPDATE este folosită pentru actualizarea datelor din

coloanele unui tabel (sau ale unei vizualizări).

Valorile câmpurilor care trebuie modificate pot fi furnizate explicit sau pot fi

obţinute în urma unei cereri SQL.

Sintaxa generală a instrucţiunii UPDATE:

UPDATE nume_tabel_sau_vizualizare

SET nume_coloana = expresie

[,nume_coloana = expresie...]

[ WHERE conditie];

Sau mai general, expresia poate fi o cerere

UPDATE nume_tabel_sau_vizualizare

SET (column1[,column2[,…]]) = (subquery) / column = expr /

(query)

[WHERE condition]

Observaţii:

Pentru a se putea executa instrucţiunea UPDATE, utilizatorul

care o lansează în execuţie trebuie să aibă acest privilegiu.

Dacă nu este specificată clauza WHERE se vor modifica toate

liniile.

Cererea trebuie să furnizeze un număr de valori corespunzător

numărului de coloane din paranteza care precede caracterul de egalitate.

Se remarcă următoarele:

Clauza SET conţine o listă cu una sau mai multe coloane,

împreună cu o expresie care specifică noua valoare pentru fiecare coloană.

Aceasta este o listă de perechi nume-valoare, separate prin virgule, cu un

operator de egalitate între fiecare nume şi valoare.

Page 391: CURS BD Combinat

Expresia poate fi o constantă, un alt nume de coloană sau orice

altă expresie pe care SQL o poate transforma într-o singură valoare, care

poate fi apoi atribuită coloanei respective.

Clauza WHERE conţine o expresie care limitează rândurile

actualizate. Dacă această clauză este omisă, motorul SQL va încerca să

actualizeze toate rândurile din tabel sau din vizualizare.

Exemple:

Un film a fost adăugat cu un preţ incorect. Instrucţiunea

următoare va actualiza două coloane din acelaşI rând a tabelului MOVIE.

UPDATE FILM

SET RETAIL_PRET_VHS = 29.95 ,

RETAIL_PRET_DVD = 34.95

WHERE FILM_ID = 21

Conducerea firmei de produse video a decis să crească salariul

tuturor funcţionarilor cu 10 procente. Această instrucţiune va actualiza o

singură coloană de pe mai multe rânduri, rotujind rezultatul la 2 zecimale cu

funcţia ROUND.

UPDATE ANGAJAT

SET ANGAJAT_PLATA_ORA = ROUND

(ANGAJAT_PLATA_ORA * 1.1, 2)

WHERE ANGAJAT_JOB_CATEGORY =‟C‟ ;

Exemple BD CARTE

Preţul cărţilor scrise de Lucian Blaga să fie modificat, astfel încât să fie egal

cu preţul celei mai scumpe cărţi de informatică din bibliotecă.

UPDATE carte

SET pret = (SELECT MAX(pret)

FROM carte

WHERE coded = ‟I‟)

WHERE autor = ‟Lucian Blaga‟;

Page 392: CURS BD Combinat

Exemplu:

Să se modifice preţul cărţilor din bibliotecă, care se găsesc într-un număr de

exemplare mai mic decât media numărului de exemplare pe bibliotecă. Noua

valoare a preţului să fie egală cu suma preţurilor cărţilor scrise de Zola.

UPDATE carte

SET pret = (SELECT SUM(pret)

FROM carte

WHERE autor = ‟Zola‟) WHERE nrex < (SELECT AVG(nrex) FROM carte);

Exemplu: Să se reducă cu 10% salariile redactorilor şefi care nu sunt asociaţi

nici unei publicaţii.

UPDATE salariat SET salariu = 0,9*salariu WHERE cod_salariat IN (SELECT cod_salariat FROM redactor_sef WHERE cod_salariat NOT IN (SELECT cod_salariat

FROM publicatie));

Exemplu:

Să se mărească cu 5% salariile redactorilor şefi ce coordoneaza publicaţiile

care au cel mai mare număr de frame-uri.

UPDATE salariat

SET salariu = 1,05*salariu

WHERE cod_salariat IN

(SELECT cod_salariat

FROM publicatie

WHERE nr_publicatie IN

(SELECT nr_publicatie

FROM frame

GROUP BY nr_publicatie

HAVING COUNT(*) > ALL

(SELECT COUNT(*)

FROM frame

GROUP BY nr_publicatie)));

Page 393: CURS BD Combinat

** Oracle9i permite utilizarea valorii implicite DEFAULT in comenzile

INSERT si UPDATE. Unei coloane i se atribuie valoarea implicită definită la

crearea sau modificarea structurii tabelului dacă nu se precizează nici o valoare sau

dacă se precizează cuvântul cheie DEFAULT în comenzile INSERT sau UPDATE.

Dacă nu este definită nici o valoare implicită pentru coloana respectivă, sistemul îi

atribuie valoarea null.

Exemplu:

UPDATE carte

SET pret = DEFAULT

WHERE codel = 77;

Exemplu BD GALERIE ARTA

a) Să se transfere în galeria 10 opera având codul 110.

UPDATE opera

SET cod_galerie = 10

WHERE cod_opera = 110;

b) Să se modifice informaţiile referitoare la opera având codul 120,

considerând că se află expusă în aceeaşi galerie şi a fost achiziţionată la aceeaşi

dată ca şi opera al cărei cod este 110.

UPDATE opera

SET (cod_galerie, data_achizitiei) =

(SELECT cod_galerie, data_achizitiei

FROM opera

WHERE cod_opera = 110)

WHERE cod_opera = 120;

c) Să se modifice copie_opera pe baza valorilor din tabelul opera. Se

consideră că operele care au acelaşi autor ca şi opera având codul 100 sunt expuse

în galeria ce conţine lucrarea al cărei cod este 110.

UPDATE copie_opera

SET cod_galerie = (SELECT cod_galerie

FROM opera

WHERE cod_opera = 110)

WHERE cod_autor = (SELECT cod_autor

FROM opera

Page 394: CURS BD Combinat

WHERE cod_opera = 100);

Cazurile în care instrucţiunea UPDATE nu poate fi executată sunt similare

celor în care eşuează instrucţiunea INSERT. Acestea au fost menţionate anterior.

Exemplu:

UPDATE opera

SET cod_galerie = 47

WHERE cod_galerie = 40;

Deoarece galeria având codul 47 nu există în tabelul „părinte“ (galerie),

instrucţiunea precedentă va genera eroarea „ORA-02291: integrity constraint

(STUDENT.SYS_C002773) violated - parent key not found“.

Exemplu:

Să se transfere în galeria având codul 50 toate operele din galeria 60, care

sunt create de Nicolae Grigorescu. Să se mărească cu 10% valoarea acestor opere.

UPDATE opera o

SET cod_galerie = 50,

valoare = valoare * 1.10

WHERE (SELECT INITCAP(nume) ||' '||INITCAP(prenume)

FROM artist

WHERE cod_artist = o.cod_artist)= 'Nicolae Grigorescu'

AND o.cod_galerie = 60;

Exemplu:

Să se actualizeze operele al căror autor este Ştefan Luchian astfel: codul

galeriei devine codul galeriei în care este expusă cea mai scumpă operă a artistului,

valoarea fiecărei opere va fi mărită cu 10% din media valorilor operelor din

galerie, iar data achiziţiei va fi considerată data celei mai recente achiziţii din

galerie.

UPDATE opera o

SET cod_galerie = (SELECT cod_galerie

FROM artist a, opera b

WHERE a.cod_artist = b.cod_artist

AND INITCAP(nume) = 'Luchian '

AND INITCAP(prenume) = 'Stefan'

AND valoare =

(SELECT MAX(valoare)

Page 395: CURS BD Combinat

FROM opera

WHERE cod_artist =

b.cod_artist)),

(valoare, data_achizitiei) =

(SELECT o.valoare + AVG(o2.valoare)*0.10,

MAX(o2.data_achizitiei)

FROM opera o2

WHERE o.cod_opera = o2.cod_opera)

WHERE cod_artist = (SELECT cod_artist

FROM artist

WHERE INITCAP(nume) = 'Luchian '

AND INITCAP(prenume) = 'Stefan');

Oracle9i introduce o nouă funcţionalitate, reprezentată de posibilitatea

utilizării valorilor implicite (DEFAULT) în instrucţiunile INSERT şi UPDATE.

Unei coloane i se atribuie valoarea implicită definită la crearea sau modificarea

structurii tabelului dacă:

nu se precizează nici o valoare;

se precizează cuvântul cheie DEFAULT în comenzile INSERT

sau UPDATE.

Dacă nu a fost definită nici o valoare implicită pentru coloana respectivă,

sistemul îi atribuie valoarea null. Cuvântul cheie DEFAULT nu poate fi specificat

la actualizarea vizualizărilor.

Exemplu:

Să se creeze tabelul test, având o coloană căreia i se specifică o valoare

implicită. Ulterior, să se modifice această valoare. Să se insereze şi să se

actualizeze câte o înregistrare din tabel, utilizând valoarea implicită.

CREATE TABLE test(

cod NUMBER PRIMARY KEY,

nume VARCHAR2(30) DEFAULT 'NECUNOSCUT');

ALTER TABLE test MODIFY (nume DEFAULT 'NEDEFINIT');

INSERT INTO test VALUES (1, DEFAULT);

UPDATE test SET nume = DEFAULT WHERE cod = 2;

Page 396: CURS BD Combinat

Comanda (Instrucţiunea) DELETE

Instrucţiunea DELETE şterge unul sau mai multe rânduri dintr-un tabel.

Instrucţiunea poate să folosească şi o vzualizare, dar numai dacă aceasta se bazează

pe un singur tabel (ceea ce înseamnă că instrucţiunile DELETE nu pot fi folosite

pentru vizualizări care conţin uniuni). În instrucţiunile DELETE nu sunt referite

niciodată coloane, doarece instrucţiunea şterge rânduri întregi de date, inclusiv

toate valorile datelor (toate coloanele) din rândurile afectate. Dacă vreţi să ştergeţi

o singură valoare din rândurile existente, folosiţi instrucţiunea UPDATE pentru a

înlocui valorile respective cu valori nule (presupunând că valorile nule sunt

permise în acele coloane).

Sintaxa generală a instrucţiunii DELETE este

DELETE FROM nume_tabel_sau_vizualizare [AS alias]

[ WHERE conditie ];

Se remarcă următoarele:

Comanda DELETE nu şterge structura tabelului.

Clauza WHERE este opţională. Totuşi, este folosită aproape întotdeauna,

deoarece o instrucţiune DELETE fără o clauză WHERE încearcă să şteargă

toate rândurile din tabel. În clauza WHERE pot fi folosite şi subcereri.

Atunci când este inclusă, clauza WHERE specifică rândurile care urmează

să fie şterse. Orice rând pentru care condiţia WHERE este evaluată ca

adevărată este şters din tabel.

Nu se pot şterge rânduri dacă se încalcă o restricţie referenţială. În general,

rândurile subordonate trebuie şterse înaintea rândurilor părinte.

Pentru a şterge linii identificate cu ajutorul valorilor din alte tabele, se

utilizează subcereri.

Comanda nu poate fi folosită pentru ştergerea valorilor unui câmp

individual. Acest lucru se poate realiza cu ajutorul comenzii UPDATE.

Exemple BD MOVIE

Să se şteargă filmul adăugat mai devreme (cu FILM_ID = 21 ).

Se observă că trebuie să se ştergă mai întâi rândurile corespondente din

Page 397: CURS BD Combinat

tabelele FILM_COPY şi FILM_LIMBA, deoarece acestea sunt rânduri

„copii” ale rândului din tabelul „FILM”

DELETE FROM FILM_COPY

WHERE FILM_ID = 21;

DELETE FROM FILM_LIMBA

WHERE FILM_ID = 21;

DELETE FROM FILM

WHERE FILM_ID = 21;

Să se şteargă din tabelul FILM_LIMBA toate rândurile pentru

limba spaniolă (COD_LIMBA='es' ). În multe implementări SQL se face

diferenţierea literelor mari de cele mici, caz în care valoarea codului de limbă

trebuie specificată cu litere mici pentru a se potrivi cu datele din tabel.

DELETE FROM FILM_LIMBA

WHERE COD_LIMBA =‟es‟;

Exemplu: Să se elimine cititorii care au numele „Popa‟şi cei care au restituit astăzi cel

puţin o carte.

DELETE FROM cititor WHERE nume=‟Popa‟ OR codec IN (SELECT codec FROM imprumuta WHERE data_ef=SYSDATE);

Exemplu: Să se elimine redactorii şefi care nu au coordonat nici o publicaţie.

DELETE FROM redactor_sef WHERE cod_salariat NOT IN (SELECT DISTINCT cod_salariat FROM publicatie);

Page 398: CURS BD Combinat

Exemplu: Să se şteargă salariul angajatului având codul 1279.

UPDATE salariat

SET salariu=null

WHERE cod_salariat = 1279;

Exemplu:

Urmatoarele doua comenzi sunt echivalente.

DELETE FROM opera

WHERE cod_opera = 777;

DELETE FROM (SELECT * FROM opera)

WHERE cod_opera = 777;

Exemplu:

Să se şteargă cartea cea mai scumpă

DELETE FROM carte

WHERE pret = (SELECT MAX(pret)

FROM carte);

Exemplu:

Pentru fiecare autor care are mai mult de 10 creaţii expuse în muzeu, să se

şteargă ultima operă creată de acesta.

DELETE FROM opera o1

WHERE cod_artist =

(SELECT cod_artist

FROM opera o2

WHERE cod_artist = o1.cod_artist

AND data_crearii =

(SELECT MAX(data_crearii)

FROM opera

WHERE cod_artist = o2.cod_artist)

AND 10 <

(SELECT COUNT(*)

FROM opera

WHERE cod_artist = o2.cod_artist));

Page 399: CURS BD Combinat

Exemple BD GALERIE de ARTA

a) Să se suprime înregistrarea corespunzătoare operei având codul 120.

DELETE FROM opera

WHERE cod_opera = 120;

Următoarea instrucţiune are acelaşi efect, dar utilizează o subcerere:

DELETE FROM (SELECT * FROM opera)

WHERE cod_opera = 120;

b) Să se şteargă întregul conţinut al tabelului copie_opera.

(nu se foloseste caluza where)

DELETE FROM copie_opera;

c) Să se şteargă toate operele care se află expuse într-o galerie al cărei nume

conţine şirul de caractere „muzeu“.

DELETE FROM opera

WHERE cod_galerie = (SELECT cod_galerie

FROM galerie

WHERE UPPER(nume_galerie)

LIKE '%MUZEU%');

Dacă se încearcă ştergerea unei înregistrări care conţine o valoare implicată

într-o constrângere de integritate, atunci va fi returnată o eroare.

Exemplu:

DELETE FROM galerie

WHERE cod_galerie = 40;

În urma execuţiei acestei instrucţiuni sistemul generează eroarea „ORA-

02292: integrity constraint (STUDENT.SYS_C002773) violated - child record

found“, datorată calităţii de cheie externă a coloanei cod_galerie în tabelul opera.

Există opere în galeria având codul 40 şi de aceea aceasta nu poate fi suprimată.

În cazul în care constrângerea de integritate referenţială a fost definită

utilizând opţiunea ON DELETE CASCADE, atunci instrucţiunea DELETE va

şterge atât liniile indicate, cât şi liniile „copil“ din tabelele corespunzătoare.

Page 400: CURS BD Combinat

LIMBAJUL PENTRU CONTROLUL DATELOR

Controlul unei baze de date cu ajutorul SQL-ului se refera la:

asigurarea confidentialitatii si securitatii datelor;

organizarea fizica a datelor;

realizarea unor performante;

reluarea unor actiuni in cazul unei defectiuni;

garantarea coerentei datelor in cazul prelucrarii concurente.

Sistemul de gestiune trebuie:

să pună la dispoziţia unui număr mare de utilizatori o mulţime

coerentă de date;

să garanteze coerenţa datelor în cazul manipulării simultane de

către diferiţi utilizatori.

Coerenţa este asigurată cu ajutorul conceptului de tranzacţie.

Tranzacţia este unitatea logică de lucru constând din una sau mai multe instrucţiuni

SQL, care trebuie să fie executate atomic (ori se execută toate, ori nu se execută

nici una!), asigurând astfel trecerea BD dintr-o stare coerentă în altă stare coerentă.

Dacă toate operaţiile ce constituie tranzacţia sunt executate şi devin

efective, spunem că tranzacţia este validată, iar modificările aduse de tranzacţie

devin definitive.

Dacă dintr-un motiv sau altul (neverificarea condiţiilor, accesul

imposibil) o operaţie a tranzacţiei nu a fost executată spunem că tranzacţia a fost

anulată. Modificările aduse de toate operaţiile tranzacţiei anulate sunt şi ele

anulate şi se revine la starea bazei de date de dinaintea tranzacţiei anulate.

Este posibil ca o tranzacţie să fie descompusă în subtranzacţii, astfel

încât dacă este necesar să se anuleze doar parţial unele operaţii.

Fiecare tranzacţie se poate termina:

“normal” (commit);

“anormal” (rollback).

Controlul tranzacţiilor constă în:

definirea începutului şi sfârşitului unei tranzacţii,

validarea sau anularea acesteia,

eventuală descompunere în subtranzacţii.

Limbajul pentru controlul datelor (LCD) permite salvarea informaţiei,

realizarea fizică a modificărilor în baza de date, rezolvarea unor probleme de

concurenţă.

Page 401: CURS BD Combinat

Limbajul conţine următoarele instrucţiuni:

COMMIT - folosită pentru permanentizarea modificărilor

executate asupra BD (modificările sunt înregistrate şi sunt vizibile tuturor

utilizatorilor);

ROLLBACK - folosită pentru refacerea stării anterioare a BD

(sunt anulate toate reactualizările efectuate de la începutul tranzacţiei);

SAVEPOINT - folosită în conjuncţie cu instrucţiunea

ROLLBACK, pentru definirea unor puncte de salvare în fluxul programului.

O tranzacţie constă:

dintr-o singură instrucţiune LDD;

dintr-o singură instrucţiune LCD;

din instrucţiuni LMD care fac schimbări consistente în date.

Tranzacţia începe:

după o comandă COMMIT,

după o comandă ROLLBACK,

după conectarea iniţială la Oracle,

când este executată prima instrucţiune SQL.

Tranzacţia se termină:

dacă sistemul cade;

dacă utilizatorul se deconectează;

dacă se dau comenzile COMMIT sau ROLLBACK ;

dacă se execută o comandă LDD.

După ce se termină o tranzacţie, prima instrucţiune SQL executabilă va

genera automat începutul unei noi tranzacţii.

Un commit apare automat:

când este executată o comandă LDD;

când este executată o comandă LCD;

după o ieşire normală din SQL*Plus fără specificarea explicită a

comenzilor COMMIT sau ROLLBACK.

Un rollback apare automat după o ieşire “anormală“ din SQL*Plus sau o

cădere sistem.

Din momentul în care s-a executat instrucţiunea COMMIT, BD s-a

modificat (permanent) în conformitate cu instrucţiunile SQL executate în cadrul

tranzacţiei care tocmai s-a terminat. Din acest punct începe o nouă tranzacţie.

Page 402: CURS BD Combinat

Dacă se foloseşte utilitarul SQL*Plus, există posibilitatea ca după fiecare

comandă LMD să aibă loc o permanentizare automată a datelor (un COMMIT

implicit). Acest lucru se poate realiza folosind comanda:

SET AUTO[COMMIT] {ON | OFF}

Comanda ROLLBACK permite restaurarea unei stări anterioare a BD.

ROLLBACK [TO [SAVEPOINT] savepoint];

Dacă nu se specifică nici un savepoint, toate modificările făcute în

tranzacţia curentă sunt anulate, iar dacă se specifică un anumit savepoint, atunci

doar modificările de la acel savepoint până în momentul respectiv sunt anulate.

Executarea unei instrucţiuni ROLLBACK presupune terminarea tranzacţiei curente

şi începerea unei noi tranzacţii.

Punctele de salvare pot fi considerate ca nişte etichete care referă o

submulţime a schimbărilor dintr-o tranzacţie, marcând efectiv un punct de salvare

pentru tranzacţia curentă. Punctele de salvare NU sunt obiecte ale schemei. Prin

urmare, nu sunt referite in DD.

Server-ul Oracle implementează un punct de salvare implicit pe care îl mută

automat după ultima comandă LMD executată. Dacă este creat un punct de salvare

având acelaşi nume cu unul creat anterior, cel definit anterior este şters automat.

SAVEPOINT savepoint;

Exemplu:

Comanda ROLLBACK nu va genera terminarea tranzacţiei.

COMMIT

INSERT …

SAVEPOINT a

UPDATE …

INSERT …

SAVEPOINT b

DELETE …

ROLLBACK TO a

Starea datelor înainte de COMMIT sau ROLLBACK este următoarea:

starea anterioară a datelor poate fi recuperată;

utilizatorul curent poate vizualiza rezultatele operaţiilor LMD

prin interogări asupra tabelelor;

alţi utilizatori nu pot vizualiza rezultatele comenzilor LMD

făcute de utilizatorul curent (read consistency);

Page 403: CURS BD Combinat

înregistrările (liniile) afectate sunt blocate şi, prin urmare, alţi

utilizatori nu pot face schimbări în datele acestor înregistrări.

Execuţia unei comenzi COMMIT implică anumite modificări.

Toate schimbările (INSERT, DELETE, UPDATE) din baza de

date făcute după anterioara comandă COMMIT sau ROLLBACK sunt

definitive. Comanda se referă numai la schimbările făcute de utilizatorul

care dă comanda COMMIT.

Toate punctele de salvare vor fi şterse.

Starea anterioară a datelor este pierdută definitiv.

Toţi utilizatorii pot vizualiza rezultatele.

Blocările asupra liniilor afectate sunt eliberate; liniile pot fi

folosite de alţi utilizatori pentru a face schimbări în date.

Execuţia unei comenzi ROLLBACK implică anumite modificări.

Anulează tranzacţia în curs şi toate modificările de date făcute

după ultima comandă COMMIT.

Sunt eliberate blocările liniilor implicate.

Nu şterge un tabel creat prin CREATE TABLE. Eliminarea

tabelului se poate realiza doar prin comanda DROP TABLE.

Exemplu:

Ce efect are următoarea secvenţă de instrucţiuni?

(a) SELECT *

FROM salariat;

(b) SAVEPOINT a;

(c) DELETE FROM salariat;

INSERT INTO salariat VALUES (18,‟Breaban‟,‟Marin‟,4,5000, ‟tehnored‟); INSERT INTO salariat VALUES (23,‟Popescu‟,‟Emil‟,7,40000,‟grafician‟); SAVEPOINT b;

(d) INSERT INTO salariat VALUES (29,‟‟,‟‟,5,3000000,‟tehnoredactor‟); SELECT AVG(salariu) FROM salariat;

Page 404: CURS BD Combinat

(e) ROLLBACK TO b; SELECT AVG(salariu) FROM salariat; (f) ROLLBACK TO a; INSERT INTO salariat VALUES (18,‟Ion‟,‟Mihai‟,5,580,‟redr_sef‟); COMMIT;

Consistenţa la citire Într-un sistem multi-user, sistemul Oracle furnizează read consistency la

nivel de instrucţiune SQL, adică o singură comandă SQL nu poate da rezultate care sunt contradictorii sau inconsistente. Read consistency asigură că fiecare utilizator “vede” datele aşa cum existau la ultimul commit, înainte să înceapă o operaţie LMD. Prin urmare, modificările efectuate asupra unei baze de date nu sunt vizibile decât după ce operaţia de actualizare a fost validată. Numai utilizatorul care a executat tranzacţia poate vedea modificările făcute de el în cursul acestei tranzacţii.

Modelul multiversiune, furnizat de Oracle, asigură consistenţa la citire:

garantează că setul de date văzut de orice instrucţiune SQL este consistent şi nu se schimbă în timpul execuţiei unei instrucţiuni (Oracle asigură o consistenţă la citire la nivel de instrucţiune);

operaţiile de citire (SELECT) nu trebuie să vadă datele care sunt în proces de schimbare;

operaţiile de scriere (INSERT, DELETE, UPDATE) nu trebuie să afecteze consistenţa datelor şi să întrerupă sau să intre în conflict cu alte operaţii de scriere concurente.

Cum se implementează modelul multiversiune? Dacă asupra bazei este executată o comandă LMD, server-ul Oracle face o copie a datelor dinainte de modificare şi o depune în segmentul rollback (undo).

Toţi utilizatorii (cu excepţia celor care modifică datele) vor vedea datele cum sunt înainte de modificare (văd conţinutul segmentului undo). Dacă comanda LMD este commit, atunci schimbările din baza de date devin vizibile oricărui utilizator care foloseşte instrucţiunea SELECT. Când se termină tranzacţia, spaţiul ocupat în segmentul undo de “vechea” dată este liber pentru reutilizare. Server-ul Oracle asigură astfel o vizualizare consistentă a datelor în orice moment.

Page 405: CURS BD Combinat

Carte

Controlul datelor (LCD)

Tranzacţia este o unitate logică de lucru, constituită dintr-o secvenţă de

comenzi care trebuie să se execute atomic pentru a menţine consistenţa datelor. Server-ul Oracle asigură consistenţa datelor prin intermediul tranzacţiilor,

inclusiv în eventualitatea unei anomalii a unui proces sau a sistemului. Tranzacţiile oferă mai multă flexibilitate şi control în modificarea datelor.

Controlul tranzacţiilor se realizează prin utilizarea instrucţiunilor limbajului de control al datelor: COMMIT, ROLLBACK, SET TRANSACTION, SAVEPOINT.

Tranzacţiile pot fi de tip LMD, LDD sau LCD. Tranzacţiile LDD şi LCD

constau dintr-o singură instrucţiune LDD, respectiv LCD. Tranzacţiile LMD

constau dintr-o succesiune de instrucţiuni LMD care determină o modificare

consistentă a datelor. De exemplu, un transfer de fonduri între două conturi

bancare presupune debitarea unui cont şi creditarea celuilalt cu aceeaşi sumă.

Ambele acţiuni trebuie fie să eşueze, fie să se încheie cu succes. Creditarea nu

trebuie salvată fără să fie salvată şi operaţia de debitare.

Procesarea tranzacţiilor

Modificările făcute asupra datelor în timpul unei tranzacţii sunt temporare

până când tranzacţia este salvată. Operaţiile de prelucrare a datelor afectează iniţial

un buffer al bazei. Prin urmare, starea precedentă a datelor poate fi recuperată.

În general, o tranzacţie începe atunci când este întâlnită prima instrucţiune

LMD şi se termină la:

apariţia unei instrucţiuni LDD;

emiterea unei instrucţiuni LCD;

părăsirea mediului SQL*Plus;

defectarea staţiei de lucru sau la înregistrarea unei întreruperi

a sistemului.

Execuţia unei instrucţiuni LDD determină salvarea automată a modificărilor

survenite pe perioada tranzacţiei. Server-ul Oracle generează o operaţie COMMIT

implicită înainte şi după orice instrucţiune LDD. Aşadar, chiar dacă instrucţiunea

LDD nu este executată cu succes, instrucţiunea anterioară acesteia nu mai poate fi

anulată întrucât server-ul a efectuat deja operaţia COMMIT.

Instrucţiunile COMMIT şi ROLLBACK încheie tranzacţia curentă prin

Page 406: CURS BD Combinat

definitivarea, respectiv anularea tuturor modificărilor aflate în aşteptare. Aceste

instrucţiuni permit:

asigurarea consistenţei datelor;

previzualizarea modificărilor asupra datelor înainte ca acestea

să devină permanente;

gruparea logică a operaţiilor.

Ieşirea din mediul SQL*Plus fără lansarea unei instrucţiuni COMMIT sau

ROLLBACK are ca efect salvarea automată a tranzacţiei curente.

Atunci când intervine o anomalie (cădere) a sistemului sau închiderea

anormală a sesiunii SQL*Plus, întreaga tranzacţie curentă este anulată automat

(ROLLBACK). Acest fapt împiedică eroarea să cauzeze modificări nedorite ale

datelor şi determină revenirea la starea din momentul ultimei operaţii COMMIT.

O ieşire normală din iSQL*Plus are loc prin apăsarea butonului Exit.

Terminarea normală a unei sesiuni SQL*Plus are loc prin execuţia comenzii EXIT.

În SQL*Plus, închiderea ferestrei este interpretată ca ieşire anormală.

Interfaţa SQL*Plus pune la dispoziţie variabila de mediu AUTOCOMMIT,

care poate avea valorile ON sau OFF. Dacă această variabilă are valoarea ON,

atunci efectul fiecărei instrucţiuni LMD se definitivează imediat ce instrucţiunea a

fost executată. Dacă variabila AUTOCOMMIT are valoarea OFF, definitivarea

unei tranzacţii va avea loc la execuţia comenzii COMMIT sau în cazurile de salvare

automată a tranzacţiilor, prezentate anterior.

După încheierea unei tranzacţii, următoarea instrucţiune SQL executabilă

marchează automat începutul unei noi tranzacţii.

Comanda COMMIT

Instrucţiunea COMMIT determină încheierea tranzacţiei curente şi

permanentizarea modificărilor care au intervenit pe parcursul acesteia.

Instrucţiunea suprimă toate punctele intermediare definite în tranzacţie şi

eliberează blocările tranzacţiei. De asemenea, instrucţiunea poate fi utilizată pentru

terminarea unei tranzacţii read-only începută printr-o comandă SET

TRANSACTION.

Sistemul lansează implicit o comandă COMMIT înainte şi după orice

instrucţiune LDD. Sintaxa corespunzătoare comenzii COMMIT este următoarea:

COMMIT [WORK] [COMMENT 'text' | FORCE 'text' [, nr_întreg] ];

Opţiunea WORK a fost introdusă din motive de conformitate cu standardul

SQL. Instrucţiunile COMMIT şi COMMIT WORK sunt echivalente.

Clauza COMMENT permite specificarea unui comentariu care va fi asociat

Page 407: CURS BD Combinat

tranzacţiei curente. Textul care îi urmează poate ocupa maxim 255 octeţi şi va fi

stocat în vizualizarea DBA_2PC_PENDING din dicţionarul datelor.

Într-un sistem distribuit, clauza FORCE permite salvarea manuală a unei

tranzacţii distribuite in-doubt (în care operaţia COMMIT a fost întreruptă de o

cădere a sistemului sau a reţelei). Textul care îi urmează conţine identificatorul

local sau global al tranzacţiei. Pentru a afla aceşti identificatori se poate consulta,

de asemenea, vizualizarea DBA_2PC_PENDING din dicţionarul datelor.

Pentru a atribui tranzacţiei un system change number (SCN) se specifică un

număr întreg în clauza FORCE. Valoarea unui SCN este mărită ori de câte ori este

salvată o tranzacţie. Acest număr are un rol important în asigurarea consistenţei la

citire. În general, o cerere citeşte un bloc de date care are ca atribut un SCN

corespunzător ultimei modificări a blocului respectiv. Dacă acest SCN este mai

mare decât cel citit la începutul interogării, înseamnă că blocul a fost modificat

ulterior lansării cererii. Prin urmare, trebuie găsită o versiune mai veche a blocului

în segmentele de anulare.

O instrucţiune COMMIT care conţine clauza FORCE permanentizează

numai tranzacţia specificată şi nu o afectează pe cea curentă. Prezenţa acestei

clauze nu este permisă în PL/SQL.

Exemplu:

Să se insereze o înregistrare în tabelul artist şi să se permanentizeze

modificarea.

INSERT INTO artist(cod_artist, nume, prenume)

VALUES (189, 'Pallady', 'Theodor');

COMMIT;

Înainte de operaţia COMMIT, utilizatorul curent poate vizualiza rezultatele

comenzilor LMD prin interogarea tabelelor. Efectele acestor operaţii nu sunt

vizibile celorlalţi utilizatori. Server-ul Oracle asigură consistenţa la citire, astfel

încât fiecare utilizator vizualizează datele în starea corespunzătoare ultimei operaţii

COMMIT efectuate asupra lor. Liniile afectate de tranzacţia curentă sunt blocate,

nefiind posibilă modificarea lor de către ceilalţi utilizatori.

Dacă mai mulţi utilizatori modifică simultan acelaşi tabel, fiecare dintre

aceştia poate consulta numai propriile modificări. Pe măsură ce operaţia COMMIT

este executată de către utilizatori, actualizările efectuate de aceştia devin vizibile.

În urma execuţiei instrucţiunii COMMIT, modificările asupra datelor sunt

scrise în baza de date, iar starea precedentă a datelor este pierdută definitiv. În

acest fel, rezultatele tranzacţiei pot fi vizualizate de către toţi utilizatorii. Blocările

asupra liniilor afectate sunt eliberate, astfel că înregistrările devin disponibile

Page 408: CURS BD Combinat

celorlalţi utilizatori pentru a efectua noi actualizări. După operaţia COMMIT, toate

punctele intermediare (SAVEPOINT) ale tranzacţiei respective sunt şterse.

Comanda ROLLBACK

Atunci când o linie este modificată, valorile anterioare ale coloanelor

actualizate sunt salvate într-un segment de reluare. Dacă tranzacţia este anulată,

server-ul Oracle va rescrie valorile din acest segment în linia tabelului.

Pentru a renunţa la modificările efectuate se utilizează instrucţiunea

ROLLBACK. În urma execuţiei acesteia, se încheie tranzacţia, se anulează

modificările asupra datelor, se restaurează starea lor precedentă şi se eliberează

blocările asupra liniilor.

O parte a tranzacţiei poate fi anulată automat printr-o operaţie ROLLBACK

implicită dacă a fost detectată o eroare în timpul execuţiei unei instrucţiuni. Dacă o

singură instrucţiune LMD eşuează în timpul execuţiei unei tranzacţii, efectul său

este anulat de un ROLLBACK la nivel de instrucţiune, dar schimbările efectuate de

instrucţiunile LMD precedente nu sunt anulate. Acestea din urmă pot fi salvate sau

anulate explicit de către utilizator.

Sintaxa instrucţiunii ROLLBACK este următoarea:

ROLLBACK [WORK]

[TO [SAVEPOINT] pct_intermediar | FORCE 'text'];

Semnificaţiile opţiunilor WORK şi FORCE sunt similare celor prezentate în

cadrul instrucţiunii COMMIT.

În clauza TO SAVEPOINT se poate specifica punctul intermediar până la

care se doreşte anularea tranzacţiei. În absenţa acestei clauze, întreaga tranzacţie

este anulată. O tranzacţie in-doubt nu poate fi anulată manual până la un punct

intermediar.

Dacă a fost definit un punct intermediar prin instrucţiunea SAVEPOINT

nume, instrucţiunea ROLLBACK TO SAVEPOINT nume determină întoarcerea

tranzacţiei curente la punctul intermediar specificat.

În felul acesta se revine într-o stare anterioară a tranzacţiei şi se anulează

modificările care au survenit după definirea punctului intermediar. De asemenea,

sunt şterse punctele intermediare ulterioare acestuia şi sunt eliberate toate blocările

asupra tabelelor sau liniilor, efectuate după punctul intermediar respectiv.

Comanda SAVEPOINT

Instrucţiunea SAVEPOINT marchează un punct intermediar în procesarea

tranzacţiei. În acest mod este posibilă împărţirea tranzacţiei în subtranzacţii.

Page 409: CURS BD Combinat

Această instrucţiune nu face parte din standardul ANSI al limbajului SQL.

Punctele intermediare definite în procesarea unei tranzacţii nu sunt obiecte

ale schemei şi nu pot fi referite în dicţionarul datelor. Nu există nici o modalitate

de a lista punctele intermediare definite. Dacă este creat un al doilea punct

intermediar având acelaşi nume cu un punct intermediar precedent, acesta din urmă

este şters.

Instrucţiunea SAVEPOINT are sintaxa:

SAVEPOINT nume_pct_intermediar;

Exemplu:

Să se mărească prin 20%, respectiv 50% valoarea operelor care au codurile

100, respectiv 150. Să se verifice că valoarea totală a operelor din galerie nu

depăşeşte 7 000 000, iar apoi să se reactualizeze valoarea operei având codul 150,

mărind-o cu 40%.

UPDATE opera

SET valoare = valoare * 1.2

WHERE cod_opera = 100;

SAVEPOINT val_100;

UPDATE opera

SET valoare = valoare * 1.5

WHERE cod_opera = 150;

SAVEPOINT val_150;

SELECT SUM(valoare)

FROM opera;

ROLLBACK TO SAVEPOINT val_100;

UPDATE opera

SET valoare = valoare * 1.4

WHERE cod_opera = 150;

COMMIT;

Page 410: CURS BD Combinat

Consistenţa la citire

Utilizatorii pot accesa baza de date prin operaţii de citire (instrucţiuni

SELECT) sau prin operaţii de scriere (instrucţiuni INSERT, UPDATE, DELETE).

Consistenţa la citire este necesară pentru a asigura că:

datele vizualizate de către utilizatorii care scriu şi citesc din

baza de date sunt consistente;

utilizatorii care citesc din baza de date nu pot vizualiza starea

datelor care sunt în curs de modificare;

utilizatorii care scriu în baza de date sunt asiguraţi că

modificările asupra acesteia se realizează în mod consistent;

modificările pe care le efectuează un utilizator nu intră în

conflict cu cele ale altui utilizator.

Scopul consistenţei la citire este ca fiecare utilizator să vizualizeze datele în

starea existentă la ultima operaţie COMMIT.

Consistenţa la citire se implementează automat, prin păstrarea unei copii

parţiale a bazei de date în segmentele de reluare. Atunci când se efectuează o

operaţie INSERT, UPDATE sau DELETE, server-ul Oracle reţine o copie a datelor

în starea dinaintea modificării şi o scrie într-un segment de reluare.

Pentru toţi utilizatorii care citesc din baza de date, cu excepţia celui care a

iniţiat modificarea, datele sunt vizibile în starea dinaintea începerii reactualizării.

Aceşti utilizatori vizualizează starea datelor din segmentul de reluare. Astfel, se

garantează că utilizatorii citesc date consistente care nu sunt în curs de schimbare.

După ce se efectuează operaţia COMMIT asupra tranzacţiei, modificările

făcute în baza de date devin vizibile tuturor. Server-ul Oracle creează vizualizări

consistente la citire pentru interogările care au început înainte ca tranzacţia să fie

salvată. Apoi, spaţiul ocupat de datele vechi în segmentul de reluare va fi eliberat

pentru a fi refolosit.

Dacă se efectuează operaţia ROLLBACK asupra tranzacţiei, modificările

sunt anulate. Astfel, versiunea datelor salvate în segmentul de reluare este rescrisă

în tabel, iar baza de date revine în starea de dinaintea începerii tranzacţiei.