Sunteți pe pagina 1din 44

SEMINAR 1 - CONTINUT:

1. Baze de date: schema bazei de date, tabela, camp, cheie primara, cheie externa,
relatie, forme normale (FN).
2. Introducere in ORACLE: SQL Developer, autentificarea

I. BAZE DE DATE – NOTIUNI FUNDAMENTALE:

Tabela, relatie, coloana, inregistrare, cheie primara, cheie externa – vezi curs.
Tipuri de legaturi intre tabele:
 1-1 – legatura dintre cele doua tabele se face pe baza cheilor primare
 1-n – cheia primara din tabela “parinte” se adauga in tabela “copil” sub forma de
cheie externa
 n-n – nu se poate implementa practic si se recurge la adaugarea unei tabele
suplimentare care va contine cheile primare ale tabelelor initiale si campuri
referitoare la asocierea cu tabelele “parinte”. Cheia primara din tabela intermediara
va fi o cheie compusa.
Schemele conceptuala, logica si fizica ale bazei de date.

II. Limbajul SQL

Limbajul SQL – Structured Query Language este un limbaj standard de interogare a


bazelor de date implementat în majoritatea SGBD. In ORACLE este implementat limbajul SQL
cu anumite particularitati.

1. Tipuri de date:

TIP Caracteristici
CHAR(size) sir de caractere de lungime fixa
VARCHAR2(size) sir de caractere de lungime variabila
VARCHAR(size)
NUMBER(p,s) Numeric: p (precision) = 1..38, s (scale) =-84..127
DATE data calendaristica
ROWID adresa fiecarui rind din tabela
BLOB binary large object (max 4GB) se stocheaza date nestructurate
(text,imagine, video, date spatiale)
CLOB Character Large Object – date de tip text de dimensiune foarte mare
NCLOB National CLOB – include caractere nationale
BFILE contine un pointer catre un fisier binar stocat in afara bazei de date

2. Operatori SQL

Operator Caracteristici
<, >, =, >=, <=, NOT Operatori de comparatie
BETWEEN ... AND ... între două valori (inclusiv).
IN (listă) egal cu oricare valoare din listă
LIKE similar cu un şablon
% - oricâte caractere; _ - un caracter;
IS NULL are valoarea NULL
3. Comenzi SQL

Comenzile referitoare la bazele de date sunt comune tuturor versiunilor de SQL si sunt
impartite in urmatoarele categorii:

1) Comenzi LDD (Limbaj de Definire a Datelor - Data Definition Language)

Comanda Scop
CREATE Creaza un obiect nou (tabela, utilizator, rol, etc)
ALTER Modifica o parte dintre proprietatile unui obiect
DROP Elimina un obiect din baza de date

2) Comenzi LMD (Limbaj de Manipulare a Datelor - Data Manipulation Language)


Comanda Scop
SELECT Regaseste inregistrari in tabele sau vederi (view)
DELETE Sterge inregistrari din tabele
INSERT Adauga o noua inregistrare in tabela
UPDATE Modifica valorile unor inregistrari din tabele

3) Comenzi LPT (Limbaj pentru Procesarea Tranzactiilor – Transaction Processing


Language)

Comanda Scop
COMMIT Finalizeaza o tranzactie
ROLLBACK Anuleaza o tranzactie
SAVEPOINT Defineste un punct de salvare, in locul in care tranzactia salveaza toate
operatiile efectuate pana in momentul respectiv, inainte de a continua
urmatorul set de modificari efectuate in baza de date.

4) Comenzi LCD (Limbaj de Control al Datelor - Data Control Language)

Comanda Scop
GRANT Acorda utilizatorilor drepturile necesare pentru accesul si manipularea
obiectelor din baza de date
REVOKE Anuleaza anumite drepturi utilizatorilor
Comenzi LDD (Data Definition Language – Limbaj de Definire a Datelor)

Comanda Scop
CREATE Creaza un obiect nou: TABLE, INDEX, CLUSTER, TABLESPACE,
SEQUENCE, VIEW, MATERIALIZED VIEW, USER, ROLE,
PROCEDURE, FUNCTION, TRIGGER
ALTER Modifica o parte dintre proprietatile unui obiect
DROP Sterge un obiect din baza de date

CREAREA TABELELOR – COMANDA CREATE TABLE


Pentru a crea o tabela se specifica urmatoarele:
- denumirea tabelei
- definirea coloanelor si tipul acestora
- stabilirea restrictiilor de integritate

RESTRICTII DE INTEGRITATE
- Tipuri de restrictii:
o NOT NULL
o UNIQUE
o PRIMARY KEY
o FOREIGN KEY
o CHECK

- Precizarea restrictiilor se poate face in 2 moduri: in-line la definirea coloanei pe care se


impune restrictia si out-of-line separat, fie la sfarsitul sintaxei CREATE TABLE, fie prin
comanda ALTER TABLE

Exemplul 1. Sa se creeze tabela firme si tabela agenti in care sa fie precizate restrictiile de
integritate.
CREATE TABLE firme
(codfirma NUMBER(2) CONSTRAINT PKey_firme PRIMARY KEY,
denfirma VARCHAR2(20) NOT NULL,
loc VARCHAR2(20),
zona VARCHAR2(15) CONSTRAINT FZONA_CK check (zona IN
('Moldova','Ardeal','Banat','Muntenia','Dobrogea','Transilvania')));

CREATE TABLE agenti


(codagent VARCHAR2(3) CONSTRAINT pk_agent PRIMARY KEY,
numeagent VARCHAR2(25) NOT NULL,
dataang DATE DEFAULT SYSDATE,
datanast DATE,
functia VARCHAR2(20),
codfirma NUMBER(2),
CONSTRAINT FK_agenti FOREIGN KEY (codfirma) REFERENCES firme(codfirma));
Exemplul 2. Se considera activitatea de evidenta a comenzilor incheiate de o societate comerciala
cu diversi clienti prin intermediul angajatilor care detin anumite functii si isi desfasoara activitatea
in diverse departamente, aflate in mai multe tari/regiuni/locatii. Comenzile pot fi plasate si online
si contin produse aflate in depozitul societatii.

Figura 1. Schema BD pentru activitatea de evidenta a comenzilor si a resurselor umane

Deschideti de pe site schema BD


http://bd.ase.ro/uploads/bd_seminar_zi/diagrama_hr.jpg
si scriptul de creare a tabelelor
http://bd.ase.ro/uploads/bd_seminar_zi/ru_ldd.txt

CREAREA UNEI TABELE PE BAZA COLOANELOR DIN ALTA TABELA:

CREATE TABLE nume_tabela


AS
SELECT [*, nume coloane] FROM nume_tabela_sursa
[WHERE conditie];

Exemplul 3. Sa se creeze tabela fosti_agenti pe baza tabelei agenti si care va contine doar o parte
din coloanele tabelei initiale (codagent, numeagent, functia, codfirma)
CREATE TABLE fosti_agenti
AS
SELECT codagent, numeagent, functia, codfirma FROM agenti;

MODIFICAREA STRUCTURII TABELELOR - COMANDA ALTER TABLE


Comanda ALTER TABLE permite:
- Modificarea structurii unei tabele avand urmatoarele optiuni:
Adaugare coloana ADD nume_coloana tip_data
Modificare coloana MODIFY nume_coloana tip_nou_data
Stergere coloana DROP COLUMN nume_coloana
Inactivare coloana in vederea stergerii ulterioare SET UNUSED

- Modificarea restrictiilor de integritate avand urmatoarele optiuni:


Adaugare restrictie ADD CONSTRAINT nume_restrictie
tip_restrictie
Modificare restrictie MODIFY CONSTRAINT nume_restrictie
tip_nou_restrictie
Stergere restrictie DROP CONSTRAINT nume_restrictie
Dezactivare/activare restrictie DISABLE/ENABLE CONSTRAINT
nume_restrictie

- Redenumirea tabelei: RENAME


ALTER TABLE nume_tabela RENAME TO nume_nou_tabela;
sau
RENAME nume_tabela TO nume_nou_tabela;

