Documente Academic
Documente Profesional
Documente Cultură
3BD-Cursuri Si Laboratoare PDF
3BD-Cursuri Si Laboratoare PDF
Baze de date
Conf. univ. dr. Nicoleta IACOB
Cuprins
2.1. Noțiunile de bază de date relaţională, sistem de gestiune a bazelor de date relaţionale............... 8
1
4.5. Categorii de instrucţiuni SQL................................................................................................ 24
Procedura de instalare Oracle XE (Oracle Database 11g Express Edition) și Apex (Oracle
Application Express) pe Windows .................................................................................................... 49
2
Tipuri de operatori:............................................................................................................................ 58
Clauza WHERE................................................................................................................................. 59
Functii de conversie........................................................................................................................... 63
Subinterogari ..................................................................................................................................... 66
Interogarea datelor din mai multe relatii folosind tipuri de asocieri ................................................. 68
Comanda DELETE............................................................................................................................ 70
Index .................................................................................................................................................. 74
Sinonim ............................................................................................................................................. 75
Bibliografie............................................................................................................................................ 76
4
1. Noţiuni introductive în teoria bazelor de date
1.1. Noțiunile de bază de date, sistem de gestiune a bazei de date
Prin entitate se înţelege un obiect concret sau abstract reprezentat prin proprietăţile sale. O proprietate
a unui obiect poate fi exprimată prin perechea (ATRIBUT, VALOARE).
Entitatea poate fi persoană, loc, concept, activitate etc. Prin urmare, ea poate fi un obiect cu existenţă
fizică, reală sau poate fi un obiect cu existenţă conceptuală, abstractă.
Exemplu: În exemplul “Produsul X are culoarea Y”, atributul este „culoarea”, iar valoarea este
reprezentată litera„Y”.
5
ambiguităţi, să fie stabilă, să fie familiară utilizatorului astfel încât acesta să o poată folosi
cu uşurinţă;
• pentru fiecare entitate este obligatoriu să se dea o descriere detaliată;
• nu pot exista, în aceeaşi diagramă, două entităţi cu acelaşi nume, sau o aceeaşi entitate cu
nume diferite.
Relaţia este o comunicare între două sau mai multe entităţi. Gradul unei relaţii este dat de numărul de
entităţi participante într-o relaţie (de exemplu, relaţie binară, ternară, cvadruplă, n-ară).
Existenţa unei relaţii este subordonată existenţei entităţilor pe care le leagă.
O relaţie în care aceeaşi entitate participă mai mult decât o dată în diferite roluri defineşte o relaţie
recursivă. Uneori, aceste relaţii sunt numite unare.
Asupra entităţilor participante într-o relaţie pot fi impuse constrângeri care trebuie să reflecte
restricţiile care există în lumea reală asupra relaţiilor. O clasă de constrângeri, numite constrângeri de
cardinalitate, este definită de numărul de înregistrări posibile pentru fiecare entitate participantă (raport
de cardinalitate). Cel mai întâlnit tip de relaţii este cel binar, iar în acest caz rapoartele de cardinalitate
sunt, în general, one-to-one (1:1), one-to-many (1:M) sau many-to-many (N:M).
• 1:1 - legătura de tip “una-la-una” (one-to-one) - este asocierea prin care unui element
(entitate) din mulţimea E1 îi corespunde un singur element din mulţimea E2 şi reciproc;
• 1:M – legătura de tip “una-la-multe” (one-to-many) - este asocierea prin care unui element
din mulţimea E1 îi corespund unul sau mai multe elemente din mulţimea E2, dar unui
element din E2 îi corespunde un singur element în mulţimea E1;
• N:M - legătura de tip “multe-la-multe” (many-to-many) - este asocierea prin care unui
element din mulţimea E1 îi corespund unul sau mai multe elemente din mulţimea E2 şi
reciproc.
R A1 ... Aj .. Am
r1 a11 ... a1j ... a1m
... ... ... ... ... ...
ri ai1 ... aij ... aim
... ... ... ... ... ...
rn an1 ... anj ... anm
6
unde liniile din acest tabel formează elementele relaţiei, sau tupluri, înregistrări, care în general sunt
distincte, coloanele A1, A2, ..., Am formează o mulţime de atribute, iar a11, …, anm sunt valoari pentru
fiecare din atributele A1, Am.
Atributul este o proprietate descriptivă a unei entităţi sau a unei relaţii (de exemplu, denumire,
unitate_de_masura a unui produs, sunt atribute ale entităţii PRODUS).
Atributele sunt utile atunci când într-o relaţie un domeniu apare de mai multe ori. Prin numele dat
fiecărei coloane (atribut), se diferenţiază coloanele care conţin valori ale aceluiaşi domeniu, eliminând
dependenţa faţă de ordine.
a) Identificarea entităţilor. Prin convenţie, entităţile sunt substantive, se scriu cu litere mari şi se
reprezintă prin dreptunghiuri. Într-o diagramă nu pot exista două entităţi cu acelaşi nume, sau o
aceeaşi entitate cu nume diferite.
b) Identificarea asocierilor dintre entităţi şi calificarea lor. Între majoritatea componentelor (adică a
entităţilor) unui sistem economic se stabilesc legături (asocieri).
c) Identificarea atributelor entităţilor şi a asocierilor dintre entităţi. Atributele unei entităţi reprezintă
proprietăţi ale acestora. Atributele sunt substantive, iar pentru fiecare atribut i se va preciza tipul fizic
(integer, float, char, string etc.)
În cadrul diagramei entitate-asociere, un atribut de identificare se marchează prin subliniere sau prin
marcarea cu simbolul # plasat la sfârşitul numelui acestuia.
Pentru ca un atribut să fie atribut de identificare, acesta trebuie să satisfacă unele cerinţe:
• oferă o identificare unică în cadrul entităţii;
• este uşor de utilizat;
• este scurt (de cele mai multe ori, atributul de identificare apare şi în alte entităţi, drept cheie
externă).
Pentru o entitate pot exista mai multe atribute de identificare, numite atribute (chei) candidate. Dacă
există mai mulţi candidaţi cheie, se va selecta unul, preferându-se acela cu valori mai scurte şi mai
puţin volatile.
O bază de date relaţională (BDR) reprezintă un ansamblu de relaţii, prin care se reprezintă datele şi
legăturile dintre ele.
În cadrul bazei de date relaţionale, datele sunt organizate sub forma unor tablouri bidimensionale
(tabele) de date, numite relaţii. Asocierile dintre relaţii se reprezintă prin atributele de legătură. În
cazul legăturilor de tip „una-la-multe”, aceste atribute figurează într-una dintre relaţiile implicate în
asociere. În cazul legăturilor de tip „multe-la-multe”, atributele sunt situate într-o relaţie distinctă,
construită special pentru explicarea legăturilor între relaţii.
8
Prin sistem de gestiune a bazelor de date relaţionale (SGBDR) se înţelege un SGBD care utilizează
drept concepţie de organizare a datelor modelul relaţional.
Definirea unui SGBDR impune o detaliere a caracteristicilor pe care trebuie să le prezinte un SGBD
pentru a putea fi considerat relaţional. În acest sens, Codd a formulat (în 1985) 13 reguli, care exprimă
cerinţele pe care trebuie să le satisfacă un SGBD.
R1: Reprezentarea logică a datelor. Într-o bază de date relaţionată, informaţia este reprezentată la nivel
logic sub forma unor tabele (relaţii). Acest lucru înseamnă că toate datele trebuie să fie memorate şi
prelucrate în acelaşi mod.
R2: Garantarea accesului la date. Orice dată din baza de date relaţionată trebuie să poată fi accesată
prin specificarea numelui relaţiei (tabelei), a valorii cheii primare și numelui atributului (coloană).
R4: Metadatele. Utilizatorii autorizaţi trebuie să poată aplica asupra descrierii bazei de date aceleaşi
operaţii ca şi asupra datelor obişnuite.
9
Presupunem că se doreşte schimbarea preţului unitar la un anumit produs, această schimbare trebuie
efectuată în tabela de bază PRODUS, atributul „Pret_unitar” din tabela virtuală FACTURA, fiind
actualizabil, întrucât actualizarea se poate propaga spre tabela de bază.
R7: Actualizările în baza de date (inserările, modificările şi ştergerile din baza de date):
• un SGBDR nu trebuie să oblige utilizatorul să caute într-o relaţie, tuplu cu tuplu, pentru a
regăsi informaţia dorită;
• această regulă exprimă cerinţa ca în operaţiile prin care se schimbă conţinutul bazei de date să
se lucreze la un moment dat pe o întreagă relaţie.
R9: Independenţa logică a datelor. Schimbarea relaţiilor bazei de date nu trebuie să afecteze
programele de aplicaţie.
R10: Restricţiile de integritate. Restricţiile de integritate trebuie să fie definite într-un limbaj
relaţional, nu în programul de aplicaţie.
R11: Distribuirea geografică a datelor. Distribuirea datelor pe mai multe calculatoare dintr-o reţea de
comunicaţii de date nu trebuie să afecteze programele de aplicaţie.
R12: Prelucrarea datelor la nivelul de bază. Dacă sistemul posedă un limbaj de bază orientat pe
prelucrarea de tupluri şi nu pe prelucrarea relaţiilor, acest limbaj nu trebuie să fie utilizat pentru a evita
restricţiile de integritate (se introduc inconsistenţe).
Orice model de date, conform unei sugestii a lui Codd, trebuie să se bazeze pe trei componente:
1) structurile de date. O bază de date relaţională (BDR) reprezintă un ansamblu de relaţii, prin
care se reprezintă date şi legăturile dintre ele. Structurile sunt definite de un limbaj de definire
10
a datelor (Data Definition Language). Datele în modelul relațional sunt structurate în relații
(tabele) bidimensionale;
2) operatorii de manipulare a datelor. Relațiile pot fi manipulate utilizând un limbaj de
manipularea datelor (Data Manipulation Language). În modelul relațional, limbajul folosește
operatori relaționali bazați pe conceptul algebrei relaționale. În afară de acesta, există limbaje
echivalente algebrei relaționale, cum ar fi calculul relațional orientat pe tuplu și calculul
relațional orientat pe domeniu;
3) constrângerile de integritate. Prin integritatea datelor se subînțelege că datele rămân stabile, în
siguranță și corecte. Integritatea în modelul relațional este menținută de constrângeri interne
care nu sunt cunoscute utilizatorului.
Domeniul este un ansamblu de valori caracterizat printr-un nume. El poate fi explicit sau implicit.
Tabela/relaţia este un subansamblu al produsului cartezian al mai multor domenii, caracterizat printr-
un nume, prin care se definesc atributele ce aparţin aceleaşi clase de entităţi.
Cheia este un atribut sau un ansamblu de atribute care au rolul de a identifica un tuplu dintr-o tabelă.
Tipuri de chei: primare/alternate, simple/comune, externe.
Tuplul este linia dintr-o tabelă şi nu are nume. Ordinea liniilor (tuplurilor) şi coloanelor (atributelor)
dintr-o tabelă nu trebuie să prezinte nici-o importanţă.
Schema tabelei este formată din numele tabelei, urmat între paranteze rotunde de lista atributelor, iar
pentru fiecare atribut se precizează domeniul asociat.
Schema bazei de date poate fi reprezentată printr-o diagramă de structură în care sunt puse în evidenţă
şi legăturile dintre tabele. Definirea legăturilor dintre tabele se face logic construind asocieri între
tabele cu ajutorul unor atribute de legătură. Atributele implicate în realizarea legăturilor se găsesc fie
în tabelele asociate, fie în tabele distincte construite special pentru legături. Atributul din tabela iniţială
se numeşte cheie externă, iar cel din tabela finală este cheie primară. Legăturile posibile sunt 1:1,
1:M, N:M. Potenţial, orice tabelă se poate lega cu orice tabelă, după orice atribute.
Legăturile se stabilesc la momentul descrierii datelor prin limbaje de descriere a datelor (LDD), cu
ajutorul restricţiilor de integritate. Practic, se stabilesc şi legături dinamice la momentul execuţiei.
a) Algebra relaţională este o colecţie de operaţii formale aplicate asupra tabelelor (relaţiilor), şi a
fost concepută de E.F. Codd. Operaţiile sunt aplicate în expresiile algebrice relaţionale care sunt
cereri de regăsire. Acestea sunt compuse din operatorii relaţionali şi operanzi. Operanzii sunt
întotdeauna tabele (una sau mai multe). Rezultatul evaluării unei expresii relaţionale este format
dintr-o singură tabelă.
11
Algebra relaţională are cel puţin puterea de regăsire a calcului relaţional. O expresie din calculul
relaţional se poate transforma într-una echivalentă din algebra relaţională şi invers.
Codd a introdus 6 operatori de bază (reuniunea, diferenţa, produsul cartezian, selecţia, proiecţia,
joncţiunea) şi 2 operatori derivaţi (intersecţia şi diviziunea). Ulterior au fost introduşi şi alţi operatori
derivaţi (speciali). În acest context, operatorii din algebra relaţională pot fi grupaţi în două categorii:
operatori pe mulţimi şi operatori speciali.
Fie R1, R2, R3 - relaţii (tabele).
b) Calculul relaţional se bazează pe calculul predicatelor de ordinul întâi şi a fost propus de E.F.
Codd. Predicatul este o relaţie care se stabileşte între anumite elemente şi care poate fi confirmată sau
nu. Predicatul de ordinul 1 este o relaţie care are drept argumente variabile care nu sunt predicate.
Variabila poate fi de tip tuplu (valorile sunt dintr-un tuplu al unei tabele) sau domeniu (valorile sunt
dintr-un domeniu al unei tabele). Cuantificatorii (operatorii) utilizaţi în calculul relaţional sunt:
universal (∀) şi existenţial (∃).
Construcţia de bază în calculul relaţional este expresia relaţională de calcul tuplu sau domeniu.
Pentru implementarea acestor operatori există comenzi specifice în limbajele de manipulare a datelor
(LMD) din sistemele de gestiune a bazelor de date relaţionale (SGBDR). Aceste comenzi sunt utilizate
în operaţii de regăsire (interogare).
12
După tehnica folosită la manipulare, LMD sunt bazate pe:
• calculul relaţional (QUEL în Ingres, ALPHA propus de Codd);
• algebra relaţională (ISBL, RDMS);
• transformare (SQL, SQUARE);
• grafică (QBE, QBF).
Transformarea oferă o putere de regăsire echivalentă cu cea din calculul şi algebra relaţională. Se
bazează pe transformarea (mapping) unui atribut sau grup de atribute într-un atribut dorit prin
intermediul unor relaţii. Rezultatul este o relaţie (tabelă) care se poate utiliza într-o altă transformare.
Grafica oferă interactivitate mare pentru construirea cererilor de regăsire. Utilizatorul specifică cererea
alegând sau completând un ecran structurat grafic. Poate fi folosită de către toate categoriile de
utilizatori în informatică.
Algebra relaţională este prin definiţie neprocedurală (descriptivă), iar calculul relaţional permite o
manieră de căutare mixtă (procedurală/neprocedurală).
Restricţii de integritate structurale, care se definesc prin egalitatea sau inegalitatea unor valori din
cadrul relaţiilor. Acestea sunt:
• restricţia de unicitate a cheii - cheia primară trebuie să fie unică și minimală;
• restricţia de integritate a referirii. Într-o tabelă t1 care referă o tabelă t2, valorile cheii externe
trebuie să figureze printre valorile cheii primare din t2 sau să ia valoarea NULL
(neprecizat);
• restricţia de integritate a entităţii. Într-o tabelă, atributele din cheia primară nu trebuie să ia
valoarea NULL.
Pe lângă acestea, există o serie de alte restricţii structurale care se referă la dependenţele dintre date:
funcţionale, multivaloare, joncţiune etc. (sunt luate în considerare la tehnicile de proiectare a bazelor
de date relaţionale - BDR).
Restricţii de integritate de comportament - sunt cele care se definesc prin comportamentul datelor şi
ţin cont de valorile din BDR. Acestea sunt:
• restricţia de domeniu. Domeniul corespunzător unui atribut dintr-o tabelă trebuie să se
încadreze între anumite valori;
• restricţii temporale. Valorile anumitor atribute se compară cu nişte valori temporale (rezultate
din calcule etc.).
Restricţiile de comportament fiind foarte generale se gestionează fie la momentul descrierii datelor (de
exemplu prin clauza CHECK), fie în afara modelului la momentul execuţiei.
13
2.4. Tipuri de constrângeri de integritate
Termenul de cheie (keys) este folosit pentru definirea câtorva categorii de constrângeri, şi sunt:
PRIMARY KEY, UNIQUE KEY, FOREIGN KEY, REFERENCED KEY.
Tehnica de normalizare
Tehnica de normalizare este utilizată în activitatea de proiectare a structurii BDR şi constă în
eliminarea unor anomalii (neajunsuri) de actualizare din structură.
Anomaliile de actualizare sunt situaţii nedorite care pot fi generate de anumite tabele în procesul
proiectării lor:
• anomalia de ştergere - stergând un tuplu dintr-o tabelă, pe lângă informaţiile care trebuie
şterse, se pierd şi informaţiile utile existente în tuplul respectiv;
• anomaliile de adăugare - nu pot fi incluse noi informaţii necesare într-o tabelă, deoarece nu se
cunosc şi alte informaţii utile (de exemplu valorile pentru cheie);
• anomalia de modificare - este dificil de modificat o valoare a unui atribut atunci când ea apare
în mai multe tupluri.
14
Normalizarea este o teorie construită în jurul conceptului de forme normale (FN), care ameliorează
structura BDR prin înlăturarea treptată a unor neajunsuri şi prin imprimarea unor facilităţi sporite
privind manipularea datelor.
Normalizarea utilizează ca metodă descompunerea (top-down) unei tabele în două sau mai multe
tabele, păstrând informaţii (atribute) de legătură.
Codd a definit iniţial 3 forme normale, notate prin FN1, FN2 şi FN3. Întrucât într-o primă formulare,
definiţia FN3 ridică ceva probleme, Codd şi Boyce au elaborat o nouă variantă, cunoscută sub numele
de Boyce-Codd Normal Form (BCNF). Astfel, BCNF este reprezentată separat în majoritatea
lucrărilor. R. Fagin a tratat cazurile FN4 şi FN5.
Normalizarea bazei de date relaţionale poate fi imaginată ca un proces prin care pornindu-se de la
relaţia iniţială/universală R se realizează descompunerea succesivă a acesteia în subrelaţii, aplicând
operatorul de proiecţie. Relaţia R poate fi ulterior reconstruită din cele n relaţii obţinute în urma
normalizării, prin operaţii de joncţiune.
Dintre toate formele normale, doar FN1 are caracter de obligativitate. Se spune că o bază de date este
normalizată dacă toate relaţiile se află măcar în FN1.
O relaţie este în FN1 dacă domeniile pe care sunt definite atributele relaţiei sunt constituite numai din
valori atomice. Un tuplu nu trebuie să conţină atribute sau grupuri de atribute repetitive.
Primele două metode generează relaţii stufoase prin duplicarea forţată a unor atribute, respectiv
tupluri, creându-se astfel redundanţe masive cu multiple anomalii de actualizare.
15
Metoda a treia presupune eliminarea grupurilor repetitive prin construirea de noi relaţii, ceea ce
generează o structură ce oferă cel mai mic volum de redundanţă.
Exemplu: Fie relaţia nenormalizată (primară) FACTURI. Să se stabilească o structură de tabele care să
permită stocarea informaţiilor conţinute în document (factură) şi obţinerea unor situaţii sintetice
privind evidenţa sumelor facturate pe produse, pe clienţi, pe anumite perioade de timp.
FACTURI
nr_factura#
data_factura
nume_client
adresa_client
telefon_client
email_client
banca_client
nr_cont_client
delegat
cod_produs
denumire_produs
unitate_de_masura
data_expirarii
cantitate
pret_unitar
valoare
valoare_tva
total_valoare_factura
total_valoare_tva
Relaţia FACTURI nenormalizată
În cazul în care o factură conţine mai multe produse, relaţia de mai sus va avea grupurile repetitive:
„cod_produs”, „denumire_produs”, „data_expirarii”, „cantitate”, „pret_unitar”, „valoare”,
„valoare_tva”.
Exemplu: Deoarece o factură poate avea unul sau mai multe produse înscrise pe aceasta, informaţiile
legate de produse vor fi separate într-o altă tabelă. Aplicând etapele de aducere în FN1, se obţin două
relaţii.
16
FACTURI LINII_FACTURI
nr_factura# nr_factura#
data_factura cod_produs#
nume_client denumire_produs
adresa_client unitate_de_masura
telefon_client data_expirarii
banca_client cantitate
nr_cont_client pret_unitar
delegat valoare
toal_valoare_factura valoare_tva
toal_valoare_tva
Relaţia FACTURI adusă în forma normală FN1
Observaţii:
• Câmpul „adresa_client” cuprinde informaţii despre judeţul, localitatea, strada şi numărul
domicililului clientului. Dacă se consideră că este de interes o evidenţă a sumelor
factorizate pe judeţe sau localităţi, se vor pune în locul câmpului „adresa_client” trei
câmpuri distincte: „judet_client”, „localitate_client”, „adresa_client”, uşurând în acest fel
interogările;
• Între tabela FACTURI şi tabela LINII_FACTURI există o relaţie de „una-la-multe”, adică
unui număr unic de factură îi pot corespunde unul sau mai multe produse care sunt
memorate ca înregistrări în tabela LINII_FACTURI. Cheia primară în această tabelă este
o cheie compusă, formată din două câmpuri: „nr_factura” şi „cod_produs”.
Însă, eliminarea grupurilor repetitive, adică aducerea unei relaţii în FN1, nu rezolvă complet problema
normalizării.
Exemplu: Relaţia care conţine date redundante (de exemplu, modificarea denumirii unui produs atrage
după sine modificarea în fiecare tuplu în care apare acest produs) este relaţia LINII_FACTURI. Se
observă că nu există nici o dependenţă funcţională între atributele necomponente ale cheii. În schimb,
toate atributele care nu intră în alcătuirea cheii compuse sunt dependente de aceasta, iar DF dintre
17
atributul component al cheii primare sunt: cod_produs --> denumire_produs, cod_produs -->
unitate_de_masura, data_expirarii. Ca urmare se formează încă două relaţii.
Chiar dacă au fost eliminate o parte din redundanţe, mai rămân şi alte redundanţe ce se vor elimina
aplicând alte forme normale.
Exemplu: În relaţia FACTURI se observă că atributul „nume_client” determină în mod unic atributele
„adresa_client”, „telefon_client”, „email_client”, „banca_client” şi „nr_cont_client”. Deci pentru
atributul „nume_client” se construieşte o relaţie CLIENTI în care cheia primară va fi acest atribut, iar
celelalte atribute vor fi „adresa_client”, „telefon_client”, „email_client”, „banca_client” şi
„nr_cont_client”. Câmpurile „valoare” şi „valoare_tva” depind de câmpurile „cantitate”, „pret_unitar”,
şi de un procent fix de TVA. Fiind câmpuri ce se pot calcula în orice moment, ele vor fi eliminate din
tabelă LINII FACTURI, deoarece constituie informaţie memorată redundant.
Observaţii:
• Această a treia formă normală mai poate suferi o serie de rafinări pentru a putea obţine o
structură performantă de tabele ale bazei de date. De exemplu, se observă că
„nume_client” este un câmp în care este înscris un text destul de lung format dintr-o
succesiune de litere, semne speciale (punct, virgulă, cratimă), spaţii, numere. Ordonarea şi
regăsirea informaţiilor după astfel de câmpuri este lentă şi mai greoaie decât după câmpuri
numerice. Din acest motiv se poate introduce un nou atribut „cod_client” care să fie
numeric şi care să fie cheia primară de identificare pentru fiecare client;
• O altă observaţie care poate fi făcută în legătură cu tabelele aflate în cea de a treia formă
normală este aceea că „total_valoare_factura” este un câmp care ar trebui să conţină
informaţii sintetice obţinute prin însumarea valorii tuturor ofertelor aflate pe o factură.
Este de preferat ca astfel de câmpuri să fie calculate în rapoarte sau interogări şi să nu fie
memorate în tabelele bazei de date.
Verificarea aplicării corecte a procesului de normalizare se realizează astfel încât uniunea acestor
relaţii să producă relaţia iniţială, cu alte cuvinte, descompunerea este fără pierderi.
Celelalte forme normale se întâlnesc mai rar în practică. Aceste forme nu sunt respectate, în general,
pentru că beneficiile de eficienţă pe care le aduc nu compensează costul şi munca de care este nevoie
pentru a le respecta.
Fiecare dintre cele 6 forme normale este mai restrictivă ca predecesoarea sa. Astfel, de exemplu, o
schemă de relaţie aflată în forma normală trei este şi în forma normală doi, aşa cum se reprezintă în
figura de mai jos:
FN 5
FN 1 FN 3 FNBC FN 4
FN 2
Forme normale
Scopul formelor normale este acela de a elimina redundanţele din cadrul relaţiilor prin descompunerea
acestora în două sau mai multe relaţii, fără însă a pierde informaţie, ceea ce înseamnă faptul că este
posibilă, în orice moment, revenirea la relaţia originară doar pe baza relaţiilor obţinute din
descompunere.
Dependenţa multivaloare este caz particular al dependenţei joncţiune. Dependenţa funcţională este caz
particular al dependenţei multivaloare.
b) Proiectarea schemei externe are rolul de a specifica viziunea fiecărui utilizator asupra BDR. Pentru
acest lucru, din schema conceptuală se identifică datele necesare fiecărei viziuni. Datele obţinute se
structurează logic în subscheme ţinând cont de facilităţile de utilizare şi de cerinţele utilizator. Schema
externă devine operaţională prin construirea unor vizualizări (view) cu SGBD-ul şi acordarea
drepturilor de acces. Datele într-o vizualizare pot proveni din una sau mai multe colecţii şi nu ocupă
spaţiul fizic.
20
Realizarea componentelor logice. Componentele logice ale unei BD sunt programele de aplicaţie
dezvoltate, în cea mai mare parte, în SGBD-ul ales. Programele se realizează conform modulelor
funcţionale proiectate în etapa anterioară. Componentele logice ţin cont de ieşiri, intrări, prelucrări şi
de colecţiile de date. În paralel cu dezvoltarea programelor de aplicaţii se întocmesc şi diferite
documentaţii (tehnică, de exploatare, de prezentare).
Punerea în funcţiune şi exploatarea. Se testează funcţiile BDR mai întâi cu date de test, apoi cu date
reale. Se încarcă datele în BDR şi se efectuează procedurile de manipulare, de către beneficiar cu
asistenţa proiectantului. Se definitivează documentaţiile aplicaţiei. Se intră în exploatare curentă de
către beneficiar conform documentaţiei.
Dezvoltarea sistemului. Imediat după darea în exploatare a BDR, în mod continuu, pot exista factori
perturbatori care generează schimbări în BDR. Factorii pot fi: organizatorici, datoraţi progresului
tehnic, rezultaţi din cerinţele noi ale beneficiarului, din schimbarea metodologiilor etc.
21
• operatori binari de comparaţie:
<
>
<=
>=
=
<> sau != diferit
• operatori aritmetici mari:
@ valoarea absolută
! factorial
!! factorial, operator postfix
~ NOT orientat pe biţi
• operatori de comparaţie:
A BETWEEN min AND max (compară A cu două valori: min şi max)
A IN (v1,...,vn) compară A cu o listă de valori
A IS NULL
A IS NOT NULL
A LIKE model_şir
• operatori logici:
Operatorii logici sunt legaţi prin cuvintele cheie AND, OR, NOT şi returnează o valoare
logică TRUE, FALSE sau NULL.
• operatori relaţionali:
UNION (reuniune)
INTERSECT (intersecţie)
MINUS (diferenţă)
• funcții pe mai mutle rânduri (funcții de grup) - lucrează cu grupuri de rânduri pentru a returna
un singur rezultat pentru fiecare grup. Aceste funcții sunt cunoscute cu denumirea de
funcții de grup. Toate funcţiile de grup, mai puţin COUNT(*) ignoră valorile NULL.
Majoritatea funcţiilor de grup acceptă opţiunile: DISTINCT (determină luarea în calcul
22
numai a valorilor distincte ale rândurilor din cadrul grupului) şi ALL (este implicit și
determină luarea în calcul a tuturor valorilor grupului de rânduri).
Funcţiile agregat - calculează un rezultat din mai multe linii ale unui tabel (funcţii de totalizare):
o COUNT (furnizează numărul de linii ale unui rezultat);
o SUM (execută suma tuturor valorilor dintr-o coloană);
o MAX (returnează valoarea cea mai mare dintr-o coloană);
o MIN (returnează valoarea cea mai mică dintr-o coloană);
o AVG (calculează media valorilor dintr-o coloană).
Funcţiile scalare - primesc unul sau mai multe argumente şi returnează valoarea calculată sau NULL
în caz de eroare. Argumentele funcţiilor pot fi constante sau valori ale atributelor specificate prin
numele coloanelor corespunzătoare.
În limbajul SQL sunt definite mai multe tipuri de date: numeric, şir de caractere, şir de biţi, dată
(calendaristică), timp.
Denumirile tipurilor de date precum şi limitele acestora diferă de la un SGBD la altul, dar în general,
sunt destul de asemănătoare.
Asemănarea dintre cele două tipuri prezentate mai sus este aceea că ambele reprezintă şiruri de
maxim n caractere, iar deosebirea este aceea că pentru şiruri cu număr de caractere mai mic ca n,
CHAR (n) completează şirul cu spaţii albe până la n caractere, iar VARCHAR (n) memorează
numai atâtea caractere câte are şirul dat.
23
• Tipuri pentru data calendaristică şi timp
o DATE permite memorarea datelor calendaristice în formatul yyyy-mm-dd;
o TIME permite memorarea timpului, folosind trei câmpuri hh:mm:ss;
o TIMESTAMP(p) permite memorarea combinată a datei calendaristice şi a timpului,
cu precizia p pentru câmpul SECOND (al secundelor); valoarea implicită a lui p este
6;
o INTERVAL este utilizat pentru memorarea intervalelor de timp.
Tipurile de date sunt „case-insensitive”, deci nu ţin cont de caracterele mari sau mici.
În funcţie de tipul acţiunii pe care o realizează, instrucţiunile SQL se împart în mai multe categorii.
Datorită importanţei pe care o au comenzile componente, unele dintre aceste categorii sunt evidenţiate
ca limbaje relaționale în cadrul SQL, şi anume:
• limbajul de definire a datelor (LDD sau DDL – Data Definition Language);
• limbajul de interogare a datelor (LQD sau DQL - Data Query Language);
• limbajul de prelucrare a datelor (LMD sau DML – Data Manipulation Language);
• limbajul de control al datelor (LCD sau DCL – Data Control Language).
• facilități de descriere a datelor la nivel logic. Pentru descrierea datelor la nivel logic,
limbajele relaționale dispun de o serie de comenzi, precum:
o crearea tabelelor virtuale: CREATE VIEW;
o ștergerea tabelelor virtuale: DROP VIEW;
o acordarea drepturilor de acces la BD:
GRANT CONNECT – conectarea la BD a unui utilizator;
GRANT drepturi – acordarea unor drepturi de acces (pentru regăsire,
actualizare etc.).
24
o retragerea drepturilor de acces la BD:
REVOKE drepturi – retragerea unor drepturi;
REVOKE CONNECT – deconectarea unui utilizator de la BD.
facilități de descriere a datelor la nivel fizic. Pentru definirea unor caracteristici legate de
organizarea la nivel fizic a datelor din baza de date, limbajele relaționale dispun de o serie
de comenzi, și anume:
o crearea indecşilor: CREATE INDEX;
o ștergerea indecşilor: DROP INDEX;
o controlul alocării spațiului fizic al BD:
CREATE SPACE – creează un model de alocare a spațiului fizic pentru o
BD;
ALTER SPACE – actualizează modelul de alocare a spațiului fizic;
DROP SPACE – şterge un model de alocare a spațiului fizic.
o regruparea fizică a datelor dintr-o BD (clustere):
CREATE CLUSTER – creează un cluster dintr-o BD;
ALTER CLUSTER– actualizează un cluster;
DROP CLUSTER – şterge un cluster.
25
Crearea unei relaţii indicând cheile la nivel de tabel
Exemplu: Să se creeze relaţia LINII_FACTURI(nr_factura, cod_produs, cantitate,
PRET_UNIRAR).
CREATE TABLE LINII_FACTURI
(nr_factura VARCHAR(5),
cod_produs CHAR (5),
cantitate REAL,
pret_unitar REAL,
PRIMARY KEY (nr_factura, cod_produs),
FOREIGN KEY (cod_produs)
REFERENCES PRODUSE (cod_produs));
Dacă cheia primară are mai mult de o coloană atunci cheile trebuie indicate la nivel de tabel.
Unele limbaje relaţionale (QBE) admit toate aceste tipuri de modificări în schema unei relaţii, iar
altele (SQL sau QUEL) numai o parte.
ALTER TABLE nume_tabel ...
26
ALTER TABLE LINII_FACTURI
MODIFY pret_unitar DECIMAL (10,2);
Fiecărei restricţii i se poate da un nume, lucru util atunci când, la un moment dat (salvări, restaurări,
încărcarea BD) se doreşte dezactivarea uneia sau mai multora dintre acestea. Astfel se prefigurează
numele fiecărei restricţii cu tipul său:
• pk_(PRIMARY KEY) - pentru cheile primare;
• un_(UNIQUE) - pentru cheile alternative - care impune respectarea unicității valorilor;
• nn_(NOT NULL) - pentru atributele obligatorii;
• ck_(CHECK) - pentru reguli de validare la nivel de atribut;
• fk_(FOREIGN KEY) - pentru cheile străine.
Observaţii:
• Liniile ce nu respectă constrângerea sunt depuse automat într-un tabel special;
• Constrângerile previn ştergerea unui tabel dacă există dependenţe;
• Constrângerile pot fi activate sau dezactivate în funcţie de necesităţi.
• Constrângerile pot fi create o dată cu tabelul sau după ce acesta a fost creat.
27
Modificarea unei restricţii de integritate
ALTER TABLE nume_tabela
MODIFY(nume_atribut TIP_CONSTRÂNGERE);
Exemplu: Să se suprime restricţia de cheie primară (pentru atributul „nr_factura”) din tabela
LINII_FACTURI.
ALTER TABLE LINII_FACTURI DROP PRIMARY KEY;
Observaţii:
• Comanda ALTER TABLE realizează modificarea structurii tabelului (la nivel de coloană sau
la nivel de tabel), dar nu modificarea conţinutului acestuia;
• Constrângerile pot fi adăugate (ADD CONSTRAINT), şterse (DROP CONSTRAINT),
activate (ENABLE) sau dezactivate (DISABLE), dar nu pot fi modificate;
• Dacă există o cheie externă care referă o cheie primară şi dacă se încearcă ştergerea cheii
primare, această ştergere nu se poate realiza (tabelele sunt legate prin declaraţia de cheie
externă). Ştergerea este totuşi permisă dacă în comanda ALTER apare opţiunea
CASCADE, care determină şi ştergerea cheilor externe ce referă cheia primară urmărind
sintaxa:
ALTER TABLE Nume_tabela
DROP PRIMARY KEY CASACDE;
28
6. Limbajul de manipulare a datelor (LMD)
Instrucţiunile LMD (sau DML, Data Manipulation Language) sunt utile pentru interogarea și
prelucrarea datelor din obiectele unei scheme. Aceste instrucţiuni permit:
• interogarea bazei de date (SELECT);
• adăugarea de înregistrări în tabele (sub forma rândurilor din tabele) sau vizualizări (INSERT);
• modificarea valorilor unor coloane din înregistrările existente în tabele sau vizualizări
(UPDATE);
• suprimarea de înregistrări din tabele sau vizualizări (DELETE).
O colecție de comenzi LMD care formează o unitate logică de lucru se numește tranzacție.
Instrucţiunile LMD individuale afectează datele dintr-un singur tabel. Este posibil ca într-o
instrucţiune LMD să se refere şi o vizualizare care conţine date din mai multe tabele (adică o
vizualizare care conţine o uniune de tabele), dar, în acest caz, instrucţiunea LMD poate referi numai
coloane dintr-un singur tabel al vizualizării. Cu alte cuvinte, atunci când o instrucţiune LMD foloseşte
o vizualizare, toate coloanele vizualizării referite în instrucţiunea LMD trebuie să corespundă unor
coloane dintr-un singur tabel fizic al bazei de date.
Sistemul SGBD nu va efectua în baza de date nici o modificare care încalcă una din restricţii.
29
Actualizarea datelor se referă la adăugarea unor noi rânduri într-o tabelă (cu instrucţiunea INSERT), la
modificarea valorilor uneia sau mai multor valori dintr-un rând (cu comanda UPDATE) şi la ştergerea
unui rând dintr-o tabelă (cu comanda DELETE).
Comanda fundamentală a standardului SQL este SELECT, aceasta permiţând interogarea unei baze de
date.
Clauzele SELECT şi FROM sunt obligatorii. SELECT specifică datele care se selectează, iar clauza
FROM specifică relaţiile din care se selectează. Restul clauzelor sunt opţionale.
Exemplul 1: Să se selecteze toate produsele împreună cu toate datele acestora existente în baza de
date.
SELECT * FROM PRODUSE;
Exemplu: Să se determine numărul facturii şi codul produselor pentru produsele cu o cantitate mai
mare de 300 şi cu un preţ unitar mai mare sau egal ca 100.
SELECT cod_produs, nr_factura FROM LINII_FACTURI
WHERE cantitate>’300’ AND pret_unitar>=’100’;
30
Interogarea datelor folosind operatorul IN
SELECT valoare_câmp IN (valoare1, valoare2,...);
Exemplu: Să se selecteze numărul facturii și codul produselor pentru produsele cu prețul unitar de 70,
80, 90.
SELECT * FROM LINII_FACTURI
WHERE pret_unitar IN (70.00,80.00,90.00);
Sintaxa DISTINCT se referă la o înregistrare care poate cuprinde unul sau mai multe câmpuri.
Exemplu: Să se selecteze numele adresa şi emailul tuturor persoanelor din București care au adresă de
email pe gmail sau personal.
SELECT nume_client, adresa_client, email_client
FROM CLIENTI
WHERE adresa_client LIKE ‘%BUCUREȘTI %’ AND
(email_client LIKE ‘%gmail%’ OR email_client LIKE’%personal%’);
Sintaxa este:
val BETWEEN minim AND maxim;
sau
val>=min AND val<=max;
31
Cele trei expresii val, min, max pot fi de tip numeric (numeric, decimal, int, smalint etc.) sau de tip
dată calendaristică.
Exemplu: Să se selecteze codurile tuturor facturilor înregistrate în perioada 1 ianuarie 2017 şi 1 mai
2017.
SELECT nr_factura
FROM FACTURI
WHERE data_factura BETWEEN ‘2017-01-01’ AND ‘2017-05-01’;
Dacă ORDER BY nu este urmat de ASC sau DESC, ordonarea se face implicit crescător.
Observaţii:
• Atunci când în clauza FROM a unei comenzi SELECT apar mai multe tabele se realizează
produsul cartezian al acestora. De aceea numărul de linii rezultat creşte considerabil, fiind
necesară restricţionarea acestora cu o clauza WHERE. Se utilizează sintaxa:
nume_tabel.nume_câmp
Clauza FROM specifică două relaţii (FACTURI și CLIENTI).
32
Clauza SELECT cuprinde valori din relaţia FACTURI şi din relaţia CLIENTI, prin
urmare trebuie definite câmpurile în funcţie de tabela din care fac parte.
• Clauza WHERE include condiţii care exprimă o egalitate între valorile identificatorului
nume_câmp a relaţiei nume_tabel şi a celei ale referinţei la acest identificator în tabela
referită.
• Asocieri de la una-la-una
Două relaţii stochează informaţii în asocierea una-la-una dacă unei înregistrări din relaţia A îi
corespunde (sau nu) o singură înregistrare din B.
Acest tip de asociere este utilizată mai rar. Există, totuşi, cazuri în care este necesară şi utilă stabilirea
unei astfel de relaţii.
Exemplu:
LINII_FACTURI PRODUSE
nr_factura# cod_produs#
cod_produs# denumire_produs
cantitate unitate_de_masura
pret_unitar data_expirarii
• Asocieri de la una-la-multe
O relaţie A se află într-o asociere de una-la-multe cu o relaţie B dacă fiecărei înregistrări din A îi
corespund una sau mai multe înregistrări din relaţia B. Unei înregistrări din relaţia B nu îi corespunde
decât maxim o înregistrare din relaţia A.
Exemplu:
FACTURI LINII_FACTURI
nr_factura# nr_factura#
data_factura cod_produs#
nume_client cantitate
delegat pret_unitar
Observaţie: Relaţia A are cheia primară „ nr_factura”, iar relaţia B are atributul „ cod_produs” cheie
externă.
33
• Asocieri de la mai multe-la-multe
O relaţie A se află în asociere de tipul multe-la-multe cu o relaţie B dacă unei înregistrări din relaţia A
îi pot corespunde mai multe înregistrări din relaţia B şi unei înregistrări din relaţia B îi pot corespunde
mai multe înregistrări din relaţia A.
Exemplu:
A 1:M B 1:M C
FACTURI LINII_FACTURI PRODUSE
Observaţie: În exemplul de mai sus, relaţia LINII_FACTURI realizează joncţiunea între relaţiile
FACTURI şi PRODUSE, stocând informaţiile privind nr_factura, cod_produs, cantitate, pret_unitar
etc.
Interogarea datelor din mai multe relaţii folosind aliasuri (sau pseudonime)
Un alias este o redenumire fie a unui câmp, fie a unei relaţii. Aliasurile sunt utilizate la eliminarea
rescrierii complete a denumirii unei relaţii sau a unui câmp, redenumindu-le într-un mod simplificat.
Există posibilitatea de a utiliza aliasuri pentru tabelele din clauza FROM şi utilizarea lor în cadrul
comenzii SELECT respective (alias.coloana). Această identificare (prin 'tabel.coloana' sau
'alias.coloana') este obligatorie atunci când se face referinţă la o coloană ce apare în mai mult de un
tabel din clauza FROM.
Observaţie: În cazul în care un atribut apare doar într-o relaţie dintre cele menţionate în listă, nu este
obligatorie precizarea relaţiei (adică a aliasului) din care face parte atributul respectiv.
Exemplu: Selectaţi numărul facturii şi denumirea produselor fiecărei facturi folosind operaţia de join,
apoi utilizând clauza WHERE.
SELECT F.nr_factura, P.cod_produs, P.denumire_produs
FROM LINII_FACTURI F INNER JOIN PRODUSE P
ON (F.cod_produs =P.cod_produs);
Observaţii:
• Rezultatul este acelaşi. Valorile NULL vor fi ignorate;
• Sintaxei SELECT-FROM-INNER JOIN i se pot adăuga şi alte condiţii, neincluse în condiţiile
de join, dacă acestea se referă la alte câmpuri decât cele care participă la join.
selectează toate informaţiile din A, pe care le completează cu informaţii din B, în măsura în care
satisfac condiţiile de join; acolo unde nu vor exista informaţii din B, acestea vor fi completate cu
NULL.
Exemplu: Selectaţi toate facturile. Dacă există informaţii despre aceste facturi, afişaţi şi aceste
informaţii.
SELECT *
FROM LINII_FACTURI F LEFT OUTER JOIN PRODUSE P
ON (F.cod_produs =P.cod_produs);
Observaţie: Ordinea în care se scrie denumirea relaţiei în sintaxa LEFT OUTER JOIN este foarte
importantă. Astfel, relaţia din stânga este relaţia primară, adică relaţia pentru care se doreşte returnarea
tuturor informaţiilor; relaţia din dreapta este relaţia secundară, adică informaţiile din ea sunt necesare
doar în măsura în care se potrivesc condiţiilor de asociere. Astfel se explică şi denumirea de asociere
de la stânga spre exterior.
selectează toate informaţiile din B, pe care le completează cu informaţii din A, în măsura în care
satisfac condiţiile de join; acolo unde nu vor exista informaţii din A, acestea vor fi completate cu
NULL.
35
Exemplu: Selectaţi toate facturile și produsele corespunzătoare, inclusiv facturile fără niciun produs.
SELECT *
FROM PRODUSE P RIGHT OUTER JOIN LINII_FACTURI F
ON (P.cod_produs =F.cod_produs);
Observaţie: Sintaxa RIGHT OUTER JOIN este utilizată mai rar; de obicei se utilizează sintaxa LEFT
OUTER JOIN.
şi returnează înregistrări distincte dacă este folosită instrucţiunea UNION, şi toate înregistrările dacă
se foloseşte UNION ALL. Astfel operatorul UNION elimină duplicatele, iar UNION ALL
vizualizează toate înregistrările, inclusiv duplicatele.
Pentru a utiliza această interogare, trebuie să se ţină seama de două cerinţe: domeniile Câmp 1A, Câmp
2A,..., Câmp nA şi Câmp 1, Câmp 2, ..., Câmp n trebuie să fie respectiv aceleaşi şi, numărul de
câmpuri din fiecare interogare trebuie să coincidă.
Operatorul UNION se foloseşte atunci când între relaţii nu există o asociere directă.
Interogarea datelor mai multor relaţii folosind operatorul de concatenare a două şiruri de caractere
Rolul operatorului de concatenare a două şiruri de caractere este de a uni două şiruri de caractere într-
unul singur. Este utilizat în toate SGBD-urile, cu mici modificări ale simbolului: în SQL se foloseşte
simbolul ‚+’, în Oracle simbolul ‚||’ etc.
Se pot concatena o constantă cu un câmp, sau două câmpuri. Câmpurile trebuie să fie de tip text.
returnează un număr egal cu valoarea maximă a câmpului Nume_câmp din relaţia Nume_tabela,
valorile NULL fiind ignorate.
Exemplu: Selectaţi cea mai recentă factură din tabela FACTURI, fără a da un nume rezultatului, apoi
cu nume pentru câmpul rezultat.
SELECT MAX(data_factura) FROM FACTURI;
Atât funcţia MIN cât şi funcţia MAX se pot aplica doar pentru tipurile de date numeric sau dată
calendaristică.
Funcţia SUM se aplică acelor câmpuri care au domeniul de valori de tipul FLOAT, DECIMAL,
NUMERIC, INT etc. şi nu are sens pentru câmpuri de tip text.
37
• Interogarea datelor folosind funcţia AVG
Sintaxa:
AVG (nume_câmp) FROM Nume_tabela
returnează un număr egal cu media aritmetică a tuturor valorilor câmpului Nume_câmp din relaţia
Nume_tabela. Valorile NULL sunt ignorate.
Funcţia AVG se utilizează doar pentru date de tip numeric: INT, FLOAT, NUMERIC.
Exemplu: Selectaţi fiecare produs în parte grupându-le crescător şi precizaţi cantitatea vândută din
fiecare tip.
SELECT P.denumire_produs, SUM(F.cantitate) AS suma
FROM PRODUSE P, LINII_FACTURI F
WHERE F.cod_produs= P.cod_produs
GROUP BY P.cod_produs;
Observație: Menţionarea clauzelor SELECT, FROM, WHERE, GROUP BY, ORDER BY în această
ordine este obligatorie. Greşeala frecventă care duce la apariţia unor mesaje de eroare este aceea a
introducerii unor câmpuri după care se grupează în clauza SELECT şi neintroducerea lor în clauza
GROUP BY.
Exemplu: Selectaţi produsele grupate după cod care au preţul unitar cuprins între 500 şi 3000.
SELECT P.denumire_produs, P.cod_produs, F.pret_unitar
FROM PRODUSE P, LINII_FACTURI F
WHERE F.cod_produs= P.cod_produs
GROUP BY P.cod_produs
HAVING F.PRET_UNIRAR BETWEEN 500 AND 3000;
38
6.2. Adăugarea de noi tupluri (Comanda INSERT)
În vederea adăugării unor rânduri noi într-o tabelă sau într-o vizualizare se utilizează comanda
INSERT. Instrucţiunea are două forme de bază: una în care valorile coloanelor sunt specificate chiar în
instrucţiune şi alta în care valorile sunt selectate dintr-un tabel sau o vizualizare, folosind o
subinterogare.
Exemplu:
INSERT INTO PRODUSE (cod_produs, denumire_produs,
unitate_de_masura, data_expirarii)
VALUES (50, ‘PAINE’, ‘KG’,’2017-05-15’);
Clauza VALUES specifică valorile ce vor fi introduse în tabel sau vizualizare. Pentru a insera mai
multe linii prin aceeaşi instrucţiune INSERT, în locul acestei clauze se va preciza o subcerere.
Dacă nu se mai cunoaşte ordinea de declarare a coloanelor se foloseşte comanda DESCRIBE care va
afişa lista coloanelor definite pentru tabela respectivă, tipul şi lungimea lor.
39
INSERT INTO PRODUSE (cod_produs, denumire_produs,
unitate_de_masura)
VALUES (50, ‘PAINE’, ‘KG’);
sau explicit, prin specificarea în lista de valori a cuvântului cheie NULL sau a şirului vid (‘’)
în cazul şirurilor de caractere sau datelor calendaristice. Exemplu:
INSERT INTO PRODUSE (cod_produs, denumire_produs,
unitate_de_masura, data_expirarii)
VALUES (50, ‘PAINE’, ‘KG’, NULL);
Se remarcă următoarele:
• lista de coloane este opţională, dar dacă este inclusă trebuie să fie încadrată între paranteze
rotunde;
• dacă lista de coloane este omisă, instrucţiunea SELECT internă trebuie să furnizeze o valoare
pentru fiecare coloană din tabel, în ordinea în care sunt definite coloanele în tabel. Este
bine ca întotdeauna să se includă lista de coloane, deoarece omiterea acesteia face ca
instrucţiunea INSERT să fie dependentă de definiţia tabelului. Dacă o coloană este
modificată sau în tabel este adăugată o nouă coloană, chiar şi opţională, probabil
instrucţiunea INSERT va eşua la următoarea rulare;
• dacă lista de coloane este specificată, instrucţiunea SELECT internă trebuie să furnizeze o
valoare pentru fiecare coloană din lista de valori, în aceeaşi ordine. Cu alte cuvinte, între
lista de coloane şi setul de rezultate al instrucţiunii SELECT trebuie să existe o
corespondenţă una-la-una. Orice coloană care lipseşte din listă va primi o valoare nulă,
presupunând că valorile nule sunt acceptate în coloana respectivă;
• cuvântul cheie NULL poate fi folosit în instrucţiunea SELECT pentru specificarea unei valori
nule pentru o coloană.
Dacă o dată calendaristică necesită specificarea altui secol sau oră, trebuie folosită funcţia TO_DATE.
Exemplu:
INSERT INTO PRODUSE (cod_produs, denumire_produs,
unitate_de_masura, data_expirarii)
VALUES (50, ‘PAINE’, ‘KG’, TO_DATE(‘FEB-3 , 2017’, 'MON-DD,
YYYY’));
40
Inserare de valori folosind variabile de substituţie
Exemplu:
ACCEPT cod_produs PROMPT 'Introduceti codul produsului:'
ACCEPT denumire_produs PROMPT 'Introduceti denumirea produsului:'
INSERT INTO PRODUSE (cod_produs, denumire_produs)
VALUES (‘&cod_produs’, ‘&denumire_produs’)
Exemplul înregistrează informaţia pentru un produs, în tabelul PRODUSE. Utilizatorului îi sunt cerute
codul produsului şi denumirea produsului, folosind mesajele de prompt stabilite în ACCEPT.
Parametrul de substitutie SQL*Plus nu trebuie precedat de & când este referit într-o comanda
ACCEPT. Pentru a continua o comandă SQL*PLUS pe linia următoare se foloseşte o linie (-).
Numărul şi tipul câmpurilor (coloanelor) din lista specificată în comanda INSERT trebuie să
corespundă numărului şi tipului valorilor din subinterogare.
Exemplu:
INSERT INTO PRODUSE (cod_produs, denumire_produs,
unitate_de_masura)
SELECT cod_produs, denumire_produs, unitate_de_masura
FROM PRODUSE
WHERE denumire_produs = 'PAINE';
Inserări multitabel
O inserare multitabel presupune introducerea de linii calculate pe baza rezultatelor unei subcereri, în
unul sau mai multe tabele. Acest tip de inserare, introdus de Oracle, este util în mediul data
warehouse. Astfel, datele extrase dintr-un sistem sursă, pot fi transformate utilizând instrucţiuni
INSERT multitabel, spre a fi încărcate în obiectele bazei de date.
41
Sintaxa clauzei inserare_multi_tabel este următoarea:
INSERT ALL INTO…[VALUES…] [INTO…[VALUES…] …]
| inserare_condiţionată| subcerere
Utilizând clauza inserare_condiţionată, decizia inserării unei linii depinde de condiţia specificată prin
intermediul opţiunii WHEN. Expresiile prezente în aceste condiţii trebuie să facă referinţă la coloane
returnate de subcerere. O instrucţiune de inserare multitabel poate conţine maxim 127 clauze WHEN.
Specificarea opţiunii ALL determină evaluarea tuturor condiţiilor din clauzele WHEN. Pentru cele a
căror valoare este TRUE, se inserează înregistrarea specificată în opţiunea INTO corespunzătoare.
Opţiunea FIRST determină inserarea corespunzătoare primei clauze WHEN a cărei condiţie este
evaluată TRUE. Toate celelalte clauze WHEN sunt ignorate.
Dacă nici o condiţie din clauzele WHEN nu este TRUE, atunci sistemul execută clauza INTO
corespunzătoare opţiunii ELSE, iar dacă aceasta nu există, nu efectuează nici o acţiune.
Inserările multitabel pot fi efectuate numai asupra tabelelor, nu şi asupra vizualizărilor. De asemenea,
acest tip de inserare nu se poate efectua asupra tabelelor distante. Subcererea dintr-o instrucţiune
corespunzătoare unei inserări multitabel nu poate utiliza o secvenţă.
În funcţie de momentul în care se doreşte realizarea modificărilor asupra bazei de date, utilizatorul
poate folosi una din următoarele comenzi:
• SET AUTOCOMMIT IMM[EDIATE] (schimbările se efectuează imediat);
• SET AUTOCOMMIT OFF (schimbările sunt păstrate într-un buffer).
Instrucţiunea UPDATE este folosită pentru actualizarea datelor din coloanele unui tabel (sau ale unei
vizualizări).
Valorile câmpurilor care trebuie modificate pot fi furnizate explicit sau pot fi obţinute în urma unei
cereri SQL.
Observaţii:
• Pentru a se putea executa instrucţiunea UPDATE, utilizatorul care o lansează în execuţie
trebuie să aibă acest privilegiu;
• Dacă nu este specificată clauza WHERE se vor modifica toate liniile;
• Cererea trebuie să furnizeze un număr de valori corespunzător numărului de coloane din
paranteza care precede caracterul de egalitate.
Se remarcă următoarele:
• clauza SET conţine o listă cu una sau mai multe coloane, împreună cu o expresie care
specifică noua valoare pentru fiecare coloană. Aceasta este o listă de perechi
(NUME,VALOARE), separate prin virgule, cu un operator de egalitate între fiecare
NUME şi VALOARE;
• expresia poate fi o constantă, un alt nume de coloană sau orice altă expresie pe care SQL o
poate transforma într-o singură valoare, care poate fi apoi atribuită coloanei respective;
• clauza WHERE conţine o expresie care limitează rândurile actualizate. Dacă această clauză
este omisă, motorul SQL va încerca să actualizeze toate rândurile din tabel sau din
vizualizare.
Oracle permite utilizarea valorii implicite DEFAULT în comenzile INSERT și UPDATE. Unei
coloane i se atribuie valoarea implicită definită la crearea sau modificarea structurii tabelului dacă:
• nu se precizează nici o valoare;
• 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. Cuvântul cheie DEFAULT nu poate fi specificat la actualizarea vizualizărilor.
Cazurile în care instrucţiunea UPDATE nu poate fi executată sunt similare celor în care eşuează
instrucţiunea INSERT.
Notă: În general, se folosește cheia primară pentru a identifica o singură înregistrare. Folosirea altor
coloane poate determina modificarea mai multor înregistrări.
De exemplu, identificarea unei singure înregistrări în tabelul PRODUSE prin denumire poate fi
periculoasă, deoarece pot exista mai multe produse cu aceeaşi denumire.
Comanda UPDATE modifică anumite înregistrări dacă este specificată clauza WHERE.
Exemplul următor mărește prețul unitar cu 25% pentru produsul cu codul 50.
UPDATE LINII_FACTURI
43
SET pret_unitar = pret_unitar * 1.25
WHERE cod_produs = 50;
Modificarea înregistrarilor folosind subinterogări după mai multe câmpuri (folosind valori dintr-un
alt tabel)
În clauza SET a unei comenzi UPDATE pot fi implementate subinterogări după mai multe câmpuri.
UPDATE nume_tabel
SET (coloana, coloana, ...) =
(SELECT coloana, coloana,
FROM nume_tabel
WHERE conditie)
WHERE conditie;
Dacă se încercă atribuirea unei valori unui câmp care are legată de o constrângere de integritate, va
rezulta o eroare.
Instrucţiunea DELETE şterge unul sau mai multe rânduri dintr-un tabel. Instrucţiunea poate să
folosească şi o vizualizare, dar numai dacă aceasta se bazează pe un singur tabel (ceea ce înseamnă că
instrucţiunile DELETE nu pot fi folosite pentru vizualizări care conţin uniuni). În instrucţiunile
DELETE nu sunt referite niciodată coloane, doarece instrucţiunea şterge rânduri întregi de date,
inclusiv toate valorile datelor (toate coloanele) din rândurile afectate. Dacă se şterge o singură valoare
din rândurile existente, se folosește instrucţiunea UPDATE pentru a înlocui valorile respective cu
valori nule (presupunând că valorile nule sunt permise în acele coloane).
Se remarcă următoarele:
• comanda DELETE nu şterge structura tabelului;
• clauza WHERE este opţională. Totuşi, este folosită aproape întotdeauna, deoarece o
instrucţiune DELETE fără o clauză WHERE încearcă să şteargă toate rândurile din tabel.
În clauza WHERE pot fi folosite şi subcereri;
• atunci când este inclusă, clauza WHERE specifică rândurile care urmează să fie şterse. Orice
rând pentru care condiţia WHERE este evaluată ca adevărată este şters din tabel;
• nu se pot şterge rânduri dacă se încalcă o restricţie referenţială. În general, rândurile
subordonate trebuie şterse înaintea rândurilor părinte;
• pentru a şterge linii identificate cu ajutorul valorilor din alte tabele, se utilizează subcereri;
44
• comanda nu poate fi folosită pentru ştergerea valorilor unui câmp individual. Acest lucru se
poate realiza cu ajutorul comenzii UPDATE.
Dacă se încearcă ştergerea unei înregistrări care conţine o valoare implicată într-o constrângere de
integritate, atunci va fi returnată o eroare.
În cazul în care constrângerea de integritate referenţială a fost definită utilizând opţiunea ON DELETE
CASCADE, atunci instrucţiunea DELETE va şterge atât liniile indicate, cât şi liniile „copil“ din
tabelele corespunzătoare.
Ştergerile accidentale pot fi omise, restaurându-se valorile iniţiale prin comanda AUTOCOMMIT
OFF.
Exemplu: Stergeţi toate produsele care expiră înainte de 1 Ianuarie, 2017. Ştergerile să nu fie efectuate
imediat ci ulterior.
SET AUTOCOMMIT OFF
DELETE FROM PRODUSE
WHERE data_expirarii > TO_DATE('01-01-17', 'DD-MM-YY');
Exemplul de mai jos şterge toate produsele cu denumirea PAINE. Subinterogarea caută în tabelul
PRODUSE codul produsului PAINE, apoi furnizează codul interogării principale, care şterge
înregistrările din LINII_PRODUSE pe baza acestuia.
DELETE FROM LINII_PRODUSE
WHERE cod_produs =
(SELECT cod_produs
FROM PRODUSE
WHERE denumire_produs = 'PAINE');
În exemplul de mai jos se încearcă ştergerea produsului cu codul 10 din tabelul PRODUSE, dar
aceasta provoacă o eroare, deoarece codul produsului este folosit ca şi cheie externă în tabelul
LINII_FACTURI.
Dacă înregistrarea părinte, care se încearcă să se şteargă, are înregistrări fii, atunci se primește un
mesaj de eroare: child record found violation ORA - 02292.
DELETE FROM PRODUSE
WHERE cod_produs = 50;
45
Controlul unei baze de date cu ajutorul SQL-ului se referă la:
• asigurarea confidentialităţii şi securităţii datelor;
• organizarea fizică a datelor;
• realizarea unor performanţe;
• reluarea unor acţiuni în cazul unei defecţiuni;
• garantarea coerenţei datelor în cazul prelucrării concurente.
Comenzile de control la dispoziția administratorului (DBA) - GRANT, REVOKE – sunt utilizate pentru
a da sau a lua drepturi de acces (la comenzi LMD, deci la operarea unor modificări a bazei de date).
Sintaxa:
GRANT
[Privilegii]
ON
TO
Utilizator IDENTIFIED BY ’DenumireParola’;
REVOKE
[Privilegii]
ON
TO
Utilizator IDENTIFIED BY ’DenumireParola’;
Reluarea unor acțiuni în cazul apariţiei unei defecțiuni hard sau soft presupune recuperarea ultimei
stări coerente a bazei de date. În funcţie de defecţiunea care a determinat întreruperea lucrului,
restaurarea bazei de date se realizează automat de SGBD sau manual, adică necesită intervenţie
umană.
46
Salvarea bazei de date se realizează conform unei strategii existând combinaţiile:
copii ale bazei de date şi copii ale jurnalelor acestora;
jurnale ale tranzacţiilor;
jurnale ale imaginii înregistrărilor din baza de date.
Copiile bazei de date - pot fi realizate automat de sistem la anumite intervale de timp sau la comanda
administratorului bazei de date, ori de câte ori este nevoie şi de obicei pe un alt suport magnetic decât
cele pe care rezidă baza de date. Aceste copii pot fi utilizate doar în situaţia în care prelucrările
efectuate între momentul realizării copiilor şi cel al apariţiei unei defecţiuni pot fi reluate. Acest lucru
este posibil doar dacă prelucrările sunt efectuate într-o secvenţă cunoscută iar timpul necesar pentru
reprocesarea nu este foarte mare. Durata mare de execuţie pentru astfel de copii face ca anumite
SGBD-uri să recurgă la copii ale jurnalelor bazei de date. Volumul datelor care vor fi copiate în acest
caz va fi mai mic, iar procesul de restaurare va implica într-o măsură mai mică intervenţia umană.
Jurnalul tranzacţiilor - este un fişier special întreţinut de SGBD, în care sunt memorate informaţiile
despre tranzacţiile efectuate asupra bazei de date, cum sunt:
identificatorul sau codul tranzacţiei;
momentul începerii execuţiei tranzacţiei;
numărul terminalului sau identificatorul utilizatorului care a iniţiat tranzacţia;
datele introduse;
înregistrările modificate şi tipul modificării.
Jurnalul imaginilor înregistrărilor din baza de date - se deosebeşte de jurnalul tranzacţiilor prin aceea
că el nu conţine descrierea operaţiilor efectuate asupra bazei de date, ci efectul acestora.
Sistemul de gestiune a bazelor de date asigură accesul concurent al mai multor utilizatori la baza de
date. Fiecare utilizator trebuie să aibă o vedere validă și consistentă asupra bazei de date, incluzând și
modificările făcute de alți utilizatori; în același timp, procesarea incorectă a datelor trebuie evitată,
pentru a nu afecta consistența datelor sau integritatea acestora.
Pentru ultimele două, se utilizează blocarea datelor (primul utilizator care le accesează, le blochează).
Cu cât dimensiunea datelor blocate este mai mică, cu atât gestionarea accesului concurențial este mai
eficientă.
Coerenţa este asigurată cu ajutorul conceptului de tranzacţie. Tranzacţia este unitatea logică de lucru
constând din una sau mai multe instrucţiuni SQL, care trebuie să fie executate atomic (ori se execută
toate, ori nu se execută nici una!), asigurând astfel trecerea BD dintr-o stare coerentă în altă stare
coerentă. Dacă toate operaţiile ce constituie tranzacţia sunt executate şi devin efective, spunem că
tranzacţia este validată (COMMIT), iar modificările (INSERT, DELETE, UPDATE) aduse de
47
tranzacţie devin definitive (modificările sunt înregistrate şi sunt vizibile tuturor utilizatorilor). Din
acest punct prima instrucţiune SQL executabilă va genera automat începutul unei noi tranzacţii.
Dacă dintr-un motiv sau altul (neverificarea condiţiilor, accesul imposibil) o operaţie a tranzacţiei nu a
fost executată spunem că tranzacţia a fost anulată (ROLLBACK). Modificările aduse de toate
operaţiile tranzacţiei anulate sunt şi ele anulate şi se revine la starea bazei de date de dinaintea
tranzacţiei anulate. Executarea unei instrucţiuni ROLLBACK presupune terminarea tranzacţiei curente
şi începerea unei noi tranzacţii.
Este posibil ca o tranzacţie să fie descompusă în subtranzacţii, astfel încât dacă este necesar să se
anuleze doar parţial unele operaţii.
Limbajul pentru controlul datelor (LCD) permite salvarea informaţiei, realizarea fizică a modificărilor
în baza de date, rezolvarea unor probleme de concurenţă.
Oracle XE este o versiune de bază de date ideală pentru training și inițiere în tehnologia bazelor de
date. Este gratuită și poate fi instalată pe orice mașina (fizică sau virtuală) singurele ei limitari fiind
cele legate de spațiul de stocare (poate folosi până la 11 GB), respectiv memorie și processor (până la
1 Gb RAM și 1 procesor/mașină). Suportul este asigurat pe Oracle Discussion Forum, o comunitate
monitorizată de Oracle și alți experți în domeniu. Pașii preliminari sunt:
1. Se descarcă Oracle XE în funcție de sistemul de operare pe care se va instala (32 bit/64 bit):
http://www.oracle.com/technetwork/database/database-technologies/express-
edition/downloads/index.html
2. Se descarcă Apex:
http://www.oracle.com/technetwork/developer-tools/apex/downloads/index.html
3. Se instalează Oracle XE, singurele input-uri așteptate de la utilizator fiind:
a. calea unde va fi instalat (default pe drive-ul C)
b. parola pentru administratorul bazei de date (sysdba)
Datorită faptului că Oracle XE conține o versiune mai veche de Apex, aceasta trebuie
upgradată cu versiunea descarcată la pasul 2. Pașii de upgrade sunt următorii:
49
1. Se dezarhivează versiunea descarcată la pasul 2 în directorul C:\apex
2. Se deschide un command prompt și se navighează în calea de mai sus:
cd C:\apex
3. Folosind SQLPLUS ne conectăm la baza de date instalată anterior:
{Command prompt} C:\apex> sqlplus /nolog
SQL> CONNECT SYS as SYSDBA
Enter Password: SYS_Password // parola de sysdba setată anterior
4. Se instalează Apex:
SQL> @apexins SYSAUX SYSAUX TEMP /i/
5. Se loghează din nou în SQL Plus și se execută comanda:
{Command prompt} C:\apex> sqlplus /nolog
SQL> CONNECT SYS as SYSDBA
Enter Password: SYS_Password
SQL> @apxldimg.sql C:\
6. Se introduce parola pentru apex-ul nou instalat:
SQL> @apxchpwd
Enter password for Application Express ADMIN account.
7. Pentru a accesa Apex-ul nou instalat se accesează link-ul:
http://localhost:8080/apex/apex_admin
în Username, enter ADMIN
în Password, enter the password entered în Step 6
50
ORACLE SQL DEVELOPER
51
APLICAȚII REZOLVATE
Să se creeze tabelele din figura de mai sus în care sa fie precizate restricțiile de integritate:
Crearea tabelelor
create table prof.emp --contine angajatii unei firme
(empno number(6,0) constraint emp_empno_pk
primary key, --cheia primara
firstname varchar2(25),
lastname varchar2(25) constraint
emp_lastname_nn not null,
cnp varchar(13),
phone varchar2(20),
email char(50) constraint emp_email_nn not
null,
adr varchar2(60) default 'necunoscuta',
jobid varchar2(10) constraint emp_jobid_nn
not null,
hiredate date constraint
emp_hiredate_nn not null, --data angajarii pe postul actual
mgr number(6,0), --cod manager
sal number(9,2),
comm number(9,2), --comision
deptno number(4,0)
);
52
Vizualizarea campurilor
describe prof.emp;
53
create table prof.jobs
(jobid varchar2(10) constraint jobs_jobid_pk
primary key,
job varchar2(40) constraint jobs_job_nn not
null, --denumire job
minsal number(9,2),
maxsal number(9,2)
);
describe prof.jobs;
Schema curenta
alter session set current_schema=prof;
Adaugarea constrangerilor
alter table emp
add constraint emp_deptno_fk foreign key(deptno)
references prof.dept(deptno);
55
Crearea unui script pentru manipularea datelor
Prin intermediul comenzii sql*plus ACCEPT, mesajele afisate la cererea introducerii valorilor pot fi
modificate.
• accept - memoreaza valoarea intr-o variabila;
• prompt - afiseaza textul specificat.
--sau
--sa se adauge in tabela dept datele pentru noul departament (cu
date introduse de la tastatura).
prompt Sa se adauge in dept datele pentru:
insert into dept (deptno, dname,locid)
values(&deptno,'&dname',&locid);
select* from dept;
56
Modificarea tabelelor
--adaugati o noua coloana tabelului emp care sa contina comentarii
alter table emp
add (comments varchar2(80));
describe prof.emp;
Tipuri de constrangeri
Constrangerile de tip CHECK se pot implementa la nivel de coloana doar daca nu refera o alta
coloana a tabelului
--sa se adauge restrictia de validare: sal>0
alter table emp
add (constraint emp_sal_chk check(sal>0);
Instructiunnea SELECT
Sintaxa generala
select [all/distinct/unique] lista de selectie (coloane, alias)
from lista de relatii (tabele)
where conditie de cautare asupra liniilor
57
group by lista de atribute care permit partitionarea
having conditie asupra partitiilor
order by lista de atribute [asc|desc];
Tipuri de operatori:
operatori aritmetici: +, -, * , ...
operatori de comparatie: <, <=, >, >=, =, <>, between, in, is, like...
operatori logici: and, or, not
operatori relationali: union, intersec, minus
Functia generala nvl (expr1, expr2) forteaza functiile grup sa includa valori nulle.
select firstname, sal, sal*12, comm, sal*12 + nvl(comm,0)
venituri_anuale from emp;
Randuri duplicate
select deptno from emp;
Ordonarea inregsitrarilor
--afisati angajatii in ordine alfabetica
select firstname
from emp
order by firstname;
58
--sa se afiseze numele si salariul tuturor angajatilor. Rezultatele sa se afiseze crescator dupa
numarul departamentului si descrescator dupa salariu:
select deptno, firstname, sal
from emp
order by deptno, sal desc;
Clauza WHERE
--ulterior se poate adauga la linia de stare (o selectie explicita, prin introducerea codului
corespunzator managerului).
select *
from emp
where mgr=&cod_manager; --7698
--afisati managerii
select firstname, deptno
from emp
where mgr is null;
59
--afisati numele care incep cu litera s, procent (%)
select *
from emp
where firstname like 's%';
--sa se selecteze numele, adresa si emailul tuturor persoanelor din bucuresti care au adresa de
email pe gmail sau spiruharet.
select firstname, adr, email
from emp
where adr like '%bucuresti%' and (email like '%gmail%' or email like
'%spiruharet%');
Negarea comparatiei
--afisati date depre angajatii care nu fac parte din departamentele 10 si 30
select *
from emp
where deptno not in(10,30);
Conditii multiple
--afisati salariatii din departamentul 10 care au salariul cel putin 1000
select *
from emp
where deptno = 10 and sal >= 1000;
--
select *
from emp
where deptno = 20 and jobid='ac_mgr' or jobid ='ad_vp' ;
60
--
select *
from emp
where deptno = 20 and (jobid='ac_mgr' or jobid ='ad_vp');
Functii de tip caracter - accepta argumente de tip caracter si intorc rezultate de tip caracter
(chr, concat, initcap, lower, upper, lpad & rpad, ltrim & rtrim, translate, replace, substr etc.) sau
numeric (ascii, instr, length).
--afisati toate persoanele al caror nume contine litera a (cu litere mici) pe orice pozitie
select *
from emp
where lower(firstname) like '%a%';
--sa se afiseze departamentele din alte localitati decat Bucuresti (cu litere mari).
select *
from locations
where upper (city) <> 'bucuresti' ;
--lpad(string,len,pstring)
--rpad(string,len,pstring)
--completatii cu spatii la stanga
select lpad(city,10,'-') from locations;
--substr(string,pos,len)
--extrageti din coloanal CNP din tabelum emp, ziua, luna si anul nasterii
select firstname as numele, substr(cnp,6,2) as ziua, substr(cnp,4,2)
luna, substr(cnp,2,2) anul_nasterii
from emp;
--instr(string,search)
--instr(string,search,pos,n)
--in numele localitatilor, determinati pozitia de inceput pe care se gaseste subsirul tt
select city, instr(city,'tt') from locations;
--ltrim(string,rem)
--rtrim(string,rem)
--
select ltrim(' tech', ' ') from dual;
--
select rtrim('tech ', ' ') from dual;
--length(string)
--sa se afiseze lungimea atributului nume din tabela emp
select firstname, length (firstname) lungime_nume from emp;
61
--translate(string,from,to)
--in denumirea localitatilor inlocuiti litera o cu m
select city, translate(city,'o','m') from locations;
--replace(string,search,replace)
--replace(string,search)
Functii de tip numeric: mod, abs, sqrt,exp, de calcul trigonometric (sin, sinh, tan, tanh, cos,
cosh, ctg etc.; de calcul al logaritmului: ln, log, lg; de calcul al puterilor: pow; de rotunjire: floor, ceil,
round, trunc, etc.) - accepta argumente de tip numeric si intorc rezultate de tip numeric.
--round(number,n)
--afisati media primelor rotunjita la 2 zecimale
select avg(nvl(comm,0)), round (avg(nvl(comm,0)),2)from emp;
--trunc(number,n)
select avg(nvl(comm,0)),trunc (avg(nvl(comm,0)),1) from emp;
Functia trunc(data1,'char') gaseste prima zi a lunii care e continuta in data1, daca char = 'month',
sau gaseste prima zi a anului care contine data1 daca char= 'year'.
select sysdate data_curenta,
trunc (sysdate, 'month') prima_zi_luna,
trunc (sysdate,'year') prima_zi_an
from sys.dual;
--ceil(number)
--floor(number)
select avg(nvl(comm,0)), ceil(avg(nvl(comm,0))) from emp;
--
select avg(nvl(comm,0)), floor(avg(nvl(comm,0))) from emp;
--months_between(date1,date2)
select firstname, hiredate,
round(months_between(sysdate,hiredate),0) from emp;
--add_months(date,mon)
select firstname, hiredate, add_months(hiredate,2) from emp;
62
--next_day(date,day)
--sa se afiseze urmatoarea zi de sambata (dupa data curenta-->sysdate)
select next_day (sysdate,'saturday') urmatoarea_sambata from dual;
--last_day(date)
select firstname, hiredate, last_day(hiredate) from emp;
--sa se afiseze numele angajatilor si data implinirii limitei de varsta pentru pensionare (65 de
ani) precum si numarul de luni ramase pana la pensionare (65 ani*12 luni).
select firstname, datan,
add_months (datan, 65*12) data_pensionare,
round (months_between(add_months(datan,65*12),sysdate),2)
luni_ramase_pensionare
from emp;
Functii de conversie: to_char, to_number, to_date - fac conversia dintr-un tip de data in altul;
--to_char(number)
--to_char(number,format)
--to_char(date)
--to_char(date,format)
--to_date(string)
--to_date(string,format)
--
select to_date(hiredate,'dd-mon-yyyy') from emp;
Functii care accepta orice tip de tip de date: nvl, greatest & least, decode
--
select nvl(comm,0)from emp;
--greatest(value1,value2, …)
--least(value1,value2, …)
63
Functia generala decode evalueaza o expresie intr-un mod similar structurii if-then-else.
decode( value,
, search1, result1
[, search2, result2 . . .]
, default)
--
select count(distinct jobid) from emp;
--sa se afiseze salariul de baza mediu, minim si maxim pentru toti salariatii cu codul cuprins
intre 7000 si 7500.
select sum(sal), round (avg (sal),2) mediu, min (sal) minim, max
(sal) maxim
from emp
where empno between 7000 and 7500;
Instructiunea CASE
--sa se specifice daca un angajat dat are salariu mic, mediu, bun sau excellent dupa cum este mai
mic decat 5000, cuprins intre [5000,10.000), cuprins intre [10.000,15.000] sau mai mare decat
15.000.
select firstname, sal,
(case
when sal <5000 then 'mic'
when sal <10000 then 'mediu'
when sal <=15000 then 'bun'
else 'excelent'
end) as calificare
from emp;
64
Gruparea datelor
Functiile de agregare se pot folosi ca extensii ale clauzei group by:
• rollup - permite instructiunii select sa calculeze niveluri de subtotal multiple peste un grup de
dimensiuni;
• cube - genereaza toate subtotalurile care pot fi calculate dintr-un cube pe dimensiunile
specificate;
• grouping;
• grouping set.
--in departamentul 30 afisati media salariilor pentru fiecare job, daca aceasta este mai mare de
3700
select jobid, round(avg(sal),2)
from emp
where deptno = 30
group by jobid
having round(avg(sal),2) > 3700;
--
select firstname, e.deptno, dname, jobid
from emp e, dept d
where e.deptno = d.deptno and jobid = 'ac_mgr';
--
select e.firstname, d.dname, d.deptno
from emp e, dept d
where e.deptno(+) = d.deptno;
Union
--afisaja job-urile din ambele departamente (10 si 30)
select jobid, deptno from emp
where deptno=10
union
select jobid, deptno from emp
where deptno=30;
65
Intersect
select deptno from dept
intersect
select deptno from emp;
Minus
select deptno from dept
minus
select deptno from emp;
Subinterogari
select column(s)
from table(s)
where column(s) = (select column(s)
from table(s)
where condition(s) );
--afisati angajatii care lucreaza pe acelasi post cu angajatul care are numarul 7369, si au salariul
mai mic ca cel al angajatului cu numarul 7782.
select firstname, jobid, sal
from emp
where jobid=
(select jobid
from emp
where empno=7369)
and sal<
(select sal
from emp
where empno = 7782);
--sa se afiseze numele angajatilor care au cel mai mic salariu din departamentul din care fac
parte.
select firstname,sal,deptno
from emp
where (deptno,sal) in
66
(select deptno,min(sal)
from emp
group by deptno);
--sa se afiseze codul si numele angajatilor care au primele doua salarii cele mai mari.
select empno, firstname, sal
from
(select *
from emp
order by sal desc)
where rownum < 3;
--afisati toti angajatii care lucreaza in departamentul 10 si care castiga cel putin la fel ca
angajatii din departamentul 30
select firstname,sal,deptno
from emp
where sal >= any
(select sal
from emp
where deptno = 30)
and deptno = 10;
67
--afisati toti angajatii care lucreaza in departament cu managerul lor
select empno,firstname,jobid,mgr,deptno
from emp e1
where deptno in
(select deptno
from emp e
where e.empno = e1.mgr);
Folosind subinterogari in clauza from afisati numele angajatilor care realizeaza mai mult decat
media salariilor din departamentul in care lucreaza.
select e.firstname , e.sal , e.deptno , d.salavg
from emp e ,
(select deptno , round(avg(sal),2) salavg
from emp
group by deptno ) d
where e.deptno = d.deptno and e.sal > d.salavg;
--sa se afiseze, pentru fiecare angajat in parte, ce procent reprezinta salariul din totalul de
salarii de pe departament.
select e.firstname,e.deptno, round(e.proc/d.total*100,2) procent
from
(select firstname, deptno, sal proc
from emp
group by firstname, deptno, sal) e,
(select deptno,sum (sal) total
from emp
group by deptno) d
where e.deptno=d.deptno ;
68
- selecteaza toate informatiile din b, pe care le completeaza cu informatii din a, in masura in care
satisfac conditiile de join; acolo unde nu vor exista informatii din a, acestea vor fi completate cu null.
--
select e.firstname, d.dname
from dept d right outer join emp e
on (e.deptno = d.deptno);
--
select e.firstname, d.deptno
from emp e full outer join dept d
on (e.deptno = d.deptno);
--majorati salariul cu 15% pentru persoanele care au salariul identic cu cel al angajatului cu
codul 7788.
update emp
set sal=sal * 1.15
where sal in
(select sal
from emp
where empno = 7788);
select firstname,empno,sal from emp;
--modificati pentru angajatul numarul 7782 departamentul si slujba astfel incat sa coincida cu
cele ale angajatului numarul 7499.
update emp
set (jobid, deptno) =
69
(select jobid, deptno
from emp
where empno = 7499)
where empno = 7782;
select * from emp;
--modificati toate numerele de telefon din judetul maramures, astfel ca prefixul sa nu mai fie
0262 ci 0362, din baza de date emp.
update emp
set phone=concat('0362', substr(phone, 5))
where substr(phone,1,4)='0262';
select firstname,phone from emp;
Comanda DELETE
delete [from] table
[where condition];
--stergeti toate persoanele angajate dupa data de 10 iulie 1987. Stergerile sa nu fie efectuate
imediat ci ulterior.
set autocommit off
delete from emp
where hiredate > to_date('10-07-1987', 'dd-mm-yyyy');
select * from emp;
--
update emp
set sal = sal * 1.25;
commit;
select firstname, sal
from emp;
rollback [work];
rollback [work] to savepoint_name;
--
update emp
set sal = sal * 1.05
where deptno in
(select deptno
from dept
where locid = '1');
rollback;
select firstname, sal from emp;
savepoint savepoint_name;
--
update dept
set dname = upper(dname);
savepoint done_dept;
update emp
set sal = sal * 1.1;
rollback to done_dept;
commit;
select * from dept;
select * from emp;
--sa se stearga inregistrari din tabelul emp in functie de conditia introdusa: hiredate <
to_date('10-07-1987', 'dd-mm-yyyy')
accept p_conditie prompt 'introduceti conditia de stergere: '
begin
delete from emp
where &p_conditie;
end;
/
select * from emp;
71
Folosirea atributului %type
Putem defini tipul unei variabile in functie de tipul altei variabile sau a unei coloane de tabela.
--sa se creeze un bloc anonim in care se declara o variabila v_jobid de tip jobid (%type) a carei
valoare va fi codul jobului salariatului cu codul 7698
set serveroutput on
declare
v_jobid emp.jobid%type;
begin
select jobid into v_jobid
from emp
where empno=7698;
dbms_output.put_line('jobul este '|| v_jobid);
end;
/
--sa se specifice daca un angajat dat are salariu mare, mediu sau mic dupa cum este mai mare
decat 5000, cuprins intre 2000 si 5000 sau mai mic decat 2000
define p_empno = 7698;
declare
v_empno emp.empno%type := &p_empno;
v_sal emp.sal%type;
v_comentariu varchar2(10);
begin
select sal into v_sal
from emp
where empno = v_empno;
if v_sal < 2000 then v_comentariu := 'mic';
elsif v_sal between 2000 and 5000 then v_comentariu :=
'mediu';
else v_comentariu:= 'mare';
end if;
dbms_output.put_line('salariatul avand codul '|| v_empno ||'
are salariu '|| v_sal || ' considerat '|| v_comentariu);
end;
/
select * from emp;
Variabile de legatura - se utilizeaza pentru transmiterea valorii unor variabile din pl/sql catre
sql*plus. Referirea la o variabila de legatura se face in pl/sql prin prefixarea acestei variabile cu
caracterul „ : ”. In sql*plus, pentru declararea acestui tip de variabila se foloseste comanda
VARIABLE, iar valoarea variabilei de legatura va fi tiparita utilizand comanda PRINT.
--
variable v_jobid varchar2(35)
begin
select job into :v_jobid
from emp
where empno=7698;
--dbms_output.put_line('jobul este '|| :v_jobid);
end;
/
print v_jobid
72
--afisarea salariului maxim al angajatilor din tabelul emp utilizand variabile de legatura
variable g_max_sal number
declare
v_max_sal number;
begin
select max(sal) into v_max_sal
from emp;
:g_max_sal :=v_max_sal;
end;
/
print g_max_sal
--afisarea salariului total al angajatilor din departamentul 10 din tabelul emp folosind variabile
de legatura:
variable g_sal number
declare
v_sum_sal emp.sal%type;
v_deptno number not null :=10;
begin
select sum(sal)into v_sum_sal-- functie grup
from emp
where deptno=v_deptno;
:g_sal:=v_sum_sal;
end;
/
print g_sal
--Sa se creeze vizualizarea v_emp care sa contina codul si numele salariatilor din tabelul emp.
--sa se afiseze continutul acesteia.
--sa se insereze o noua inregistrare in aceasta vizualizare.
--sa se analizeze structura si continutul vizualizarii.
--sa se stearga vizualizarea v_emp
create view v_emp(empno,firstname)
as
select empno,firstname
from emp;
insert into v_emp values (7777, 'ionescu');
desc v_emp;
select * from v_emp;
drop v_emp;
73
--sa se creeze vizualizarea emp_dept care sa contina codul si numele departamentului, numarul
de angajati din departamentul respectiv si suma alocata pentru plata salariilor.
create view emp_dept (deptno,dname,nr_ang,val_sal)
as
select e.deptno,dname,count(*) nr_ang,sum(sal) val_sal
from emp e, dept d
where d.deptno = e.deptno
group by e.deptno,dname;
select * from emp_dept;
--
drop view emp_dept;
--Sa se creeze o secventa secv care incepe cu valoarea 10 si se termina cu valoarea 10000, pasul
de incrementare 10 si nu cicleaza. Acesta secventa secv se va folosi ulterior pentru generarea
automata de numere unice pentru campul empno din tabela emp. Se vor genera succesiv,
crescator, numerele cuprinse intre 10 si 10000.
create sequence secv --nume secventa
increment by 10 --pasul de incrementare
start with 10 --valoarea de pornire a secventei
maxvalue 10000 --valoarea maxima a secventei
nocycle; --secventa finita
--sa se modifice toate liniile din tabelul emp, regenerand codul angajatilor a.i. sa utilizeze
secventa secv. Sa se anuleze modificarile
update emp
set empno=secv.nextval;
rollback;
Index
create [unique] index index_name
on table_name
(column [,column . . .]);
74
--sa se creeze un index nou pe atributul empno din tabela emp.
create unique index emp_idx01
on prof.emp
(empno);
--
create unique index emp_idx02
on prof.emp
(empno,hiredate);
Sinonim
create synonym <name> for <user>.<table> ;
--
create synonym ang
for prof.emp;
select * from ang;
--sa se creeze un sinonim public pentru tabela emp din schema de obiecte
create public synonym prod for emp;
APLICATII PROPUSE
Știind că într-o instituție pot lucra mai mulți funcționari, iar un funcționar lucrează într-o singură
instituție, se cere să se scrie următoarele interogări:
75
3. să se specifice dacă un funcționar dat are prima mare, medie sau mică după cum este mai mare
decât 4500, cuprinsă între 1500 și 4500 sau mai mică decât 1500;
4. realizați o creștere a salariilor funcționarilor după funcție (considerăm trei funcții: SECRETAR,
CONTABIL și ADMINISTRATOR, și creșteri corespunzătoare de 10%, 15% și respectiv 20%),
folosind subprograme;
5. afișați funcționarii care nu sunt în instituția cu codul 20 (presupunând existența unei instituții cu
COD=20);
6. afișați pentru fiecare funcție salariul mediu;
7. după excluderea funcționarilor cu salariile mai mici decât 2000, să se afișeze funcțiile pentru care
media salariilor este mai mare decât 2600;
8. pentru fiecare funcție să se afișeze funcționarii cu salariile maxime;
9. afișați funcționarii care câștigă mai mult decât salariul maxim al funcționarilor care aparțin
instituției cu DENUMIRE=”Oracle”;
10. ștergeți instituția cu codul 20 (presupunând existența unei instituții cu COD=20);
11. să se gasească funcția cu cel mai scăzut salariu mediu;
12. afișați salariului total al angajaților din instituția cu codul 10, folosind variabile de legatură;
13. afișați funcționarii care lucrează pe aceeași funcție cu funcționarul care are ID=7369, și au salariul
mai mare ca cel al funcționarului cu ID=7876;
14. afișați funcționarii care nu au subalterni.
Bibliografie
• Bâscă, O., Baze de date, Editura All, 1997;
• Cârstoiu, D., Baze de date, Editura Matrix ROM, 2009;
• Connolly T., Begg C., Database Systems. A Practical Approach to Design, Implementation,
and Management, Ed. Addison Wesley, 2005
(http://www.palinfonet.com/download/software2/database%20systems.pdf);
• Fusaru D., Arhitectura bazelor de date-mediul SQL, Editura Fundației România de Mâine,
2002;
• Popa M., Baze de date (Fundamente, exemple, teste de verificare), Editura Fundației România
de Mâine, București 2006;
• Popescu I., Modelarea bazelor de date, Editura Tehnică, 2002;
• Popescu M, Baze de date, Editura Renaissance, Bucureşti, 2010;
• ***, Informatică pentru examenul de licență, Universitatea SPIRU HARET, 2017;
• ORACLE, https://www.oracle.com/index.html.
76