Documente Academic
Documente Profesional
Documente Cultură
CURS: SGBD
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 pe rsistente, 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.
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.
• 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.
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.
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 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ă.
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Ńă.
a
administratorul c procesor c administratorul
DESCRIERE
bazei de date schema aplicaŃiilor
conceptuală
b
f d
g e
procesor dicŃionarul procesor
schema datelor schema
internă externă
l i
PRELUCRARE
sistem program
de aplicaŃii
alocare extern
h h
m
programator
aplicaŃie utilizatori
memorii
secundare
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.).
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.
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.
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;
• 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.
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.
SQL*PLUS
SQL*Plus instrument puternic care este utilizat în dezvoltarea aplicaŃiilor pentru baza de
date Oracle.
SQL*Plus instrument flexibil care poate fi executat pe toate platformele pe care se instalează
produsul Oracle.
Conexiune la SQL*Plus
După ce utilizatorul se conectează la SQL*Plus, sistemul afişează un prompt (SQL>) şi
aşteaptă comenzile utilizatorului. Utilizatorul poate da:
• comenzi SQL pentru accesarea bazei de date;
• blocuri PL/SQL pentru accesarea bazei de date;
• comenzi SQL*Plus.
Suprimarea unei legături între două BD, una locală şi una la distanŃă:
DROP [PUBLIC] DATABASE LINK nume_legatura.
Câteva dintre cele mai importante comenzi disponibile în SQL*Plus :
ACCEPT – citeşte o variabilă de intrare de la utilizator;
DEFINE – declară o variabilă (DEF);
DESCRIBE – listează atributele tabelelor sau ale altor obiecte (DESC);
EDIT – invoca editorul, salveaza continutul buffer-ului in fisierul afiedt.buf;
EXIT sau QUIT – deconectează utilizatorul şi încheie sesiunea SQL*Plus;
GET – caută un fişier SQL şi îl depune în buffer-ul SQL;
HOST – execută o comandă a sistemului de operare (!);
LIST – afişează ultima comandă executată din buffer-ul SQL (L);
PROMPT – afişează un text pe ecran;
RUN – listează şi execută comanda salvată în buffer-ul SQL (/);
SAVE – salvează comanda din buffer-ul SQL într-un fişier script;
SET – modifică variabilele de mediu specifice SQL*Plus;
SHOW – afişează setările variabilelor de mediu SQL*Plus;
SPOOL – copiază ieşirea unei comenzi într-un fişier;
START – execută un script SQL (@).
Salvarea comenzilor
Comanda SQL, care este introdusă interactiv prin interfaŃa SQL*Plus, este memorată într-un
buffer SQL. Ea poate fi modificată sau executată de mai multe ori, atâta timp cât utilizatorul nu a
introdus o nouă comandă sau nu a şters explicit buffer-ul SQL (CLEAR BUFFER). Cererea nouă va
şterge vechea cerere din buffer.
Utilizatorul poate salva una sau mai multe comenzi într-un fişier, ce ulterior poate fi încărcat,
modificat sau executat. Extensia implicită a fişierului: .sql.
SAVE nume_fisier [CREATE|REPLACE|APPEND]
SQL*Plus SERVER
RAPORT
(formatat)
Display calculator
SAVE alfa
EDIT alfa
@alfa
Editarea comenzilor
Editorul integrat SQL *Plus (mini-editor mod linie) se încarcă prin:
EDIT [nume_fisier[.extensie]]
Dacă se doreşte lansarea în execuŃie a unui alt editor, se modifică variabila EDITOR cu
ajutorul comenzii DEFINE. De exemplu:
DEFINE _EDITOR = vi
SQL*Plus păstrează în memorie ultima comandă executată. Comenzile SQL*Plus nu sunt
depuse în buffer-ul SQL. Ele se dau secvenŃial, câte una la un moment dat. Dacă comanda este prea
lungă, ea va fi continuată pe linia următoare tastând caracterul „–” la sfârşitul liniei, înainte de a tasta
RETURN.
Pentru editarea comenzilor SQL şi a blocurilor PL/SQL se pot folosi:
• A[PPEND] text – adaugă textul specificat la sfârşitul liniei curente din buffer-ul SQL;
• C[HANGE] separator old [separator [new [separator]]] – schimbă textul old cu textul
new (ca separator se poate folosi orice caracter care nu este alfanumeric);
• DEL {n | n m | n * | n LAST | * | * n | * LAST | LAST} – şterge una sau mai multe linii
din buffer-ul SQL (caracterul “*” indică linia curentă); DEL fără nici o clauză are ca efect
ştergerea liniei curente;
• CL[EAR] BUFF[ER] – sterge toate liniile din buffer-ul SQL;
• I[NPUT] [text] – adaugă una sau mai multe linii de text după linia curentă din buffer;
• n text – inlocuieste linia n prin text;
• L[IST] {n | n m | n * | n LAST | * | * n | * LAST | LAST} – listează una sau mai multe
linii din buffer (caracterul “*” indică linia curentă); LIST fără nici o clauză listează toate
liniile din buffer.
Comenzi interactive
SQL*Plus dispune de comenzi ce permit comunicarea directă cu utilizatorul:
• comanda PAUSE permite afişarea unei linii vide sau unui text suspendând temporar
acŃiunea şi aşteptând un RETURN de la utilizator;
• comanda PROMPT trimite o linie goală sau un mesaj pe ecran;
• comanda ACCEPT permite citirea unei linii de pe ecran şi atribuirea valorii sale unei
variabile (utilizator) specificate (variabila poate să fie deja definită prin comanda
DEFINE).
ACCEPT variabila [NUMBER | CHAR | DATE]
[FORMAT format] [PROMPT text | NOPROMPT] [HIDE]
ObservaŃii:
• tipul implicit al variabilei este CHAR;
• textul de la opŃiunea PROMPT este tipărit înainte ca utilizatorul să dea valoarea efectivă;
• opŃiunea HIDE face ca valoarea dată de utilizator să fie mascată (de exemplu, o parolă);
• opŃiunea FORMAT indică modul de formatare;
• variabila de substituŃie, dacă este prezentă, nu trebuie prefixată de simbolul “&”.
Exemplu:
ACCEPT alfa PROMPT ’Numarul de exemplare:’
ACCEPT beta PROMPT ’Numele autorului:’
SELECT *
FROM carte
WHERE nrex = &alfa
AND autor = ’&beta’;
Setări în SQL*Plus
Pentru a preciza opŃiunile de lucru cu SQL*Plus se utilizează comanda SET. Setările SQL
standard se găsesc în fişierul login.sql, care poate fi modificat pentru a conŃine setări adiŃionale. Când
se termină sesiunea toate setările sunt pierdute.
Comanda SET are două forme sintactice:
• una din ele se foloseşte ca Help pentru utilizator;
• cealaltă se foloseşte pentru setarea variabilelor sistem.
O variabilă sistem este un câmp rezervat în care se reŃine o valoare de către sistemul Oracle,
valoare care indică o stare a sistemului. Pentru a afişa valorile tuturor variabilelor de mediu la un
moment dat se utilizeaza comanda SHOW ALL.
SET variabila_sistem valoare
Parametrul variabila_sistem poate lua oricare din valorile care apar la execuŃia comenzii
SHOW ALL.
În continuare sunt prezentate numai o parte a acestor setări (în special cele folosite la
formatarea rapoartelor) împreună cu valorile pe care le poate lua parametrul valoare.
• SET RECSEP {WR[APPED] | EA[CH] | OFF} – controlează tipărirea separatorilor de
înregistrări. Cele trei valori posibile au următoarele semnificaŃii:
- WRAPPED tipăreşte un separator după fiecare linie a unei înregistrări (chiar dacă
aceasta cuprinde mai multe linii);
- EACH face acelaşi lucru, dar numai la sfârşitul unei înregistrări;
- OFF anulează tipărirea unui separator.
• SET RECSEPCHAR {_ | c} – setează caracterul ce separă înregistrările;
• SET SPACE {1 | n} – setează numărul de spaŃii între coloane.
• SET WRA[P] {OFF | ON} – specifică modul de afişare a înregistrărilor (trunchiat sau
pe o linie).
• SET NULL text – specifică textul afişat în locul valorii NULL.
• SET HEADS[EP] {| | c | OFF | ON} – specifică caracterele ce separă numele
coloanelor de înregistrări.
• SET UND[ERLINE] {_ | c | OFF | ON} – specifică caracterul folosit pentru
sublinierea numelor coloanelor.
• SET NEWP[AGE] {1 | n | NONE} – setează numărul de linii vide lăsate la începutul
fiecărei pagini.
• SET TERM[OUT] {OFF | ON} – controlează afişarea output-ului generat de comenzi
executate dintr-un script.
• SET PAGES[IZE] {24 | n} – specifică numărul de linii afişate pe pagină (n implicit
este 24; se poate seta la valoarea 0 pentru a suprima afişarea numelor coloanelor, a titlului
unui raport).
• SET FEED[BACK] {6 | n | OFF | ON} – controlează afişarea numărului de
înregistrări furnizate ca rezultat de o comandă SELECT.
• SET ECHO {OFF | ON} – controlează afişarea comenzilor dintr-un script SQL lansat
cu comanda START, pe măsură ce acestea sunt executate.
Comanda SPOOL permite salvarea rezultatelor unei interogări într-un fişier indicat ca
parametru. Ea are următoarea sintaxă:
SQL
Structured Query Language (SQL) este un limbaj universal care poate fi utilizat pentru a
defini, interoga, reactualiza şi gestiona baze de date relaŃionale. SQL este accesibil utilizatorilor
începători, dar în acelaşi timp poate oferi programatorilor experimentaŃi facilităŃi deosebite. SQL este
un limbaj non-procedural, adică se specifică ce informaŃie este solicitată, dar nu modul cum se obŃine
această informaŃie. SQL poate fi utilizat autonom sau prin inserarea comenzilor sale într-un limbaj de
programare. SQL a sistemului Oracle este o extensie a normei SQL89 şi o implementare a normei
SQL92.
În SQL se disting trei familii de comenzi:
• Comenzi pentru definirea datelor, care permit descrierea (definirea) structurii obiectelor
ce modelează sistemul studiat. Aceste comenzi definesc limbajul de definire a datelor
(LDD).
• Comenzi pentru prelucrarea datelor, ce permit consultarea, reactualizarea, suprimarea sau
inserarea datelor. Aceste comenzi definesc limbajul de prelucrare a datelor (LMD).
• Comenzi pentru controlul datelor, care permit asigurarea confidenŃialităŃii şi integrităŃii
datelor, salvarea informaŃiei, realizarea fizică a modificărilor în baza de date, rezolvarea
unor probleme de concurenŃă. Aceste comenzi definesc limbajul de control al datelor
(LCD).
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.
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, LDD 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.
Tipuri de date
Pentru memorarea datelor numerice, tipurile cele mai frecvent folosite sunt: NUMBER,
INTEGER, FLOAT, DECIMAL.
Pentru memorarea şirurilor de caractere, cele mai frecvent tipuri de date utilizate sunt:
CHAR, VARCHAR2 şi LONG.
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ă.
Alte tipuri de date scalare furnizate de SQL sunt NCHAR şi NVARCHAR2, folosite pentru
reprezentarea caracterelor limbilor naŃionale.
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.
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.
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 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;
Tabele
Î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.
Comanda CREATE TABLE permite crearea unui tabel relaŃional sau a unui tabel obiect.
Tabelul relaŃional reprezintă structura fundamentală pentru stocarea datelor utilizatorului. Un tabel
obiect utilizează un tip obiect pentru definiŃia unei singure coloane şi este folosit pentru a stoca
instanŃele unui obiect particular.
Pentru a crea un tabel, utilizatorul trebuie să aibă acest privilegiu şi să dispună de spaŃiul de
memorie în care să creeze obiectul. La nivelul schemei sale, un utilizator are toate privilegiile.
CREATE TABLE [<nume_schema>.] <nume_tabel> (
<nume_coloana_1> <tip_date> [DEFAULT <expresie>],
…
<nume_coloana_n> <tip_date> [DEFAULT <expresie>]);
Comanda poate conŃine opŃional clauza TABLESPACE, care specifică spaŃiul tabel în care va
fi stocat tabelul. De asemenea, poate conŃine opŃional clauza STORAGE care este folosită pentru
setarea parametrilor de stocare prin intermediul cărora se specifică mărimea şi modul de alocare a
extinderilor segmentului tabel. La crearea unui tabel nu este nevoie să se specifice dimensiunea
maximă a acestuia, ea fiind determinată până la urmă de marimea spaŃiului alocat spaŃiului tabel în
care este creat tabelul.
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.
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));
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.
Exemplu:
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),…
coded CHAR(5)
CONSTRAINT nn_coded NOT NULL
CONSTRAINT ce_coded
REFERENCES domeniu(coded));
Exemplu:
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),…
coded CHAR(5) NOT NULL,
CONSTRAINT cp_carte PRIMARY KEY (codel),
CONSTRAINT ce_coded
FOREIGN KEY (coded)
REFERENCES domeniu(coded));
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.
Indecşi
Exemplu:
Să se obŃină informaŃii referitoare la indecşii tabelului carte.
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 = ’carte’;
SecvenŃe
O secvenŃă este un obiect în baza de date care serveşte pentru a genera întregi unici în
sistemele multi-utilizator, evitând apariŃia conflictelor şi a blocării.
SecvenŃele sunt memorate şi generate indiferent de tabele aceeaşi secvenŃă poate fi
utilizată pentru mai multe tabele. O secvenŃă poate fi creată de un utilizator şi poate fi partajată de
mai mulŃi utilizatori.
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}]
CACHE k | NOCACHE specifică numărul de valori alocate de server-ul Oracle pe care le va
păstra în memoria cache pentru a oferi utilizatorilor un acces rapid (implicit sunt alocate 20 de
valori);
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.
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 1
INCREMENT BY 1;
INSERT INTO domeniu
VALUES (domeniuseq.NEXTVAL,’Informatica’);
SELECT INCREMENT, START, MAXVALUE, MINVALUE,
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ă.
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.
Comentarii
Sistemul Oracle oferă posibilitatea de a comenta obiectele create, printr-un text care este
inserat în dicŃionarul datelor. Comentariul se poate referi la tabele, vizualizări, clişee sau coloane.
COMMENT ON {TABLE nume_obiect | COLUMN
nume_obiect.nume_coloana} IS ’text comentariu’
Sinonime
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.
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.
CREATE [PUBLIC] SYNONYM [schema.]nume_sinonim
FOR [schema.]obiect
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
Vizualizări
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.
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.
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ă.
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. 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';
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.
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 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ă;
• î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';
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:
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:
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ă;
• 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.
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);
Una dintre cele mai importante comenzi ale limbajului de prelucrare a datelor este 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 [PARTITION (partition_name)] |
[THE] (subquery)} [alias_tabel] }
[WHERE condiŃie]
[GROUP BY listă de expresii
[HAVING condiŃie]]
[ORDER BY {expresie | poziŃie | c_alias} [ASC | DESC]]
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.
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.
Exemplu:
Valorile de tip caracter şi de tip dată calendaristică trebuie să fie incluse între apostrofuri.
SELECT codel
FROM imprumuta
WHERE datares >= ’01–JAN–03’;
Exemplu:
Să se obŃină titlurile şi numărul de exemplare ale cărŃilor scrise de autorii al căror nume
începe cu litera S.
SELECT titlu, nrex
FROM carte
WHERE autor LIKE ’S%’;
Exemplu:
Să se afişeze data şi ora curentă.
SELECT TO_CHAR(SYSDATE,’DD/MM/YY HH24:MI:SS’)
FROM DUAL;
Exemplu:
Utilizând ideea că directorul este salariatul care nu are şef, să se tipărească numele
directorului.
SELECT ename,NVL(TO_CHAR(mgr),’Nu are sef’)
FROM emp
WHERE mgr IS NULL;
Intrebari
NVL(x, y) x si y trebuie sa fie de acelasi tip!
NVL(comm, 'nu are') este corect?
SELECT titlu.pret_total
FROM (SELECT titlu, pret*nrex pret_total
FROM carte)
WHERE pret_total>1000;
<nume angajat> castiga <salariu> lunar, dar doreste <salariu de 3 ori mai mare>
SELECT ename||'castiga'||sal||'lunar, dar doreste'
||sal*3 "salariul ideal"
FROM emp;
De ce este incorect?
SELECT titlu, MIN(pret)
FROM carte;
Clauza GROUP BY
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.
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;
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;
Î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:
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
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.
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;
OperaŃii de compunere
Un join simplu (natural join) este o instrucŃiune SELECT care returnează linii din două sau mai
multe tabele. Este preferabil ca tabelul care are linii mai puŃine să fie al doilea în operaŃia de
compunere. Comanda durează mai puŃin, dacă tabela este indexată după coloana, relativ la care se
face compunerea. Compunerea a n tabele cere minim (n-1) condiŃii de join.
Exemplu:
Să se obŃină codurile şi titlurile cărŃilor împrumutate.
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.
Pentru a simplifica scrierea şi pentru a elimina ambiguităŃile care pot să apară este necesară
folosirea alias-ului pentru tabele. Alias-ul este valid doar pentru instrucŃiunea SELECT curentă.
Exemplu:
Să se obŃină pentru fiecare salariat numele, salariul şi grila de salarizare (Θ join).
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 Oszu (self join).
Exemplu:
Să se obŃină informaŃii despre cititorii al căror cod este mai mare decât codul unui cititor având
un nume dat.
Dacă o linie nu satisface condiŃia de join, atunci linia respectivă nu va apare în rezultatul cererii.
Pentru a evita această pierdere, în algebra relaŃională a fost introdus operatorul outer-join.
Un outer-join (join extern) este reprezentat prin operatorul (+) care este plasat în clauza WHERE
după numele tabelului ale cărui linii trebuie să nu se piardă din rezultatul cererii. Semnul (+) poate fi
plasat în oricare parte a condiŃiei din clauza WHERE, însă nu în ambele părŃi. Efectul operatorului
(+) este că se generează valori null pentru coloanele tabelului lângă care apare scris, ori de câte ori
tabelul nu are nici o linie care să poată fi reunită cu o linie din celălalt tabel.
Exemplu:
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).
Exemplu:
Considerăm că tabelele dept şi emp au următorul conŃinut:
dept emp
Interogarea următoare afişează lista departamentelor, inclusiv a celor care nu au salariaŃi (left
outer join).
id nume_dep
*** analiza
101 ***
102 ***
103 ***
105 algebra
106 algebra
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.
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.
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);
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.
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.
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);
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’));
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
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);
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):
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ă.
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.
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);
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:
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;
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.
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);
FuncŃia GROUPING
• 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);
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 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
FuncŃii în SQL
FuncŃii de conversie
Conversiile pot fi făcute:
• implicit de către server-ul Oracle ;
• explicit de către utilizator.
Conversii implicite
În cazul atribuirilor, sistemul poate converti automat:
• VARCHAR2 sau CHAR în NUMBER ;
• VARCHAR2 sau CHAR în DATE;
• VARCHAR2 sau CHAR în ROWID;
• NUMBER, ROWID, sau DATE în VARCHAR2.
Pentru evaluarea expresiilor, sistemul poate converti automat:
• VARCHAR2 sau CHAR în NUMBER, dacă şirul de caractere reprezintă un număr;
• VARCHAR2 sau CHAR în DATE, dacă şirul de caractere are formatul implicit DD-MON-
YY;
• VARCHAR2 sau CHAR în ROWID.
Conversii explicite
• funcŃia TO_CHAR converteşte data calendaristică sau informaŃia numerică în şir de
caractere conform unui format;
• funcŃia TO_NUMBER converteşte un şir de caractere în număr;
• funcŃia TO_DATE converteşte un şir de caractere în dată calendaristică conform unui
format.
Dacă formatul este omis, convertirea se face conform unui format implicit. FuncŃia
TO_DATE are forma TO_DATE(şir_de_caractere [,’fmt’]). FuncŃia este utilizată dacă se doreşte
conversia unui şir de caractere care nu are formatul implicit al datei calendaristice (DD-MON-YY).
Alte funcŃii de conversie sunt: CHARTOROWID, CONVERT, HEXTORAW, RAWTOHEX,
ROWIDTOCHAR etc., iar denumirea semnificativă arată rolul fiecăreia.
Exemplu:
SELECT TO_DATE(’Feb 22,1981’,’Mon dd,YYYY’)
FROM DUAL;
FuncŃii aritmetice
Cele mai importante funcŃii aritmetice sunt: ABS (valoarea absolută), ROUND (rotunjire cu
un număr specificat de zecimale), TRUNC (trunchiere cu un număr specificat de zecimale), EXP
(ridicarea la putere a lui e), LN (logaritm natural), LOG (logaritm într-o bază specificată), MOD
(restul împărŃirii a două numere specificate), POWER (ridicarea la putere), SIGN (semnul unui
număr), COS (cosinus), COSH (cosinus hiperbolic), SIN(sinus), SQRT(rădăcina pătrată),
TAN(tangent), funcŃiile LEAST şi GREATEST, care returnează cea mai mică, respectiv cea mai mare
valoare a unei liste de expresii etc.
Pentru afişarea câmpurilor de tip dată calendaristică sau pentru calcule în care sunt implicate
aceste câmpuri, există funcŃii specifice. Câteva din elementele care apar în formatul unei date
calendaristice sunt prezentate în tabelul următor.
Format Descriere Domeniu
SS Secunda relativ la minut 0-59
SSSSS Secunda relativ la zi 0-86399
MI Minut 0-59
HH Ora 0-12
HH24 0-24
Ora
DAY Ziua săptămânii SUNDAY-SATURDAY
D Ziua săptămânii 1-7
DD Ziua lunii 1-31 (depinde de lună)
DDD Ziua anului 1-366 (depinde de an)
MM Numărul lunii 1-12
MON Numele prescurtat al lunii JAN-DEC
MONTH Luna JANUARY-DECEMBER
YY Ultimele două cifre ale anului de exemplu, 99
YYYY Anul de exemplu, 1999
YEAR Anul în litere
CC Secolul de exemplu, 17
Q Numărul trimestrului 1-4
W Săptămâna lunii 1-5
WW Săptămâna anului 1-52
Formatul RR este comentat pe urmatorul exemplu:
FuncŃii generale
• DECODE(value, if1, then1, if2, then2, … , ifN, thenN, else) – returnează then1 dacă value
este egală cu if1, then2 dacă value este egală cu if2 etc.; dacă value nu este egală cu nici
una din valorile if, atunci funcŃia întoarce valoarea else (selecŃie multiplă);
• NVL(e1, e2) – dacă e1 este NULL, returnează e2; altfel, returnează e1;
• NVL2(e1, e2, e3) – dacă e1 este NOT NULL, atunci returnează e2, altfel, returnează e3;
• NULLIF(e1, e2) – returneaza null daca e1=e2 si returneaza e1 daca e1 nu este egal cu e2;
• COALESCE(e1, e2, en) – returneaza prima expresie care nu este null din lista de
expresii (expresiile trebuie sa fie de acelasi tip).
Exemplu:
NVL(comision, 0) este 0 dacă comisionul este null. Prin urmare, expresia salariu*12 +
comision nu este corectă, deoarece rezultatul său este null dacă comisionul este null. Forma corectă
este salariu*12 + NVL(comision, 0).
Exemplu:
Să se afişeze preŃul modificat al unor cărŃi în funcŃie de editură. Pentru cărŃile din editura ALL
să se dubleze preŃurile, pentru cele din editura UNIVERS să se tripleze preŃurile, iar pentru cele din
editura XXX să se reducă la jumătate acest preŃ.
SELECT pret,editura,
DECODE(editura, ’ALL’,pret*2,
’UNIVERS’,pret*3,
’XXX’,pret/2,
pret) pret_revizuit
FROM carte;
Expresia CASE returneaza null daca nu exista clauza ELSE si daca nici o conditie nu este
indeplinita.
SELECT nume, sal,
(CASE WHEN sal <5000 THEN 'LOW'
WHEN sal <10000 THEN 'MEDIUM'
WHEN sal <20000 THEN 'GOOD'
ELSE 'EXCELLENT'
END) calificare
FROM salariat;
Exemplu:
Pentru înregistrările tabelului opera, să se afişeze titlul, data achiziŃiei, valoarea şi o coloană
reprezentând valoarea operei după ce se aplică o mărire, astfel: pentru operele achiziŃionate în 1998
creşterea este de 20%, pentru cele cumpărate în 1999 creşterea este de 15%, iar valoarea celor
achiziŃionate în anul 2000 creşte cu 10%. Pentru operele cumpărate în alŃi ani valoarea nu se
modifică.
SELECT titlu, data_achizitiei, valoare,
CASE TO_CHAR(data_achizitiei, 'yyyy')
WHEN '1998' THEN valoare * 1.20
WHEN '1999' THEN valoare * 1.15
WHEN '2000' THEN valoare * 1.10
ELSE valoare
END "Valoare marita"
FROM opera;
InstrucŃiunea din acest exemplu poate fi rescrisă utilizând funcŃia DECODE:
SELECT titlu, data_achizitiei, valoare,
DECODE (TO_CHAR(data_achizitiei, 'yyyy'),
'1998', valoare * 1.20,
'1999', valoare * 1.15,
'2000', valoare * 1.10,
valoare) "Valoare marita"
FROM opera;
FuncŃii grup
• AVG (media aritmetică),
• COUNT(*) (numărul de linii returnate de o cerere),
• COUNT ([DISTINCT] numărul valorilor unui expresii),
• SUM (suma valorilor unei expresii),
• MIN (valoarea minimă a unei expresii),
• MAX (valoarea maximă a unei expresii),
ObservaŃii:
• FuncŃiile grup operează pe un grup de linii şi nu cer folosirea clauzei GROUP BY.
• FuncŃiile grup ignoră valorile null.
• Orice funcŃie grup întoarce o singură valoare.
• Ele întorc valoarea null când sunt aplicate unei mulŃimi vide, cu excepŃia operatorului
COUNT care întoarce valoarea zero.
• Spre deosebire de funcŃiile COUNT, MIN şi MAX care pot fi aplicate unor câmpuri
numerice sau nenumerice, restul funcŃiilor grup se aplică doar câmpurilor numerice.
• FuncŃiile grup pot să apară în lista de la SELECT sau în clauza HAVING.
Exemplu:
Să se afişeze numărul cărŃilor distincte împrumutate.
SELECT COUNT(DISTINCT codel)
FROM imprumuta;
Exemplu:
Comanda care urmează este greşită! De ce?
SELECT titlu, COUNT(*)
FROM carte;
Exemplu:
Să se calculeze media preŃurilor cărŃilor din bibliotecă.
SELECT AVG(pret)
FROM carte;
Exemplu:
SELECT MAX(pret) - MIN(pret) diferenta
FROM carte;
Exemplu:
Să se obŃină suma, media valorilor, valoarea minimă şi cea maximă pentru operele de artă
expuse în galeria având codul 30. De asemenea, se va afişa numărul de opere şi numărul de artişti
care au creaŃii expuse în această galerie.
SELECT SUM(valoare) Suma, AVG(valoare) Media,
MIN(valoare) Minim, MAX(valoare) Maxim,
COUNT(*) Numar,
COUNT(DISTINCT cod_artist) "Numar artisti"
FROM opera
WHERE cod_galerie = 30;
Întrucât funcŃiile grup ignoră valorile null, această instrucŃiune va returna media valorilor pe
baza liniilor din tabel pentru care există o valoare validă stocată în coloana valoare. Aceasta
înseamnă că suma valorilor se împarte la numărul de valori diferite de null. Pentru a calcula media pe
baza tuturor liniilor din tabel, se utilizează:
SELECT AVG(NVL(valoare, 0))
FROM opera;
Exemplu:
Să se afişeze media valorilor operelor de artă pentru fiecare galerie şi, în cadrul acesteia,
pentru fiecare artist.
SELECT cod_galerie, cod_artist, AVG(valoare)
FROM opera
GROUP BY cod_galerie, cod_artist;
Exemplu:
INSERT INTO carte(codel, nrex)
VALUES ('c25', 25);
INSERT INTO domeniu
VALUES ('&cod','&intdom');inserare prin parametrizare
** Exemplu:
INSERT INTO
(SELECT cod_opera, titlu, data
FROM opera
WHERE cod_galerie = 40)
VALUES (…);
** Exemplu:
INSERT INTO opera(cod_opera,…)
VALUES (123,…)
RETURNING valoare*10, cod_opera INTO :x, :y;
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’;
Exemplu:
Se doreşte ca toŃi graficienii având salariile mai mari decât media salariilor să colaboreze la
realizarea tuturor frame-urilor din publicaŃii coordonate de redactori şefi având vechimea maximă.
Să se completeze tabelul realizeaza cu înregistrările corespunzătoare.
INSERT INTO realizeaza (cod_salariat, nr_publicatie,
nr_capitol, nr_frame)
SELECT s.cod_salariat,f.nr_publicatie, f.nr_capitol,
f.nr_frame
FROM salariat s, frame f
WHERE s.salariu > (SELECT AVG(s1.salariu)
FROM salariat s1)
AND job = 'grafician'
AND f.nr_publicatie IN
(SELECT p.nr_publicatie
FROM salariat s2, publicatie p
WHERE s2.cod_salariat = p.cod_salariat
AND s2.vechime = (SELECT MAX(s3.vechime)
FROM salariat s3));
Exemplu:
Tabelul alfa (emp_id, week_id, sale_lu, sale_ma, sale_mi, sale_jo, sale_vi) provine dintr-o
bază nerelaŃională. Să se depună aceste date, în format relaŃional, în tabelul sales_info (emp_id,
week, sales).
Practic, in tabelul sales_info se vor insera 5 inregistrari.
INSERT ALL
INTO sales_info VALUES (emp_id, week_id, sale_lu)
INTO sales_info VALUES (emp_id, week_id, sale_ma)
INTO sales_info VALUES (emp_id, week_id, sale_mi)
INTO sales_info VALUES (emp_id, week_id, sale_jo)
INTO sales_info VALUES (emp_id, week_id, sale_vi)
SELECT emp_id, week_id, sale_lu, sale_ma,
sale_mi, sale_jo, sale_vi
FROM alfa;
Comanda DELETE
Ştergerea unei linii dintr-un tabel (simplu, partiŃionat sau tabel de bază a unei vizualizări) se
realizează prin comanda DELETE.
DELETE
[FROM] tablename / viewname [AS alias]
[WHERE condiŃie] [clauza_returning]
ObservaŃii:
• Comanda DELETE nu şterge structura tabelului.
• Pentru a se putea executa instrucŃiunea DELETE, utilizatorul care o lansează în execuŃie
trebuie să aibă acest privilegiu.
• În clauza WHERE pot fi folosite şi subcereri.
• Comanda nu poate fi folosită pentru ştergerea valorilor unui câmp individual. Acest lucru
se poate realiza cu ajutorul comenzii UPDATE.
• AtenŃie la ştergere, pentru a nu afecta integritatea referenŃială!
Exemplu:
Să se elimine cititorii care au numele ‘Popa’şi cei care au restituit astăzi cel puŃin o carte.
Comanda UPDATE
Pentru modificarea valorilor existente intr-un tabel sau intr-un tabel de baza a unei vizualizari
se utilizeaza comanda UPDATE. Valorile câmpurilor care trebuie modificate pot fi furnizate explicit
sau pot fi obŃinute în urma unei cereri SQL.
UPDATE tablename / viewname
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.
Exemplu:
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’;
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)));
** 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;
(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;
(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.
Blocări
Blocările sunt folosite în ORACLE pentru a asigura integritatea datelor, permiŃând în acelaşi
timp accesul concurent la date de către un număr “infinit” de utilizatori.
Din punct de vedere a resursei blocate, blocările pot fi:
• la nivel de linie (blocarea afectează un rând);
• nivel de tabel (blocarea afectează întreg tabelul).
La nivel de rând, blocările se pot face numai în modul exclusiv (X), adică un utilizator nu
poate modifica un rând până ce tranzacŃia care l-a blocat nu s-a terminat (prin permanentizare sau
prin derulare înapoi).
Blocările la nivel de tabel pot fi făcute în mai multe feluri, în funcŃie de caracterul mai mult
sau mai puŃin restrictiv al blocării (RS – row share; RX – row exclusive; S – share; SRX – share row
exclusive; X – exclusive).
• Modul X de blocare la nivel de tabel este cel mai restrictiv. Blocarea în mod X este
obŃinută la executarea comenzii LOCK TABLE cu opŃiunea EXCLUSIVE. O astfel de
blocare permite altor tranzacŃii doar interogarea tabelului. Tabelul nu mai poate fi blocat
în acelaşi timp de nici o altă tranzacŃie în nici un mod.
• Modul de blocare RX arată că tranzacŃia care deŃine blocarea a făcut modificări asupra
tabelului. O blocare RX permite acces (SELECT, INSERT, UPDATE, DELETE)
concurent la tabel şi blocarea concurentă a tabelului de către altă tranzacŃie în modurile
RS şi RX.
• Modul de blocare S (se obŃine prin comanda LOCK TABLE cu opŃiunea SHARE) permite
altor tranzacŃii doar interogarea tabelului şi blocarea sa în modurile S şi RS.
• Modul de blocare SRX (se obŃine prin comanda LOCK TABLE cu opŃiunea SHARE ROW
EXCLUSIVE) permite altor tranzacŃii doar interogarea tabelului şi blocarea sa în modul
RS.
• Modul de blocare RS permite acces (SELECT, INSERT, UPDATE, DELETE) concurent
la tabel şi blocarea concurentă a tabelului de către altă tranzacŃie în orice mod, în afară de
X. Modul de blocare RS, care este cel mai puŃin restrictiv, arată că tranzacŃia care a blocat
tabelul, a blocat rânduri din tabel şi are intenŃia să le modifice.
Din punct de vedere a modului de declanşare a blocării, blocările pot fi:
• implicite (blocarea este făcută automat de sistem în urma unei operaŃii INSERT, DELETE
sau UPDATE şi nu necesită o acŃiune din partea utilizatorului);
• explicite (blocarea este declanşată ca urmare a comenzilor LOCK TABLE sau SELECT cu
clauza FOR UPDATE).
Folosirea clauzei FOR UPDATE într-o comandă SELECT determină blocarea rândurilor
selectate în modul X şi blocarea întregului tabel (sau tabelelor) pe care se face interogarea în modul
RS. La actualizarea rândurilor (UPDATE) blocarea la nivel de linie se menŃine în timp ce blocarea la
nivel de tabel devine RX.
Exemplu:
SELECT salariu
FROM salariat
WHERE cod_salariat = 1234
FOR UPDATE OF salariu;
UPDATE salariat
SET salariu = 23456
WHERE cod_salariat = 1234;
COMMIT;
La executarea primei comenzi, rândul cu cod_salariat = 1234 este blocat în mod X în timp ce
tabelul salariat este blocat în modul RS. La executarea celei de a doua comenzi, blocarea la nivel de
linie se menŃine în timp ce blocarea la nivel de tabel devine RX. La executarea comenzii COMMIT,
tranzacŃia este permanentizată şi toate blocările sunt eliberate.
Unul sau mai multe tabele, vizualizari, partitii sau subpartitii ale unor tabele pot fi blocate în
oricare din modurile prezentate mai sus folosind comanda LOCK TABLE, care are sintaxa
simplificata:
LOCK TABLE nume_tabel [, nume tabel] …
IN mod_blocare MODE [NOWAIT]
Clauza NOWAIT determină sistemul să returneze imediat controlul către utilizatorul care
încearcă să realizeze o blocare asupra unui tabel. Dacă acesta este deja blocat, atunci sistemul va
returna un mesaj corespunzător. Altfel, sistemul va aştepta până când tabelul devine disponibil, îl va
bloca şi apoi va returna controlul utilizatorului.
Blocarile obtinute in urma acestei comenzi sunt prioritare celor impuse automat de catre
sistem. Un tabel ramane blocat pana la operatia COMMIT sau ROLLBACK asupra tranzactiei sau
pana la revenirea intr-un punct intermediar (SAVEPOINT) definit inainte de blocarea tabelului.
O blocare impusa asupra unui tabel nu impiedica ceilalti utilizatori sa îl consulte. Blocarea
unei vizualizari implica blocarea tabelelor sale de bază.
Campul mod_blocare poate avea valorile ROW SHARE, ROW EXCLUSIVE, SHARE, SHARE
ROW EXCLUSIVE, EXCLUSIVE. Dacă se specifică NOWAIT şi rândurile selectate sunt deja blocate
de altă tranzacŃie, atunci utilizatorul este înştiinŃat de acest lucru, returnându-i-se controlul.
Datorită accesului concurent la date este posibil ca mai mulŃi utilizatori să se blocheze
reciproc. Această situaŃie este numită interblocare (deadlock), pentru că fiecare dintre utilizatori
aşteaptă ca celălalt să elibereze resursa blocată. În cazul acesta problema nu se poate rezolva prin
simpla aşteptare, una din tranzacŃii trebuind să fie derulată înapoi. Oracle detectează automat
interblocările. În acest caz, Oracle semnalează o eroare uneia dintre tranzacŃiile implicate şi
derulează înapoi ultima instrucŃiune din această tranzacŃie. Acest lucru rezolvă interblocarea, deşi
cealaltă tranzacŃie poate încă să aştepte până la deblocarea resursei pentru care aşteaptă.
Care din următoarele comenzi încheie o tranzacŃie?
SELECT
ROLLBACK
UPDATE
DELETE
CREATE TABLE
1. Ileana Popescu, LetiŃia Velcescu, Neprocedural ORACLE 10G, SQL, Editura UniversităŃii din
Bucureşti, 2008
2. Mariana Popa, Baze de date (Fundamente, exemple, teste de verificare), Editura FRM, 2006
3. Marin Fotache, Catalin Strambei, Liviu Cretu, ORACLE 9i2, Editura Polirom, 2003
4. http://www.oracle.com/index.html/ → situl oficial ORACLE