Exemplul 4
4.1 Sa se redenumeasca tabela agenti cu personal
ALTER TABLE agenti RENAME TO personal;
sau
RENAME agenti TO personal;

4.2 Sa se adauge coloanele email si varsta in tabela personal


ALTER TABLE personal
ADD (email VARCHAR2(10),
varsta NUMBER(2));

4.3 Sa se modifice tipul de date al coloanei email


ALTER TABLE personal
MODIFY (email VARCHAR2(30));

4.4 Sa se stearga coloana email


ALTER TABLE personal
DROP COLUMN email;
4.5 Sa se inactiveze coloana functia
ALTER TABLE personal
SET UNUSED COLUMN functia;

4.6 Sa se stearga coloanele inactive


ALTER TABLE personal
DROP UNUSED COLUMNS;
4.7 Sa se adauge o restrictie pe coloana varsta
ALTER TABLE personal
ADD CONSTRAINT check_varsta CHECK (varsta>18 and varsta<60);

4.8 Sa se dezactiveze restrictia anterioara


ALTER TABLE personal
DISABLE CONSTRAINT check_varsta;

4.9 Sa se stearga restrictia anterioara


ALTER TABLE personal
DROP CONSTRAINT check_varsta;

STERGEREA TABELELOR – COMENZILE DROP TABLE SI TRUNCATE


TABLE
Comanda permite stergerea unei tabele [inclusiv restrictiile acesteia] cu posibilitate de recuperare:
DROP TABLE nume_tabela [CASCADE CONSTRAINTS];
FLASHBACK TABLE nume_tabela TO BEFORE DROP;

Sterge definitiv tabela fara posibilitate de recuperare


DROP TABLE nume_tabela PURGE;

Exemplul 5.
5.1 Sa se stearga tabela fosti_agenti
DROP TABLE fosti_agenti;
5.2 Sa se recupereze tabela fosti_agenti
FLASHBACK TABLE fosti_agenti TO BEFORE DROP;

Comanda TRUNCATE TABLE sterge inregistrarile unei tabele si elibereaza spatiul alocat
acestora

Exemplul 6. Sa se stearga inregistrarile tabelei personal


TRUNCATE TABLE personal;

VIZUALIZAREA OBIECTELOR CE APARTIN UNUI ANUMIT UTILIZATOR:


Din dictionarul bazei de date se pot vizualiza o serie de informatii referitoare la obiectele
utilizatorului curent
Exemplul 7. Sa se vizualizeze toate tabelele utilizatorului curent
SELECT * FROM USER_TABLES;

Exemplul 8. Sa se vizualizeze denumirea tabelelor, restrictiile si tipul acestora pentru


utilizatorul curent
SELECT TABLE_NAME, CONSTRAINT_TYPE, CONSTRAINT_NAME
FROM USER_CONSTRAINTS;

ACTUALIZAREA TABELELOR - COMENZI LMD


(Data Manipulation Language – Limbaj de Manipulare a Datelor)
Comanda Scop
INSERT Adauga o noua inregistrare in tabela
UPDATE Modifica valorile unor inregistrari din tabele
DELETE Sterge inregistrari din tabele
MERGE Actualizeaza o tabela in functie de anumite conditii
SELECT Regaseste inregistrari in tabele sau vederi (view).
Dupa actualizarea datelor se va utiliza comanda SELECT * FROM nume_tabela; pentru a
vizualiza rezultatele!
ADAUGAREA INREGISTRARILOR – COMANDA INSERT
Inregistrarile se pot adauga in tabele in mai multe moduri:
- precizand explicit in sintaxa comenzii valorile
- cu ajutorul variabilelor de substitutie
- pe baza valorilor din alte tabele
a) Precizarea explicita a valorilor introduse se realizeaza cu comanda:
INSERT INTO nume_tabela VALUES (lista de valori pentru fiecare coloana in ordinea in care
sunt declarate coloanele in tabela);
Atentie! Trebuie precizate valori pentru toate coloanele tabelei.

Vezi scriptul pentru adaugarea inregistrarilor in tabelele utilizate ca exemplu. Descarcati de


pe site scriptul de adaugare http://bd.ase.ro/uploads/bd_seminar_zi/ru_lmd.txt

O varianta a acestei comenzi este urmatoarea:


INSERT INTO nume_tabela (lista de coloane) VALUES (lista de valori pentru fiecare coloana);
Exemplu 1. Sa creeze tabela salariati pe baza tabelei angajati fara a prelua si inregistrarile (doar
structura) si sa se adauge un nou angajat
CREATE TABLE salariati AS SELECT * FROM angajati WHERE 2=3;
INSERT INTO salariati (id_angajat, nume, salariul) VALUES (207, 'Ionescu', 4000);
INSERT INTO salariati (id_angajat, nume, salariul) VALUES (207, 'Poppescu', 4200);
SELECT * FROM salariati;
b) Adaugarea inregistrarilor pe baza valorilor din alte tabele:
INSERT INTO nume_tabela SELECT */lista de coloane
FROM tabela_sursa
[WHERE conditie];

Exemplul 2. Sa se adauge in tabela salariati toti angajatii din tabela angajati care lucreaza in
departamentele 20, 30 si 50. Si sa se finalizeze tranzactia (salvarea modificarii).
INSERT INTO salariati SELECT * FROM angajati
WHERE id_departament IN (20, 30, 50);

SELECT * FROM salariati;

COMMIT;

c) Utilizarea variabilelor de substitutie pentru adaugarea inregistrarilor pe baza valorilor


introduse de utilizator de la tastatura:
INSERT INTO nume_tabela (lista coloane) VALUES (&valoare_coloana1,
&valoare_coloana2,...);

Exemplul 3. Sa se adauge in tabela salariati un angajat ale carui date sunt introduse de utilizator
de la tastatura
INSERT INTO salariati (id_angajat, nume, data_angajare, salariul)
VALUES ('&id_angajat','&nume', TO_DATE('&data_angajare', 'mon dd, yyyy'), '&salariul');

Atentie! Pentru data_angajare se va utiliza functia de conversie TO_DATE.


Ex: TO_DATE('jan 20, 2005','mon dd, yyyy')
MODIFICAREA DATELOR – COMANDA UPDATE
Sintaxa comenzii este:
UPDATE nume_tabela SET nume_coloana = valoare
[WHERE conditie];

Exemplul 4. Sa se creasca cu 100 salariul angajatilor din tabela salariati care au salariul mai mic
decat 3000:
UPDATE salariati
SET salariul=salariul+100
WHERE salariul<3000 AND comision IS NULL;
SELECT * FROM salariati;

Exemplul 5. Sa se actualizeze salariul angajatilor al caror manager are id = 122 cu salariul


angajatului cu id = 125.
UPDATE salariati
SET salariul=(SELECT salariul FROM salariati WHERE id_angajat=125)
WHERE id_manager=122;

Exemplul 6. Sa se actualizeze salariul si comisionul angajatilor din tabela salariati cu salariul si


comisionul anagajatului cu id_angajat = 167 din tabela angajati, doar pentru angajatii care au
salariul mai mic decat salariul angajatului cu id = 173 din tabela angajati si care lucreaza in
departamentul 50.
UPDATE salariati SET (salariul, comision)=(SELECT salariul, comision FROM angajati
WHERE id_angajat=167)
WHERE salariul < (SELECT salariul from angajati WHERE id_angajat = 173) AND
id_departament =50;
STERGEREA DATELOR – COMANDA DELETE
Sintaxa comenzii este:
DELETE FROM nume_tabela
WHERE conditie;

Exemplul 7. Sa se stearga angajatii din tabela salariati care au id_manager egal cu 122 sau 123.
DELETE FROM salariati
WHERE id_manager IN (122, 123);

Exemplul 8. Sa se sterga angajatii din tabela salariati angajati inainte de anul 1999.
DELETE FROM salariati
WHERE data_angajare<TO_DATE('01-01-1999','DD-MM-YYYY');

Exemplul 9. Sa se sterga toti angajatii din tabela salariati. Sa se anuleze tranzactia.


DELETE FROM salariati;

SELECT * FROM salariati;

ROLLBACK;

SELECT * FROM salariati;

ACTUALIZAREA DATELOR CU COMANDA MERGE

Sintaxa comenzii este:


MERGE INTO nume_tabela USING nume_tabela_sursa
ON (conditia_de_legatura)
WHEN MATCHED THEN
UPDATE SET nume_coloana=valoare
WHEN NOT MATCHED THEN
INSERT VALUES (lista_valori);

Exemplul 10. Sa se actualizeze tabela salariati astfel incat toti salariatii din tabela salariati sa aiba
salariile egale cu cei din tabela angajati, iar pentru cei care nu sunt in tabela salariati sa se adauge
valorile coloanelor (id_angajat, nume, salariul) din tabela sursa agajati. Sa se numere inregistrarile
din cele doua tabele si sa se explice diferenta. Sa se finalizeze tranzactia.

MERGE INTO salariati USING angajati


ON (salariati.id_angajat = angajati.id_angajat)
WHEN MATCHED THEN
UPDATE SET salariati.salariul=angajati.salariul
WHEN NOT MATCHED THEN
INSERT (id_angajat, nume, salariul) VALUES (angajati.id_angajat, angajati.nume,
angajati.salariul);
SELECT COUNT (*) FROM salariati;
SELECT COUNT (*) FROM angajati;
COMMIT;

INTEROGAREA TABELELOR

Instructiunea SELECT realizeza regasirea datelor din tabele pe baza cererilor de interogare
SELECT [DISTINCT] (*/coloana1 [alias], expresii [alias])
FROM tabela1, tabela2, ...
WHERE (conditii, precizarea legaturilor dintre tabele)
GROUP BY nume_tabela.nume_coloana
HAVING (conditii impuse valorilor de grup)
ORDER BY nume_tabela.nume_coloana ASC/DESC;

UNDE:
SELECT specifică atributele selectate;
DISTINCT suprimă valorile duplicate;
* selectează toate atributele;
coloana selectează o anumită coloana sau mai multe coloana dintr-una sau
mai multe tabele;
expresie permite construirea de expresii avand ca rezultat valori noi
alias denumiri pentru coloanele selectate;
FROM tabele specifică tabelele ce conţin coloanele selectate;
WHERE clauza permite specificarea conditiilor si a criteriilor de selectie a
datelor;
GROUP BY se precizeaza campul dupa care vor fi grupate datele in cazul
expresiilor si functiilor de grup (SUM(), AVG(), COUNT(), MIN(),
MAX());
HAVING in cazul functiilor de grup conditiile impuse acestora se precizeaza
in clauza HAVING;
ORDER BY precizeaza ordonarea in functie un anumite campuri ascendent
(ASC) – implicit sau descendent (DESC). Numai ORDER BY
permite utilizarea aliasului;
Comenzile SQL:
- Nu sunt case sensitive, de regula comezile se scriu cu litere mari pentru a se distinge
mai usor;
- Pot fi scrise pe mai multe linii;
- Cuvintele cheie nu pot fi prescurtate sau scrise pe mai multe linii;
In construirea comenzilor SQL se utilizeaza urmatorii operatori:
<, >, =, >=, <=, NOT operatori de comparatie
BETWEEN val_min AND între două valori (inclusiv).
val_max
SELECT id_angajat, nume, salariul, id_departament FROM salariati WHERE salariul
BETWEEN 2000 AND 6100 AND id_departament NOT IN (20, 30);
SELECT id_angajat, nume, salariul, id_departament FROM salariati WHERE salariul >=
2000 AND salariul <=6100 AND id_departament = 50;
IN (listă valori) egal cu oricare valoare din lista de valori
SELECT id_angajat, nume, id_manager FROM salariati WHERE id_manager IN (120,
122, 123);
LIKE similar cu un şablon
% oricâte caractere; _ un caracter;
SELECT id_angajat, nume, id_functie FROM salariati WHERE nume LIKE 'B% ';
SELECT id_angajat, nume, id_functie FROM salariati WHERE nume LIKE '__t%';
IS NULL are valoarea NULL
SELECT id_angajat, nume, comision FROM salariati WHERE comision IS NULL;
Coloanele se specifică în ordinea în care se doresc a fi afişate, nu obligatoriu în
ordinea în care apar în descrierea tabelelor.
Valoarea NULL, ca şi în alte limbaje, semnifică valoare ne-disponibilă, ne-alocată, şi nu este
acelaşi lucru cu „blank” sau „zero”.
Cu ajutorul comenzii select se pot extrage informaţii din baza de date. Comanda SELECT permite
imprementarea operatorilor algebrei relationale:
Selecţia: Permite obţinerea unei noi relaţii care conţine toate atributele relaţiei
iniţiale şi un număr redus de tupluri. Reducerea se face după o condiţie
numită condiţie de selecţie.
Proiecţia: Permite obţinerea unei noi relaţii care conţine un număr redus de atribute
faţă de relaţia iniţială şi toate valorile sau combinaţiile distincte de valori
ale acestor atribute.

Joncţiunea: Operator binar, caz particular fiind produsul cartezian. Relaţia rezultat va
conţine tuplurile corespunzătore atributelor de jonctiune care se află într-o
anumită relaţie. Cel mai utilizat caz de joncţiune este acela în care atributele
de jonctiune sunt cheie primară într-o relaţie si cheie externă in cealalta
relatie.

Exemple:

1. Sa se selecteze toti angajatii din tabela salariati.

SELECT * FROM salariati;

2. Sa se selecteze coloanele id_angajat, nume, prenume si id_functie din tabela salariati.

SELECT id_angajat, nume, prenume, id_functie FROM salariati;

3. Sa se selecteze numai angajatii care fac parte din categoria functionar (al caror id_functie
contine „CLERK”).

SELECT * FROM salariati


WHERE upper(id_functie) LIKE '%CLERK%';

4. Sa se selecteze comenzile incheiate de salariatul cu id_angajat = 161.

SELECT * FROM comenzi


WHERE id_angajat = 161
ORDER BY nr_comanda;

5. Sa se selecteze toate comezile care au fost lansate online dupa 1 ianuarie 2000.

SELECT * FROM comenzi


WHERE LOWER(modalitate) LIKE '%online%'
AND data > TO_DATE('01.01.2000','DD.MM.YYYY');

6. Sa se selecteze id_angajat, nume, prenume, id_manager, id_departament din tabela angajati


si denumire_departament din tabela departamente si sa se realizeze jonctiunea dintre cele
doua tabele.

SELECT a.id_angajat, a.nume, a.prenume, a.id_manager, a.id_departament,


d.denumire_departament
FROM angajati a, departamente d
WHERE a.id_departament=d.id_departament;

Operatorul ANY si operatorul ALL


ANY Comapara valoarea cu oricare valoare returnata de interogare
ALL compara valoarea cu fiecare valoare returnata de interogare
7. Să se afişeze id_angajat, prenume, id_functie si salariul pentru angajatii care nu lucreaza in
departamentul IT_PROG si al caror salariu este mai mic decat oricare dintre salariile angajatilor
care lucreaza in departamentul IT_PROG:
SELECT id_angajat, prenume, id_functie,
salariul
FROM angajati
WHERE salariul < ANY
(SELECT salariul FROM angajati
WHERE id_functie = 'IT_PROG')
AND id_functie <> 'IT_PROG'
ORDER BY salariul DESC;
8. Să se afişeze id_angajat, prenume, id_functie si salariul pentru angajatii care nu lucreaza in
departamentul IT_PROG si al caror salariu este mai mic decat fiecare dintre salariile angajatilor
care lucreaza in departamentul IT_PROG:
SELECT id_angajat, prenume, id_functie,
salariul
FROM angajati
WHERE salariul < ALL
(SELECT salariul FROM angajati
WHERE id_functie = 'IT_PROG')
AND id_functie <> 'IT_PROG'
ORDER BY salariul DESC;

Realizarea jonctiunilor între relaţii. Tipuri de jonctiuni

a. Jonctiune de egalitate
9. Sa se selecteze comenzile incheiate de angajati (in clauza WHERE se va preciza conditia
de legatura dintre tabele).

SELECT a.*, c.*


FROM angajati a, comenzi c
WHERE a.id_angajat= c.id_angajat;

10. Sa se selecteze comenzile incheiate de angajatul Greene numai in luna noiembrie.

SELECT angajati.*, comenzi.*


FROM angajati, comenzi
WHERE angajati.id_angajat=comenzi.id_angajat
AND lower(comenzi.data) like '%nov%'
AND upper(angajati.nume) = 'GREENE';

11. Sa se calculeze valoarea fiecarui produs (valoare = cantitate * pret) si sa se afiseze


denumirea produsului, pretul, cantitatea si valoarea.

SELECT produse.denumire_produs, rand_comenzi.cantitate, rand_comenzi.pret,


rand_comenzi.cantitate * rand_comenzi.pret AS Valoare
FROM produse, rand_comenzi
WHERE produse.id_produs= rand_comenzi.id_produs;

12. Sa se selecteze numai produsele cu valoarea cuprinsa intre 1000 si 2000.

SELECT produse.denumire_produs, rand_comenzi.cantitate, rand_comenzi.pret,


rand_comenzi.cantitate * rand_comenzi.pret AS Valoare
FROM produse, rand_comenzi
WHERE produse.id_produs= rand_comenzi.id_produs
AND rand_comenzi.cantitate * rand_comenzi.pret BETWEEN 1000 AND 2000;

b. Jonctiune externa

13. Să se afişeze id-ul produsului, denumirea produsului şi cantitatea chiar daca nu au fost
comandate
14. SELECT p.id_produs, p.denumire_produs, rc.cantitate, rc.pret
15. FROM produse p, rand_comenzi rc
16. WHERE p.id_produs = rc.id_produs (+);

c. Jonctiunea dintre o tabelă cu aceeaşi tabelă

17. Să se afişeze numele fiecarui angajat şi numele sefului direct superior:


18.
SELECT a.nume||' lucreaza pentru: '||m.nume
FROM angajati a, angajati m
WHERE a.id_manager=m.id_angajat;
Realizarea interogarilor subordonate (se utilizeaza 2 comenzi SELECT imbricate)

19. Sa se selecteze angajatii care sunt in acelasi departament cu angajatul Smith.

SELECT * FROM angajati


WHERE id_departament =
(SELECT id_departament FROM angajati WHERE upper(nume)= 'SMITH');
Eroare "single-row subquery returns more than one row"

SELECT nume, prenume, id_angajat, id_departament FROM angajati WHERE nume =


'Smith';

SELECT * FROM angajati


WHERE id_departament IN
(SELECT id_departament FROM angajati WHERE upper(nume)= 'SMITH');

20. Să se afişeze produsele care au preţul unitar cel mai mic:

SELECT p.denumire_produs, rc.pret


FROM produse p, rand_comenzi rc
WHERE p.id_produs = rc.id_produs
AND rc.pret=(SELECT MIN(rand_comenzi.pret) FROM rand_comenzi);

Clauza FOR UPDATE - blocheaza randurile selectate de o interogare in vederea actualizarii


ulterioare, ceilalti utilizatori nu pot modifica acele randuri pana la finalizarea tranzactiei;
FOR UPDATE nu se foloseste cu:
 DISTINCT
 GROUP BY
 Functii de grup

SELECT a.id_angajat, a.id_functie, c.nr_comanda


FROM angajati a, comenzi c
WHERE a.id_angajat = c.id_angajat
FOR UPDATE;

UTILIZAREA FUNCTIILOR PREDEFINITE IN INTEROGARI

 Funcţii de tip single-row (sau scalare). O funcţie single-row întoarce un singur rezultat
pentru fiecare rând al tabelei interogate sau view
 Funcţii de grup (sau agregate). O funcţie de grup întoarce un singur rezultat pentru un grup
de rânduri interogate. Funcţiile de grup pot apare în clauza HAVING.
FUNCTII SINGLE-ROW

Funcţii de tip caracter

Functia LOWER() , UPPER(), INITCAP()

21. Sa se afiseze cu litere mari denumirea departamentelor din locatia 1700:

SELECT id_departament, UPPER(denumire_departament)


FROM departamente
WHERE id_locatie=1700;

22. Sa se afiseze salariatii al caror nume incepe cu litera s

SELECT id_angajat, nume FROM angajati WHERE nume like 's%';


SELECT id_angajat, nume FROM angajati WHERE nume like upper('s%');

23. Sa se afiseze toti angajatii cu numele Smith utilizand functiile INITCAP, UPPER, LOWER

SELECT id_angajat, nume FROM angajati WHERE INITCAP(nume) = 'Smith';


SELECT id_angajat, nume FROM angajati WHERE UPPER(nume) = 'SMITH';
SELECT id_angajat, nume FROM angajati WHERE LOWER(nume) = 'smith';

Operatorul de concatenare (||)

24. Să se afişeze denumirea produsului şi stocul disponibil

SELECT 'Produsul: ' || INITCAP(denumire_produs) || ' are pretul_minim ' || pret_min


produs_pret_minim
FROM produse;

Funcţia CONCAT() , funcţia LENGTH() , funcţia SUBSTR()

25. Să se afişeze id_client, numele clientilor concatenată cu sexul acestora şi lungimea


prenumelui, nivel_venituri numai pentru clientii cu venituri in categoria F: 110000 -
129999
SELECT id_client, CONCAT(nume_client,sex), LENGTH(prenume_client), nivel_venituri
FROM clienti
WHERE SUBSTR(nivel_venituri,1,1)='F';

Funcţii de tip numeric

Funcţia ROUND(), TRUNC()


26.Să se afişeze numărul 45,923 rotunjit la două zecimale si rotunjit la numar
intreg.
Sa se aplice si functia TRUNC.

SELECT ROUND(45.923,2), ROUND(45.923,0) FROM DUAL;


SELECT TRUNC(45.923,2), TRUNC(45.923,0) FROM DUAL;

Funcţii de tip dată calendaristică

Funcţia SYSDATE

27. Să se afişeze perioada de timp corespunzătoare (în săptămâni) între data încheierii
comenzii şi data curentă:
28.
29. SELECT nr_comanda, (SYSDATE-data)/7 saptamani
FROM comenzi;

30. Afisati data curenta (se selecteaza data din tabela DUAL):

SELECT SYSDATE data_curenta FROM DUAL;

Funcţiile MONTH_BETWEEN() , ADD_MONTHS() , NEXT_DAY() , LAST_DAY()

31. Să se afişeze comenzile, data încheierii comenzilor, numărul de luni între data curentă şi
data încheierii, următoarea zi de vineri după data încheierii, ultima zi din luna din care face
parte data încheierii, precum şi data corespunzătoare după 2 luni de la data încheierii comenzii
32.
33. SELECT nr_comanda, data,
34. round(MONTHS_BETWEEN(sysdate, data)) luni,
35. NEXT_DAY(data, 'FRIDAY'),
LAST_DAY(data)
ADD_MONTHS(data,2),
FROM comenzi;

36. Să se afişeze comenzile incheiate in luna trecuta:

SELECT nr_comanda, data FROM comenzi


WHERE round(MONTHS_BETWEEN(sysdate, data))=1;

SELECT nr_comanda, data FROM comenzi


WHERE round(MONTHS_BETWEEN(sysdate, data))=171;

Funcţia ROUND(), TRUNC()


37. Să se afişeze comenzile incheiate in 2000. Se va rotunji data încheierii la prima zi din luna
corespunzătoare dacă data încheierii este în prima jumatate a lunii sau la prima zi din luna
următoare:
38.
39. SELECT nr_comanda, data, ROUND(data, 'MONTH') FROM comenzi
WHERE data LIKE '%-00%';

Funcţii de conversie

Funcţia TO_CHAR

40. Să se afişeze comenzile si data încheierii in formatul initial si in format “MM/YY”


41.
42. SELECT nr_comanda, data, TO_CHAR(data, 'MM/YY') data_incheierii_comenzii FROM
comenzi;

Funcţia TO_DATE

43. Să se afişeze comenzile incheiate intre 15 ianuarie si 15 decembrie 1999.


44.
SELECT nr_comanda, data
FROM comenzi
WHERE data BETWEEN TO_DATE( 'January 15, 1999', 'Month dd,YYYY') AND
TO_DATE( 'December 15, 1999', 'Month dd,YYYY');

Funcţia TO_NUMBER - Converteste sirul de caractere intr-un numar cu un anumit format


TO_NUMBER(char[, 'format_model'])
Funcţia EXTRACT()

45. Sa se afiseze comenzile incheiate in anii 1997 si 1998.

SELECT nr_comanda, data


FROM comenzi
WHERE EXTRACT(YEAR FROM data) IN (1997, 1998);

46. Sa se afiseze comenzile incheiate in lunile iulie si august.

SELECT nr_comanda, data


FROM comenzi
WHERE EXTRACT(MONTH FROM data) IN (7,8);

Functiile NVL, NVL2, NULLIF, COALESCE


NVL
NVL(comision,0)
NVL(data_angajarii,'01-JAN-97')
NVL(id_functia,'Nu_exista_functia')

47. Sa se calculeze veniturile anuale ale angajatilor


SELECT nume, salariul*12 + salariul*12*NVL(comision,0) venit_anual
FROM angajati;

NVL2
48. Sa se afiseze angajatii care au comision (1) si pe cei care nu au comision (0).
SELECT nume, NVL2(comision, 1, 0)
FROM angajati;

NULLIF
49. Sa se afiseze lungimea numelui, lungimea prenumelui, daca acestea sunt egale sa se
returneze nul ca rezultat, iar daca nu sunt egale se va returna lungimea numelui.
SELECT nume, length(nume), prenume, length(prenume), NULLIF(length(nume),
length(prenume)) rezultat
FROM angajati;

COALESCE
50. Sa se afiseze id-ul managerului fircarui angajat, daca acesta este nul, se va afisa comisionul,
iar daca si acesta este nul se va afisa -1.
SELECT nume, prenume, coalesce(id_manager,commission,-1)
FROM angajati;

FUNCŢII DE GRUP

AVG([DISTINCT|ALL] n) – calculeaza media aritmetica a valorilor


COUNT(* | [DISTINCT|ALL] expr) – intoarce numarul total al valorilor
MAX([DISTINCT|ALL] expr) – intoarce valoarea maxima
MIN([DISTINCT|ALL] expr) – intoarce valoarea minima
SUM([DISTINCT|ALL] n) – calculeaza suma valorilor

Se utilizeaza urmatoarele clauze:


GROUP BY – grupeaza datele in functie de un anumit camp;
ORDER BY – ordoneaza datele in functie de un anumit camp;
HAVING – permite stabilirea unor criterii de selectie asupra functiilor de grup;

Exemple:
1. Să se afişeze valoarea maximă, valoarea medie, valoarea minimă şi valoarea totală a
produselor comandate:

SELECT AVG(rc.cantitate * rc.pret), MAX(rc.cantitate * rc.pret), MIN(rc.cantitate *


rc.pret), sum(rc.cantitate * rc.pret)
FROM rand_comenzi rc;

2. Să se afişeze data primei comenzi încheiate şi data celei mai vechi comenzi încheiate:

SELECT MIN(data), MAX(data)


FROM comenzi;

3. Să se afişeze numărul de produse al căror pret_min>350:

SELECT COUNT(*) nr_produse


FROM produse
WHERE pret_min>350;

4. Sa se afiseze numarul de salarii (distincte) din tabela angajati.

SELECT COUNT (salariul) FROM angajati;  107


SELECT COUNT (DISTINCT salariul) FROM angajati  58

5. Să se afişeze numărul total de comenzi incheiate:

SELECT COUNT(nr_comanda) nr_comenzi FROM comenzi;

6. Să se afişeze pe cate comenzi apare produsul cu codul 3124:

SELECT COUNT(nr_comanda) produse_comandate_id_produs


FROM rand_comenzi WHERE id_produs = 3124;
7. Să se afişeze cantitatea medie vândută din fiecare produs. Sa se ordoneze după
cantitate (se utilizeaza functia AVG() si clauza GROUP BY pentru gruparea datelor
in functie de id_ul produsului, iar ordonarea se realizeaza cu ajutorul functiei
ORDER BY).

SELECT id_produs, ROUND(AVG(cantitate),2) medie_produse


FROM rand_comenzi
GROUP BY id_produs
ORDER BY medie_produse;

8. Să se afişeze produsele şi cantitatea medie vândută numei pentru acele produse a


căror cantitate medie este mai mare de 25 (conditia se specifica in clauza HAVING si
nu in clauza WHERE deoarece este utilizata functia de grup AVG si conditia este
AVG(cantitate)>25).

SELECT id_produs, ROUND(AVG(cantitate),1) medie_produse

FROM rand_comenzi

GROUP BY id_produs

HAVING ROUND(AVG(cantitate),1)>25;

9. Sa se calculeze valoarea totala a fiecarei comenzi si sa se sorteze descrescator in functie de


valoare:

SELECT comenzi.nr_comanda, SUM(rand_comenzi.cantitate * rand_comenzi.pret)


total_comanda
FROM comenzi, rand_comenzi
WHERE rand_comenzi.nr_comanda=comenzi.nr_comanda
GROUP BY comenzi.nr_comanda
ORDER BY total_comanda DESC;

10. Sa se afiseze numai comenzile care au valoarea cuprinsa intre 1000 si 3000 (conditia va fi
mentionata in clauza HAVING deoarece se utilizeaza functia de grup SUM):

SELECT comenzi.nr_comanda, SUM(rand_comenzi.cantitate * rand_comenzi.pret)


total_comanda
FROM comenzi, rand_comenzi
WHERE rand_comenzi.nr_comanda=comenzi.nr_comanda
GROUP BY comenzi.nr_comanda
HAVING SUM(rand_comenzi.cantitate * rand_comenzi.pret) BETWEEN 1000 AND 3000
ORDER BY total_comanda DESC;

PARCURGEREA STRUCTURILOR IERARHICE

1. Moduri de parcurgere a structurilor arborescente:

 TOP-DOWN – se construieste setul de inregistrari copil incepand cu inregistrarea


radacina
 BOTTOM-UP – se construieste setul de inregistrari parinte pana la inregistrarea
radacina pentru un anumit nivel din ierarhie
 DIRECT PE UN ANUMIT NIVEL – se construieste setul de inregistrari incepand cu
un anumit nivel din ierarhie

2. Comenzi utilizate
Daca o tabela contine date arborescente, se pot selecta tuplurile intr-o ordine ierarhica prin
utilizarea unor clauze suplimentare in comanda SELECT:
SELECT [DISTINCT] [LEVEL] lista_coloane
FROM nume_tabela
WHERE (conditii, precizarea legaturilor dintre tabele)
CONNECT BY [PRIOR] coloana_inregistrarii_copil=[PRIOR] coloana_inregistrarii_parinte
START WITH coloana_radacina;

unde:
START WITH - specifica inregistrarile radacina pentru ierarhiile construite. Daca se omite Oracle
foloseste toate inregistrarile din tabela ca inregistrarile radacina.
CONNECT BY - specifica relatia intre coloana inregistrarii parinte si coloana inregistrarii copil
ale ierarhiei.
PRIOR – se refera la inregistrarea parcursa anterior. Locul operatorului in conditia de legatura
parinte-copil determina modul de parcurgere al arborelui (top-down sau bottom-up).
LEVEL – se utilizeaza pentru a afisa nivelul inregistrarii parcurse.

Observatii:
1. Nu se recomanda utilizarea clauzei GROUP BY deoarece se pot produce schimbari in setul
returnat de cererea ierarhica.
2. O cerere ierarhica nu se foloseste intr-o jonctiune si nu poate selecta date dintr-o tabela virtuala.

3. Procesarea interogarilor:

Pas 1: Oracle selecteaza inregistrarile radacina ale ierarhiei ce satisfac conditia din clauza START
WITH.
Pas 2: Oracle selecteaza inregistrarile copil pentru fiecare inregistrare radacina. Fiecare
inregistrare copil trebuie sa satisfaca conditia din clauza CONNECT BY.
Pas 3: Oracle selecteaza generatii succesive de inregistrari copil evaluand clauza CONNECT BY.
Pas 4: Daca exista o conditia in clauza WHERE se elimina toate acele inregistrari care nu satisfac
conditia.
Pas 5: Se construieste setul de inregistrari care satisfac conditia de parcurgere a ierarhiei.

Figura 1: Interogari ierarhice


Exemple:
Structura partiala a tabelei utilizate ca exemplu (tabela angajati din schema HR)
ID_ANGAJA PRENUM NUM SALARIU COMISIO ID_MANAGE ID_DEPARTAMEN
T E E L N R T

Observatie: Inregistrarea radacina contine angajatul cu numele Steven King cu ID_ANGAJAT =


100 si ID_MANAGER = NULL.

I. Parcurgerea arborelui TOP-BOTTOM:


1. Sa se afiseze angajatii si nivelul ierarhic al acestora pornind de la angajatul cu id-ul 100 (sa se
ordoneze in functie de nivelul ierahic).
SELECT id_angajat, nume, id_manager, LEVEL FROM angajati
CONNECT BY PRIOR id_angajat= id_manager
START WITH id_angajat = 100;
SELECT id_angajat, nume, id_manager, LEVEL FROM angajati
CONNECT BY PRIOR id_angajat= id_manager
START WITH id_angajat = 100
ORDER BY LEVEL;

2. Afisati angajatii companiei subordonati inregistrarii radacina sub forma de organigrama.


SELECT LEVEL, LPAD(' ', LEVEL)|| nume FROM angajati
CONNECT BY PRIOR id_angajat = id_manager
START WITH id_angajat= 100;

SELECT LEVEL, LPAD(' ', LEVEL)|| nume FROM angajati


CONNECT BY PRIOR id_angajat = id_manager
START WITH id_angajat= 100
ORDER BY LEVEL;
3. Afisati angajatii companiei subordonati inregistrarii radacina specificand numarul de superiori
si toti superiorii sai, id-urile (se utilizeaza clauzele: SYS_CONNECT_BY_PATH, LEVEL-1):

SELECT id_angajat, nume,


LEVEL-1 Numar_Superiori, SYS_CONNECT_BY_PATH(id_angajat, '/') ID_Superiori
FROM angajati
START WITH id_angajat= 100
CONNECT BY PRIOR id_angajat = id_manager;

Interogari ierarhice conditionate (clauza WHERE):

4. Sa se selecteze angajati si gradul de subordonare numai pentru cei din departamentele 20 si


50:

SELECT id_angajat, nume, id_manager, level FROM angajati


WHERE id_departament IN (20, 50)
CONNECT BY PRIOR id_angajat = id_manager
START WITH id_angajat = 100;

II. Parcurgerea arborelui BOTTOM UP

5. Sa se afiseze superiorii angajatilor aflati pe ultimul nivel de subordonare:


SELECT nume, LEVEL-1 Numar_Superiori, SYS_CONNECT_BY_PATH(nume, '/')
Nume_Superiori
FROM angajati
START WITH id_angajat = 100
CONNECT BY PRIOR id_angajat = id_manager
ORDER BY LEVEL desc;

6. Sa se afiseze toti superiorii lui ‘Faviet’:


SELECT id_angajat, nume, id_manager, LEVEL FROM angajati
CONNECT BY id_angajat = PRIOR id_manager
START WITH nume= 'Faviet';

III. Parcurgerea arborelui incepind cu un anumit nivel

7. Sa se afiseze toti subordonatii lui 'De Haan':


SELECT id_angajat, nume, id_manager, LEVEL FROM angajati
CONNECT BY PRIOR id_angajat = id_manager
START WITH nume= 'De Haan'
ORDER BY LEVEL;

8. Sa se afiseze toti superiorii lui De Haan:


SELECT id_angajat, nume, id_manager, LEVEL FROM angajati
CONNECT BY id_angajat = PRIOR id_manager
START WITH nume= 'De Haan'
ORDER BY LEVEL;

9. Sa se afiseze toti subordonatii lui 'De Haan' si care sunt in acelasi departament zona cu 'Chen':
SELECT id_angajat, nume, id_manager, id_departament, LEVEL FROM angajati
WHERE id_departament = (SELECT id_departament FROM angajati WHERE nume='Chen')
CONNECT BY PRIOR id_angajat = id_manager
START WITH nume = 'Kochhar'
ORDER BY LEVEL;
10. Sa se selecteze toti angajatii din departamentul 100 si subordonatii acestora:
SELECT id_angajat, nume, id_manager, id_departament, LEVEL FROM angajati
CONNECT BY PRIOR id_angajat= id_manager
START WITH id_departament=100
ORDER BY LEVEL;

11. Sa se afiseze toti subordonatii lui 'Kochhar' fara cei din departamentul 100.
SELECT id_angajat, nume, id_manager, id_departament, LEVEL FROM angajati
WHERE id_departament != 100
CONNECT BY PRIOR id_angajat = id_manager
START WITH nume= 'Kochhar'
ORDER BY LEVEL;

12. Sa se afiseze toti subordonatii lui 'Kochhar' si mai putin cei din departamentele 100 si 110.
SELECT id_angajat, nume, id_manager, id_departament, LEVEL FROM angajati
WHERE id_departament NOT IN (100,110)
CONNECT BY PRIOR id_angajat = id_manager
START WITH nume= 'Kochhar'
ORDER BY LEVEL;

13. Sa se afiseze toti subordonatii lui 'Kochhar' si cei ai lui ‘De Haan’:
SELECT id_angajat, nume, id_manager, LEVEL FROM angajati
CONNECT BY PRIOR id_angajat = id_manager
START WITH nume = 'Kochhar' OR nume= 'De Haan'
ORDER BY LEVEL;

14. Sa se afiseze toti subordonatii de pe nivelul 3:


SELECT id_angajat, nume, id_manager, LEVEL FROM angajati
WHERE LEVEL=3
CONNECT BY PRIOR id_angajat = id_manager
ORDER BY LEVEL;
15. Sa se afiseze toti subordonatii incepand cu nivelul 3:
SELECT id_angajat, nume, id_manager, LEVEL FROM angajati
WHERE LEVEL>=3
CONNECT BY PRIOR id_angajat = id_manager
ORDER BY LEVEL;

16. Sa se afiseze numarul total de angajati subordonati lui 'Steven King' grupati pe departamente:
SELECT id_departament, count(*) Total_Angajati from angajati
CONNECT BY PRIOR id_angajat = id_manager
START WITH id_angajat = 100
GROUP BY id_departament;

17. Sa se selecteze toti subordonatii angajatilor cu functia CLERK.


SELECT id_angajat, nume, id_manager, id_functie FROM angajati
CONNECT BY PRIOR id_angajat = id_manager
START WITH id_functie LIKE '%CLERK%'
ORDER BY LEVEL;

Jonctiuni externe
Functia DECODE si expresia CASE

1) Jonctiuni externe
Permit regasirea inregistrarilor comune si in plus fata de jonctiunea de egalitate si a celor care se
regasesc doar intr-o singura tabela.
Jonctiunea se poate realiza precizand in dreptul legaturii dintre tabele a semnului (+), de exemplu
conditia: tabela_A.cheie_primara=tabela_B.cheie_externa(+) va returna inregistrarile comune si a
celor care apartin doar tabelei A.

Exemple:

1. Sa se afiseze produsele comandate impreuna cu cele care nu se regasesc pe nici o


comanda.

SELECT p.id_produs, p.denumire_produs, rc.cantitate, rc.pret


FROM produse p, rand_comenzi rc
WHERE p.id_produs = rc.id_produs (+);
...

2. Sa se afiseze toti angajatii care au incheiat comenzi, precum si cei care nu au incheiat
comenzi.

SELECT a.id_angajat, a.nume, c.nr_comanda, c. data


FROM angajati a, comenzi c
WHERE a.id_angajat= c.id_angajat (+);
...

2) Realizarea interogarilor pe baza unor conditii

Functia DECODE – este utilizata pentru calcularea si returnarea unor expresii in functie de
anumite conditii de egalitate

Sintaxa este:

DECODE (VARIABILA, conditie1, expresie1, conditie2, expresie2, ….., conditie_n,


expresie_n, valoare n+1 implicita)

Expresia CASE – este utilizata pentru calcularea si returnarea unor expresii in functie de anumite
conditii diverse in care se pot utiliza operatori de comparatie, nu numai operatorul de
egalitate.

Sintaxa este:

CASE [VARIABILA]
WHEN conditie1 THEN expresie1
WHEN conditie2 THEN expresie2
…………………………………….
WHEN conditie_n THEN expresie_n
ELSE valoare n+1 implicita
END

Sau daca se utilizeaza comparatii pe variabile sau coloane diferite se poate apela la varianta
urmatoare:

CASE
WHEN VARIABILA conditie1 THEN expresie1
WHEN VARIABILA conditie2 THEN expresie2
…………………………………….
WHEN VARIABILA conditie_n THEN expresie_n
ELSE valoare n+1 implicita
END

Exemple:

1. Sa se identifice ierarhia angajatilor responsabili cu vanzarile.

SELECT id_angajat, nume, id_functie, LEVEL FROM angajati


CONNECT BY id_angajat = PRIOR id_manager
START WITH id_functie = 'SA_REP';

2. Sa se calculeze comisionul agentilor in functie de pozitia (functia) ocupata:


 0.1% din valoarea comenzilor daca functia este SA_REP
 0.2% din valoarea comenzilor daca functia este SA_MAN
 0.3% din valoarea comenzilor daca functia este AD_PRES
Pentru celelalte functii comisionul va fi 0.
SELECT nume, id_functie,
CASE WHEN UPPER(id_functie) = 'AD_PRES' THEN 0.3
WHEN UPPER(id_functie) = 'SA_MAN' THEN 0.2
WHEN UPPER(id_functie) = 'SA_REP' THEN 0.1
ELSE 0 END comision
FROM angajati;
...

Daca se aplica acest comision la valoarea comenzilor (SUM(cantitate*pret)) interogarea devine:

SELECT a.nume, a.id_functie,


(CASE WHEN UPPER(a.id_functie) = 'AD_PRES' THEN 0.3
WHEN UPPER(a.id_functie)= 'SA_MAN' THEN 0.2
WHEN UPPER(a.id_functie)= 'SA_REP' THEN 0.1
ELSE 0 END)*SUM(r.cantitate*r.pret) valoare_comision
FROM angajati a, comenzi c, rand_comenzi r
WHERE a.id_angajat=c.id_angajat
AND c.nr_comanda=r.nr_comanda
GROUP BY a.nume, a.id_functie;
Cu functia DECODE cerinta se poate rezolva astfel:
SELECT nume, id_functie,
DECODE(UPPER(id_functie) , 'AD_PRES' , 0.3,'SA_MAN', 0.2, 'SA_REP' , 0.1, 0) comision
FROM angajati;

2) Sa se calculeze diferit discountul (DC) pentru clienti astfel:


 daca clientul a incheiat 1 comanda atunci DC= 10%;
 daca a incheiat 2 comenzi atunci DC =15%;
 daca a incheiat mai mult de 3 comenzi atunci DC =20%.

SELECT cl.nume_client, count(co.nr_comanda) numar_comenzi,


CASE WHEN COUNT(co.nr_comanda) = 1 THEN 0.1
WHEN COUNT(co.nr_comanda) = 2 THEN 0.15
WHEN COUNT(co.nr_comanda)>=3 THEN 0.2
ELSE 0 END discount
FROM clienti cl, comenzi co
WHERE cl.id_client=co.id_client
GROUP BY cl.nume_client;

Tema individuala: Sa se calculeze discountul pentru produse astfel:


 daca regiunea este Europe atunci CT= 10% din valoarea totala a comenzilor
 daca zona firmei este America atunci CT=15% din valoarea totala a comenzilor
 daca zona firmei este Asia atunci CT=12% din valoarea totala a comenzilor
 daca zona firmei este Orientul mijlociu si Africa atunci CT=18% din valoarea totala a
comenzilor

SELECT denumire_produs, categorie,


CASE WHEN categorie like 'hardware%' THEN 0.1
WHEN categorie LIKE 'software%' THEN 0.11
ELSE 0.01 END discount
FROM produse;

Operatorii algebrei relationale


UNION, INTERSECT, MINUS

Sunt operatori care actioneaza asupra inregistrarilor selectate de 2 sau mai multe interogari. Sunt
similari operatiilor cu multimi.

Atentie: structura (coloanele) celor 2 interogari trebuie sa fie identica!

3.1) Operatorul MINUS – este utilizat pe 2 interogari pentru a extrage din inregistrarile
selectate de prima interogare pe cele selectate de a doua interogare (A-B).
Exemple:

1) Sa se afiseze angajatii care au salariul intre 4999 si 6500 fara cei care au salariul 5000 si 6000.

SELECT * FROM angajati WHERE salariul BETWEEN 4999 AND 6500


MINUS
SELECT * FROM angajati WHERE salariul IN (5000, 6000);

2) Sa se calculeze diferit discountul (DC) pentru clienti astfel:


 daca clientul a incheiat 1 comanda atunci DC= 10% ;
 daca a incheiat 2 comenzi atunci DC =15%;
 daca a incheiat mai mult de 3 comenzi atunci DC =20%.
Din acestea sa se elimine inregistrarile incheiate de clientii care incep cu litera M. Ordonati
descrescator in functie de numele clientilor.

Observatie: clauza Order by se poate mentiona o singura data la sfarsitul intregii cereri.

SELECT cl.nume_client, COUNT(co.nr_comanda) numar_comenzi,


(CASE WHEN COUNT(co.nr_comanda)=1 THEN 0.1
WHEN COUNT(co.nr_comanda)=2 THEN 0.15
WHEN COUNT(co.nr_comanda)>=3 THEN 0.2
ELSE 0 END) discount
FROM clienti cl, comenzi co
WHERE cl.id_client=co.id_client
GROUP BY cl.nume_client
MINUS
SELECT cl.nume_client, COUNT(co.nr_comanda) numar_comenzi,
(CASE WHEN COUNT(co.nr_comanda)=1 THEN 0.1
WHEN COUNT(co.nr_comanda)=2 THEN 0.15
WHEN COUNT(co.nr_comanda)>=3 THEN 0.2
ELSE 0 END) discount
FROM clienti cl, comenzi co
WHERE cl.id_client=co.id_client
AND cl.nume_client like 'M%'
GROUP BY cl.nume_client
ORDER BY nume_client;
3.2.) Operatorul UNION – este utilizat pe 2 interogari pentru a reuni inregistrarile selectate de
prima interogare cu cele selectate de a doua interogare (A + B).

3) Sa se calculeze distinct comisionul pentru angajati folosind operatorul UNION:


 Daca au 1 comanda comisionul va fi de 10% din valoare totala a comenzilor;
 Daca au 2 comenzi comisionul va fi de 20% din valoare totala a comenzilor;
 Daca au 3 comenzi comisionul va fi de 30% din valoare totala a comenzilor.

SELECT a.nume, COUNT(c.nr_comanda) numar_comenzi,


0.1* SUM(r.cantitate*r.pret) valoare_comision
FROM angajati a, comenzi c, rand_comenzi r
WHERE a.id_angajat=c. id_angajat
AND c.nr_comanda=r.nr_comanda
GROUP BY a.nume
HAVING COUNT(c.nr_comanda)=1
UNION
SELECT a.nume, COUNT(c.nr_comanda) numar_comenzi,
0.2* SUM(r.cantitate*r.pret) valoare_comision
FROM angajati a, comenzi c, rand_comenzi r
WHERE a.id_angajat=c.id_angajat
AND c.nr_comanda=r.nr_comanda
GROUP BY a.nume
HAVING COUNT(c.nr_comanda)=2
UNION
SELECT a.nume, COUNT(c.nr_comanda) numar_comenzi,
0.3* SUM(r.cantitate*r.pret) valoare_comision
FROM angajati a, comenzi c, rand_comenzi r
WHERE a.id_angajat=c.id_angajat
AND c.nr_comanda=r.nr_comanda
GROUP BY a.nume
HAVING COUNT(c.nr_comanda)>=3;

3.3.) Operatorul INTERSECT – este utilizat pe 2 interogari pentru a returna doar inregistrarile
comune selectate de prima interogare si cele selectate de a doua interogare.

4) Sa se selecteze denumirea produselor, valoare totala comandata (SUM(cantitate*pret)) si


numarul de comenzi (count(nr_comanda)) pentru produsele comandate de cel putin 3 ori si care
au valoarea totala diferita de 1440, 3916.

SELECT p.denumire_produs, SUM(r.cantitate*r.pret) valoare, COUNT(r.nr_comanda)


numar_comenzi
FROM produse p, rand_comenzi r
WHERE r.id_produs=p.id_produs
GROUP BY p.denumire_produs
HAVING COUNT(r.nr_comanda)<=3
INTERSECT
SELECT p.denumire_produs, SUM(r.cantitate*r.pret) valoare, COUNT(r.nr_comanda)
nrcomenzi
FROM produse p, rand_comenzi r
WHERE r.id_produs=p.id_produs
GROUP BY p.denumire_produs
HAVING SUM(r.cantitate*r.pret) NOT IN (1440, 3916);

GESTIUNEA ALTOR OBIECTE ALE BAZEI DE DATE


TABELE VIRTUALE
Tabele virtuale
- Stocheaza interogări si permite reutilizarea acestora
- Protejeaza informaţiile de natura confidentiala
- Protejeaza BD la actualizare
- Tabele virtuale materializate stocheaza si inregistrarile

CREATE [OR REPLACE] VIEW nume_view AS SELECT...

Exemple:
1. Sa realizeze o tabela virtuala cu toti angajatii din departamentul 50. Actualizăm salariul.

CREATE OR REPLACE VIEW v_angajati_50


AS SELECT * FROM angajati
WHERE id_departament=50;

SELECT * FROM v_angajati_50;

UPDATE v_angajati_50
SET salariul = salariul + 100;

2. Stocarea unei interogări care să permită adăugarea unor condiţii ulterioare


SELECT * FROM v_angajati_50 WHERE EXTRACT(MONTH FROM data_angajare) = 7;

3. Actualizarea tabelelor virtuale


CREATE OR REPLACE VIEW v_rand_comenzi
AS SELECT nr_comanda, pret, pret*cantitate valoare FROM rand_comenzi;

UPDATE v_rand_comenzi
SET valoare = valoare+100;

4. Opţiunea WITH READ ONLY


CREATE OR REPLACE VIEW v_rand_comenzi
AS SELECT nr_comanda, pret, pret*cantitate valoare FROM rand_comenzi
WITH READ ONLY;

5. Sa se stearga tabela virtuală v_rand_comenzi


DROP VIEW v_rand_comenzi;

6. Vizualizarea informatiilor despre tabelele virtuale:


SELECT VIEW_NAME, TEXT FROM USER_VIEWS;

INDECSI

- Permit accesul rapid la date prin sortarea logica a înregistrărilor.


- Se crează automat la introducerea unei restricţii de cheie primară sau de unicitate sau
manual de către utilizator.

Exemple:
1. Sa se creeze un index pe tabela angajati pe coloana prenume:

SELECT * FROM angajati WHERE prenume = 'Kevin';


Cost 3
CREATE INDEX idx _nume ON angajati(prenume);
SELECT * FROM angajati WHERE prenume = 'Kevin';
Cost 2

SELECT * FROM angajati WHERE UPPER(prenume) = 'KEVIN';


CREATE INDEX idx_upper_prenume ON angajati(UPPER(prenume));

2. Vizualizarea indecşilor unui anumit utilizator:

SELECT * FROM USER_INDEXES;

3. Sa se stearga indexul creat anterior:

DROP INDEX idx_prenume;

SECVENTE

- Sunt utilizate pentru asigurarea unicitatii cheilor primare sau a valorilor pentru care s-a
impus o restrictie de tip UNIQUE.
- Pot fi utilizate pentru mai multe tabele.
- Pentru fiecare secventa se va preciza valoarea de inceput, pasul de incrementare si valoarea
maxima generata.

Exemple:
1. Sa se creeze o secventa pentru asigurarea unicitatii cheii primare din tabela Comenzi.

CREATE SEQUENCE seq_nrcomanda


START WITH 500 INCREMENT BY 10
MAXVALUE 1000 NOCYCLE;

INSERT INTO comenzi VALUES (seq_nrcomanda.NEXTVAL, TO_DATE('oct 12,05', 'mon


dd,yy'), 'direct', '104', '1', NULL);

2. Sa se afiseze valoarea curenta a secventei:

SELECT seq_nrcomanda.CURRVAL FROM DUAL;


3. Să se modifice pasul de incrementare şi valoarea maximă pentru secvenţa anterioară:

ALTER SEQUENCE seq_nrcomanda INCREMENT BY 100;


ALTER SEQUENCE seq_nrcomanda MAXVALUE 2000;

INSERT INTO comenzi VALUES (seq_nrcomanda.NEXTVAL, TO_DATE('oct 12,05', 'mon


dd,yy'), 'direct', '104', '1', NULL);

4. Să se vizualizeze informaţiile depre secvenţele utilizatorilor:

SELECT * FROM USER_SEQUENCES;

5. Să se steargă secvenţa seq_nrcomanda:

DROP SEQUENCE seq_nrcomanda;

SINONIME

- Sunt nume alternative utilizate pentru referirea obiectelor unei baze de date.
- Pot fi sinonime publice (accesibile tuturor utilizatorilor) sau private.
- Sinonimele publice pot fi create numai de administratorul bazei de date.

Exemple:

1. Sa se creeze un sinonim pentru tabela rând_comenzi:

CREATE SYNONYM rc FOR RAND_COMENZI;

2. Vizualizarea sinonimelor se realizeaza astfel:

SELECT * FROM USER_SYNONYMS;

3. Sa se stearga sinonimul creat anterior:

DROP SYNONYM rc;

PARTITII

CREATE TABLE tabela_p(data DATE, cont VARCHAR2(50), divizia VARCHAR2(50))


PARTITION BY RANGE(data)
(PARTITION P1 VALUES LESS THAN (TO_DATE('01.04.2007','DD.MM.YYYY')),
PARTITION P2 VALUES LESS THAN (TO_DATE('01.09.2007','DD.MM.YYYY')));

INSERT INTO tabela_p SELECT data, cont, divizia FROM tabela_m;

SELECT * FROM tabela_p WHERE DATA <TO_DATE('01.02.2007','DD.MM.YYYY');


SELECT * FROM tabela_p partition (p1) WHERE DATA
<TO_DATE('01.02.2007','DD.MM.YYYY');

Cost 17
SELECT * FROM tabela_m WHERE DATA <TO_DATE('01.02.2007','DD.MM.YYYY');
Cost 99

CLUSTERE

Sa se realizeze un cluster pentru campul nr_comanda si sa se adauge la acest cluster 2 tabele:


comenzi2 si rand_comenzi2 cu aceeasi structura cu tabelele din aplicatie.

CREATE CLUSTER cls_nrcomanda (nr_comanda NUMBER(12));


CREATE INDEX idx_nrcomanda ON CLUSTER cls_nrcomanda;

CREATE TABLE comenzi2


CLUSTER cls_nrcomanda (nr_comanda)
AS SELECT * FROM comenzi;

CREATE TABLE rand_comenzi2


CLUSTER cls_nrcomanda (nr_comanda)
AS SELECT * FROM rand_comenzi;

Vizualizarea informatiilor despre clustere:


SELECT * FROM USER_CLUSTERS;