Sunteți pe pagina 1din 93

BAZE DE DATE

AVANSATE

prof. univ. dr. MUNTEAN Mihaela


Managementul datelor (data management) se referă la acțiunile pe care le întreprinde o
companie pentru a manipula și controla datele pentru a îndeplini condițiile necesare pe întreg
ciclul de viață al datelor.
Managementul bazelor de date (database management) se realizeaza prin intermediul unor
sisteme informatice dedicate, de tip sisteme pentru managementul bazelor de date (database
management systems - DBMS)
 Baze de date relationale
 Baze de date neralationale (NoSQL)
 Coloana: Inregistrarile de date se stocheaza pe coloana.
 Document: Datele se pastreaza in format JSON, XML, etc. Documentele au o cheie
unica si pot fi asociate cu inregistrarile, iar ele se stocheaza in colectii de
documente, ce se pot asocia cu tabele din modelul relational.
 Cheie-valoare: Se bazeaza pe conceptul de dictionar (map) prin care se asociaza
fiecarei cheie o anumita valoare.
 Graf: Se aplica pentru acele modele in care relatiile dintre elemente sunt multiple
spre exemplu retele de socializare, rute de transport
 Multi-model: Inglobeaza mai multe modele de baze de date nerelationale.
https://db-engines.com/en/ranking
ORACLE SERVER si clientul ORACLE SQLDeveloper

Obiectele unei baze de


date
- Tabele de date (tables)
- Vederi (interogari) -
views
- Proceduri (procedures) foaie de lucru pentru comenzile
- Functii (functions) SQL
- Triggere (triggers)
- Secvente (sequences)
- Tipuri definite (types)

Ex. Se vor crea tabelele EMP si DEPT si se vor insera date (inregistrari) -
https://livesql.oracle.com/apex/livesql/file/content_O5AEB2HE08PYEPTGCFLZU9Y
CV.html
Analizati modelul de date
EMP – PK:
DEPT – PK:
FK:
Tip relatie intre DEPT si EMP:
create table dept( deptno number(2,0), dname varchar2(14), loc varchar2(13),
constraint pk_dept primary key (deptno) );

create table dept( deptno number(2,0) primary key, dname varchar2(14), loc
varchar2(13));

Crearea unei tabele (create table) presupune precizarea numelui


tabelei si a campurilor componente.
 Fiecare camp are cel putin un nume (de ex. deptno) si este de un
anumit tip (de ex. number(2,0)).
 Se pot defini si specificatii suplimentare pentru campuri (definitii la nivel
de camp) sau pentru tabela (definitii globale la nivel de tabela).
Acestea se numesc constrangeri.

de ex. O constrangere de tip PRIMARY KEY:


- la nivel de camp: deptno number(2,0) primary key
- la nivel de tabela: constraint pk_dept primary key (deptno)
create table emp( empno number(4,0), ename varchar2(10), job
varchar2(9), mgr number(4,0), hiredate date, sal number(7,2),
comm number(7,2), deptno number(2,0),
constraint pk_emp primary key (empno),
constraint fk_deptno foreign key (deptno) references dept (deptno) );

Definitii la nivel de tabela


- definitia cheii primare
constraint pk_emp primary key (empno)
- definitia cheii straine
constraint fk_deptno foreign key (deptno) references dept (deptno)
Definitii echivalente pentru tabela EMP

create table emp( empno number(4,0), ename varchar2(10), job varchar2(9), mgr
number(4,0), hiredate date,
sal number(7,2), comm number(7,2), deptno number(2,0),
constraint pk_emp primary key (empno),
constraint fk_deptno foreign key (deptno) references dept (deptno) );

create table emp( empno number(4,0) PRIMARY KEY, ename varchar2(10),


job varchar2(9), mgr number(4,0), hiredate date,
sal number(7,2), comm number(7,2),
deptno number(2,0) references dept (deptno));
insert into DEPT (DEPTNO, DNAME, LOC) values(10, 'ACCOUNTING', 'NEW YORK');

insert into emp values (7839, 'KING', 'PRESIDENT', null,


to_date('17-11-1981','dd-mm-yyyy'), 5000, null, 10 );
SELECTAREA DATELOR

Sa se afiseze salariatii din departamentul 10.

SELECT empno, ename, sal, comm FROM emp WHERE deptno = 10;
CLAUZA GROUP BY

SELECT F1(camp1), F2(camp2), ….campi,…., Fn(campn)


FROM tabela1
[WHERE cond1]
GROUP BY campi;

Aceasta clauza imparte tabela in grupuri virtuale de linii. Liniile din fiecare grup
au aceeasi valoare in campul campi (criteriu de grupare). Pentru fiecare grup se
vor efectua operatiile stabilite prin functiile F1, F2,….Fn asupra valorilor din
campurile ce apar ca si argument al acestor functii.

Fj = SUM|MIN|MAX|COUNT|AVG ; j = 1,n
Pentru fiecare department, sa se calculeze numar de
angajati si valoarea totala a salariilor.

SELECT deptno, COUNT(empno), SUM(sal + NVL(comm,0))


FROM emp
GROUP BY deptno;

In campul comm, in dreptul angajatilor fara comison,


avem memorata valoarea NULL. Aceasta nu se poate
aduna cu o valoare numerica.
Functia NVL(comm, 0) interpreteaza valoarea NULL ca
fiind similara cu valoarea 0.
Se se determine numarul de departamente din fiecare
localitate.

SELECT loc, COUNT(deptno)


FROM dept
GROUP BY loc;

Pentru fiecare tip de job sa se determine numarul de


angajati, sal min, max si mediu.

SELECT job, COUNT(empno), MIN(sal + NVL(comm,0)),


MAX(sal+NVL(comm,0)), AVG(sal+NVL(comm,0))
FROM emp
GROUP BY job;
Sa se afiseze angajatii de tip ANALYST din departamentul 10
care au un salar mai mare decat 3000 si sa se determine
valoarea totala a salariilor acestora.

Atentie!!! Aceasta solicitare nu se poate rezolva cu o singura


comanda SELECT.

SELECT ename, hiredate, sal, joj, deptno


FROM emp
WHERE deptno = 10 AND sal > 3000 AND UPPER(job) =
'ANALYST‘;

SELECT deptno, SUM(sal)


FROM emp
WHERE deptno = 10 AND sal>3000 AND UPPER(job) = 'ANALYST‘;
GROUP BY deptno;
Sa se genereze un centralizator pentru fiecare departament, iar
in cadrul departamentelor la nivelul fiecarui tip de job cu
urmatoarele informatii: department, job, nr angajati, salar
mediu.

SELECT deptno, job, COUNT(empno), AVG(sal+NVL(comm,0))


FROM emp
GROUP BY deptno, job;
GENERAREA UNUI CLASAMENT – FUNCTIA RANK()

SELECT product_name, list_price,RANK()OVER(ORDER BY list_price DESC)


FROM products;
SELECTAREA PRIMELOR INREGISTRARI – TOP n

Afisarea primilor 5 salariati in ordine descrescatoare a salariilor

SELECT empno, ename, sal+NVL(comm,0)


FROM emp
ORDER BY sal+NVL(comm,0) DESC
FETCH FIRST 5 ROWS ONLY;
Nota finala = 30% Nota activitate curs + 30% Nota activitate seminar + 40 % Nota examen
BAZE DE DATE
AVANSATE

prof. univ. dr. MUNTEAN Mihaela


COMANDA SELECT. INTEROGAREA MAI MULTOR TABELE

1.

echijonctiune

2. non-echijonctiune In locul operatorului relational = avem un alt operator


relational, precum: <>, <, >, <=, >=
STUDIU DE CAZ
O schema relationala pentru modelarea evidentei proiectelor /granturilor gestionate de
catre personalui unei organizatii: organizatia are o structura departamentala; personalul
angajat este implicat in proiectele derulate in calitate de director proiect si/sau membru in
echipa.
 Sa se afiseze o lista alfabetica a directorilor de proiecte.

select id_personal, nume_personal, prenume_personal, id_proiect, titlu_proiect


from personal, proiect
where personal.id_personal = proiect.director_proiect
order by nume_personal, prenume_personal;
 Sa se afiseze numele angajatilor care lucreaza in echipa proiectului 11.

select nume_personal, prenume_personal


from personal, implicare_proiecte
where personal.id_personal = implicare_proiecte.id_personal and id_proiect = 11;

 Sa se determine numarul de angajati implicate in fiecare proiect. Se va


afisa si titlul fiecarui proiect

select proiect.id_proiect, titlu_proiect, COUNT (id_personal) +1


from proiect, implicare_proiecte
where select proiec.id_proiect = implicare_proiecte.id_proiect
group by proiect.id_proiect, titlu_proiect;
1.

Tabela1 contine date care NU au corespondent in Tabela2. Se doreste vizualizarea si a


acestor date (se ia tot din Tabela1 ).

2. non-echijonctiune In locul operatorului relational = avem un alt operator


relational, precum: <>, <, >, <=, >=
 Sa se afiseze o lista cu tot personalul,
iar in dreptul celor care coordoneaza
proiecte sa se afiseze si titlul si bugetul
acestora.

Join extern
SELECT id_personal, nume_personal,
prenume_personal, titlu_proiect,
buget_proiect
FROM personal, proiect
WHERE id_personal = director_proiect (+);

SELECT id_personal, nume_personal,


prenume_personal, titlu_proiect, buget_proiect Join intern
FROM personal, proiect
WHERE id_personal = director_proiect;
SELECT id_personal, nume_personal, prenume_personal,
titlu_proiect, buget_proiect
FROM personal, proiect
WHERE id_personal = director_proiect (+);

Formulati interogarea utilizand sintaxa RIGHT JOIN.

Semnul (+) insoteste campul director_proiect din tabela PROIECT. Acest lucru indica faptul ca, in
tabela PROIECT avem date mai “putine” (directorii de proiect sunt mai putin; nu sunt toti
angajatii).

RIGHT JOIN – in comanda SELECT numele tabelei PERSONAL va fi plasat la dreapta cuvantului
JOIN, deoarece din aceasta tabela urmeaza sa fie afisati toti agajatii, si cei care nu
coordoneaza proiecte.

SELECT id_personal, nume_personal, prenume_personal, titlu_proiect,


buget_proiect
FROM proiecte RIGHT JOIN personal ON id_personal = director_proiect ;
 Sa se afiseze o situatie cu departamentele
si cu nr total de proiect, precum si
valoarea totala a acestor proiecte ptr.
fiecare departament.
Ulterior sa se afiseze si denumirea
departamentelor.

SELECT id_departament, COUNT(id_proiect), SUM(buget_proiect)


FROM personal, proiect
WHERE id_personal = director_proiect
GROUP BY id_departament;

SELECT personal.id_departament, den_departament, COUNT(id_proiect), SUM(buget_proiect)


FROM personal, proiect, departament
WHERE id_personal = director_proiect AND personal.id_departament = departament.id_departament
GROUP BY personal.id_departament, den_departament;
STUDIU DE CAZ

create table produse (id_produs number(3) primary key,


den_produs varchar(35));
create table vanzari_produse (id_vanzare number(3) primary
key, data_vanzare date, id_produs number(3) references
produse(id_produs), cant number(5), pret number(10,2));
SELECT – afisare date detaliate

-- o lista cu vanzarile din produsul laptop 2

SELECT id_vanzare, data_vanzare, vanzari_produse.id_produs, den_produs, cant, pret,


cant* pret as valoare
FROM produse, vanzari_produse
WHERE produse. id_produs = vanzari_produse.id_produs AND den_produs = 'laptop 2'
ORDER BY id_vanzare;
SELECT – calculul si afisarea unor 'subtotaluri'

SELECT EXTRACT(MONTH FROM data_vanzare) AS Luna, SUM(cant * pret) AS


Valoare_lunara_totala
FROM vanzari_produse
GROUP BY EXTRACT(MONTH FROM data_vanzare)
ORDER BY EXTRACT(MONTH FROM data_vanzare);

SELECT – calculul si afisarea unui ‘total general'

SELECT SUM(cant * pret) AS Valoare_totala


FROM vanzari_produse;

CELE 3 TIPURI DE PRELUCRARI NU SE POT COMBINA INTR_O SINGURA COMANDA SELECT !!!!!!
SA SE IMPLEMENTEZE URMATOARELE PRELUCRARI CU AJUTORUL
COMENZILOR SQL

1. Sa se calculeze pentru fiecare produs de cate ori a fost


solicitat, totalul cantitativ si totalul valoric.
2. Sa se afiseze o lista cu vanzarile inregistrare in luna martie
2022
3. Sa se adauge in tabela PRODUSE campul STOC de tip
NUMBER si OBS de tip VARCHAR
4. Se va actualiza campul STOC cu o aceeasi valoare
numerica, de ex. 1000.
5. Sa se afiseze urmatoarea situatie a produsor: ID_PRODUS,
DEN_PRODUS, STOC, TOTAL_CANTITATIV_VANDUT
Daca total_cantitativ_vandut > 75% stoc se va afisa in
coloana OBS mesajul ‘Atentie! Este necesara o
aprovizionare’

6. Sa se afiseze produsele din care nu s-a vandut nimic.


7. Sa se afiseze o situatie lunara cu totalul cantitativ si totalul valoric pentru fiecare
produs
Nu apare conditia de JOIN dintre tabele:
vanzari_produse.id_produs = produse.id_produs

Campul id_vanzare NU poate sa apara in comanda, deoarece asupra lui nu este aplicata
nici o functie de tipul SUM, COUNT, MIN, MAX, AVG si nu apare nici in conditia de grupare
BAZE DE DATE
AVANSATE

prof. univ. dr. MUNTEAN Mihaela


SA SE IMPLEMENTEZE URMATOARELE PRELUCRARI CU AJUTORUL
COMENZILOR SQL

1. Sa se calculeze pentru fiecare produs de cate ori a fost


solicitat, totalul cantitativ si totalul valoric.
2. Sa se afiseze o lista cu vanzarile inregistrare in luna martie
2022
3. Sa se adauge in tabela PRODUSE campul STOC de tip
NUMBER si OBS de tip VARCHAR
4. Se va actualiza campul STOC cu o aceeasi valoare
numerica, de ex. 1000.
5. Sa se afiseze urmatoarea situatie a produsor: ID_PRODUS,
DEN_PRODUS, STOC, TOTAL_CANTITATIV_VANDUT
Daca total_cantitativ_vandut > 75% stoc se va afisa in
coloana OBS mesajul ‘Atentie! Este necesara o
aprovizionare’

6. Sa se afiseze produsele din care nu s-a vandut nimic.


7. Sa se afiseze o situatie lunara cu totalul cantitativ si totalul valoric pentru fiecare
produs
SUBINTEROGARI

Acestea sunt comenzi SELECT plasate in cadrul unui SELECT


principal. Subinterogarea se poate utiliza in: clauza WHERE,
FROM, HAVING
Ex. Sa se afiseze tarile din regiunea Central and Eastern
Europe, care au un scor peste media scorului acestei
regiuni.

SELECT AVG(score) FROM indicatori_2020


WHERE regional_indicator = 'Central and Eastern Europe';
SELECT country_name, score FROM indicatori_2020
WHERE regional_indicator = 'Central and Eastern Europe' AND
score > (SELECT AVG(score) FROM indicatori_2020
WHERE regional_indicator = 'Central and Eastern Europe' );

COMANDA SELECT CU INSTRUCTIUNEA CASE


Sa se afiseze tarile din regiunea 'Western Europe‘ si GDP-ul inregistrat in anul 2020.
In dreptul celor care au un GDP > 10.5 se va afisa mesajul High GDP, in dreptul
celolltor tari Low GDP.
SELECT country_name, GDP_PER_CAPITA,
CASE
WHEN GDP_PER_CAPITA > 10.5 THEN 'High GDP'
ELSE
'Low GDP'
END AS OBS
FROM indicatori_2020
WHERE regional_indicator = 'Western Europe';
BAZE DE DATE
AVANSATE

prof. univ. dr. MUNTEAN Mihaela


SA SE IMPLEMENTEZE URMATOARELE PRELUCRARI CU AJUTORUL
COMENZILOR SQL

1. Sa se calculeze pentru fiecare produs de cate ori a fost


solicitat, totalul cantitativ si totalul valoric.
2. Sa se afiseze o lista cu vanzarile inregistrare in luna martie
2022
3. Sa se adauge in tabela PRODUSE campul STOC de tip
NUMBER si OBS de tip VARCHAR
4. Se va actualiza campul STOC cu o aceeasi valoare
numerica, de ex. 1000.
5. Sa se afiseze urmatoarea situatie a produsor: ID_PRODUS,
DEN_PRODUS, STOC, TOTAL_CANTITATIV_VANDUT
Daca total_cantitativ_vandut > 75% stoc se va afisa in
coloana OBS mesajul ‘Atentie! Este necesara o
aprovizionare’

6. Sa se afiseze produsele din care nu s-a vandut nimic.


7. Sa se afiseze o situatie lunara cu totalul cantitativ si totalul valoric pentru fiecare
produs
Sa se calculeze pentru fiecare produs de cate ori a fost solicitat, totalul cantitativ
si totalul valoric.

SELECT produse.id_produs, den_produs, COUNT(id_vanzare) AS NR_SOLICITARI,


SUM(cant) AS TOTAL_CANT, SUM(cant * pret) AS TOTAL_VALORIC
FROM produse, vanzari_produse
WHERE produse.id_produs = vanzari_produse.idprodus
GROUP BY produse.id_produs, den_produs;

Sa se afiseze o lista cu vanzarile inregistrare in luna martie 2022

SELECT data_vanzare, produse.id_produs, den_produs, cant, pret,


cant * pret AS VALOARE
FROM vanzari_produse, produse
WHERE produse.id_produs = vanzari_produse.idprodus AND
Data_vanzare BETWEEN TO_DATE(‘1/03/2022’,’dd/mm/yyyy’) AND
TO_DATE(‘31/03/2022’,’dd/mm/yyyy’);
Sa se adauge in tabela PRODUSE campul STOC de tip NUMBER si
OBS de tip VARCHAR
Se va actualiza campul STOC cu o aceeasi valoare numerica,
de ex. 1000
ALTER TABLE produse ADD stoc NUMBER(4);
ALTER TABLE produse ADD obs VARCHAR2(20);
UPDATE TABLE produse SET stoc = 1000;

Sa se afiseze urmatoarea situatie a produsor: ID_PRODUS, DEN_PRODUS,


STOC, TOTAL_CANTITATIV
Daca total_cantitativ_vandut > 75% stoc se va afisa in coloana OBS
mesajul ‘Atentie! Este necesara o aprovizionare’

SELECT produse.id_produs, den_produs, stoc, SUM(cant) AS TOTAL_CANTITATIV,


CASE
WHEN SUM(cant) > 0.75 * stoc THEN ‘Atentie! Este necesara o aprovizionare’
ELSE
‘ ‘
END AS OBS
FROM produse, vanzari_produse
WHERE produse.id_produs = vanzari_produse.id_produs
GROUP BY produse.id_produs, den_produs, stoc;
Sa se afiseze produsele din care nu s-a vandut nimic.

SELECT id_produs, den_produs FROM produse


WHERE id_produs NOT IN (SELECT DISTINCT id_produs FROM vanzari_produse);

Sa se afiseze o situatie lunara cu totalul cantitativ si totalul valoric pentru fiecare produs

SELECT EXTRACT(YEAR FROM data_vanzare), EXTRACT (MONTH FROM data_vanzare), id_produs,


SUM(cant), SUM(cant * pret)
FROM produse
GROUP BY EXTRACT(YEAR FROM data_vanzare), EXTRACT (MONTH FROM data_vanzare), id_produs;
SUBINTEROGARI

Acestea sunt comenzi SELECT plasate in cadrul unui SELECT


principal. Subinterogarea se poate utiliza in: clauza WHERE,
FROM, HAVING
Ex. Sa se afiseze tarile din regiunea Central and Eastern
Europe, care au un scor peste media scorului acestei
regiuni.

SELECT AVG(score) FROM indicatori_2020


WHERE regional_indicator = 'Central and Eastern Europe';
SELECT country_name, score FROM indicatori_2020
WHERE regional_indicator = 'Central and Eastern Europe' AND
score > (SELECT AVG(score) FROM indicatori_2020
WHERE regional_indicator = 'Central and Eastern Europe' );

COMANDA SELECT CU INSTRUCTIUNEA CASE


Sa se afiseze tarile din regiunea 'Western Europe‘ si GDP-ul inregistrat in anul 2020.
In dreptul celor care au un GDP > 10.5 se va afisa mesajul High GDP, in dreptul
celolltor tari Low GDP.
SELECT country_name, GDP_PER_CAPITA,
CASE
WHEN GDP_PER_CAPITA > 10.5 THEN 'High GDP'
ELSE
'Low GDP'
END AS OBS
FROM indicatori_2020
WHERE regional_indicator = 'Western Europe';
BAZE DE DATE
AVANSATE

prof. univ. dr. MUNTEAN Mihaela


lipseste FROM

CORECT. se calculeaza bugetul total

nu avem functia YEAR;


EXTRACT (YEAR FROM data_startup)_

conditia buget_proiect = MIN(buget_proiect) este eronata;


pentru a determina MIN trebuie formulata o subinterogare
nu se poate utiliza MIN(COUNT(id_personal))

CORECT. Se afiseaza id-urile proiectelor


(+) tabela “slaba”, iar LEFT | RIGHT indica prozitia
tabelei “bogate” fata de cuvantul JOIN
CREATE TABLE prof (id_prof NUMBER(3) PRIMARY KEY, nume VARCHAR2(30), prenume
VARCHAR2(30));
CREATE TABLE discipline (id_disc nUMBER(3) PRIMARY KEY, den_disc VARCHAR2(30), id_prof
NUMBER(3) REFERENCES prof(id_prof));
CREATE TABLE stud (nr_matr NUMBER(4) PRIMARY KEY, nume VARCHAR2(30), prenume
VARCHAR2(30));
CREATE TABLE evid_note (id_inreg NUMBER(5) PRIMARY KEY, data_nota DATE,
id_disc NUMBER(3) REFERENCES discipline(id_disc),
nr_matr NUMBER(4) REFERENCES stud(nr_matr), nota NUMBER(2) CHECK (nota IN (3,4,5,6,7,8,9,10)));

INSERT INTO prof VALUES (11, 'pop','mircea'); INSERT INTO stud VALUES (1,'st1','st1');
INSERT INTO prof VALUES (12, 'blaga','maria'); INSERT INTO stud VALUES (2,'st2','st2');
INSERT INTO prof VALUES (13, 'avram','mihai'); INSERT INTO stud VALUES (3,'st3','st3');
INSERT INTO stud VALUES (4,'st4','st4');
INSERT INTO discipline VALUES (1,'Retele de calculatoare', 12); INSERT INTO stud VALUES (5,'st5','st5');
INSERT INTO discipline VALUES (2,'Baze de date avansate', 12);
INSERT INTO discipline VALUES (3,'Medii de programare vizuala', 11);
INSERT INTO discipline VALUES (4,'Marketing online', 13);
INSERT INTO evid_note VALUES (1, TO_DATE('20.06.2022','dd.mm.yyyy'), 2, 3, 10);
INSERT INTO evid_note VALUES (2, TO_DATE('20.06.2022','dd.mm.yyyy'), 2, 1, 9);
INSERT INTO evid_note VALUES (3, TO_DATE('20.06.2022','dd.mm.yyyy'), 2, 2, 9);
INSERT INTO evid_note VALUES (4, TO_DATE('20.06.2022','dd.mm.yyyy'), 2, 5, 10);
INSERT INTO evid_note VALUES (5, TO_DATE('24.06.2022','dd.mm.yyyy'), 1, 1, 10);
INSERT INTO evid_note VALUES (6, TO_DATE('26.06.2022','dd.mm.yyyy'), 3, 3, 4);
INSERT INTO evid_note VALUES (7, TO_DATE('30.06.2022','dd.mm.yyyy'), 4, 1, 10);
INSERT INTO evid_note VALUES (8, TO_DATE('30.06.2022','dd.mm.yyyy'), 4, 5, 7);
1. O lista cu studentii care au promovat examenul la disciplina cu id_disc in ordine
descrescatoare a notelor.
2. O lista cu disciplinele si cu media notelor la acestea
3. O lista cu studentii care au obtinut la disciplina cu id_disc = 4 o nota > media
notelor la aceasta disciplina
4. O lista cu studentii si cu mediile acestora.
5. O lista cu disciplinele si numarul de student la examen la fiecare disciplina
6. O lista cu disciplinele la care s-au prezentat la examen cei mai putini studenti.
7. O lista cu profesorii, numarul de discipline predate
8. Urmatoarea situatie: nume profesor, disciplina, nota_min, nota_max
Partea executabila a unui bloc de program

comenzi SQL (CREATE TABLE, ALTER TABLE, DROP


TABLE, INSERT INTO, DELETE FROM, UPDATE, SELECT)
BEGIN
Instructiuni; instructiuni ptr. implementarea structurilor
END; algoritmice fundamentale; secventa, decizie,
/ selectie si iteratie

Secventa: un grup de comenzi SQL si/sau


instructiuni care se executa in ordinea in care apar.
variabila := valoare;

IF conditie THEN Secventa A;


ELSE
Secventa B;
END IF;
LOOP
Secventa A;
EXIT WHEN conditie;
END LOOP;

Instructiunea LOOP – END


LOOP cu EXIT WHEN permite
amplasarea unei secvente si
dupa comanda EXIT WHEN.
WHILE conditie LOOP
Secventa A; LOOP
END LOOP; secventa A;
EXIT WHEN conditie;
secventa B;
END LOOP;
Structura repetitiva cu contor

FOR I IN 1..N LOOP


Secventa;
END LOOP;
BLOCURI DE PROGRAM IN PL/SQL

PROCEDURI

ANONIME

FUNCTII
tipareste o linie
O procedura care afiseaza datele unui angajat precizat prin
identificatorul sau.
create or replace procedure p_afis_mm (p_empno number) is
v1 emp.empno%type;
v2 emp.ename%type;
v3 emp.sal%type;
v4 emp.comm%type;
v5 number;
begin
select empno, ename, sal, nvl(comm,0), sal+nvl(comm,0) into v1, v2, v3, v4, v5 from emp 
where empno = p_empno;
dbms_output.put_line ('nume '||v1);
dbms_output.put_line ('departament '||v2);
dbms_output.put_line ('salar '||v3);
dbms_output.put_line ('comision '||v4);
dbms_output.put_line ('total '||v5);
end;
/

Apelul procedurii:

begin 
p_afis_mm (7839);
end;
/
1.Procedura pafis are definit parametrul p_empno. Acesta se comporta ca si o variabila si permite formularea unor
conditii in codul de program. Paremetrului i se atribuie o valoare in momentul in care procedura se va executa ca
urmare a apelului ei.
Apelul procedurii (si deci executia ei) se realizeaza cu begin pafis (7698); end;.
Deci, p_empno va fi 7698 si pentru acest angajat se va efectua calculul.
- p_empno - parametru formal;
- 7698 - parametru actual.

2.In partea de declaratii a procedurii sunt definite variabilele v1, v2, v3, v4 si v5. Ele sunt locale procedurii, adica au
sens doar in interiorul ei. Pentru variabile valorile se calculeaza/determina in interiorul procedurii, pe cand
parametrul p_empo primeste o valoare (prin echivalentul sau actual) din exteriorul procedurii si stabileste contextul
in care se executa comenzile SQL/instructiunile din interiorul procedurii (in cazul nostru, stabileste angajatul pentru
care se vor efectua prelucrarile).

3.Declaratia (definirea) unei variable presupune precizarea numelui variabilei si a tipului ei. De exemplu,
v1 NUMBER(4);
sau
v1 emp.ename%TYPE; unde %TYPE este un atribut al campului ENAME din tabela EMP si reprezinta tipul
acestui camp.

4. Comanda SELECT contine clauza INTO v1, v2, v3, v4, v5. Rezultatul comenzii SELECT se memoreaza in
variabilele specificate.
Daca angajatul nu exista in tabela EMP, atunci executia procedurii se finalizeaza cu
eroare – No Data Found.
Aceasta este cauzata de executia comenzii SELECT si reprezinta o asa numita
EXCEPTIE, ce trebuie tratata (programata) in partea de EXCEPTION a procedurii.

begin 
p_afis_mm (0);
end;
/
BAZE DE DATE
AVANSATE

prof. univ. dr. MUNTEAN Mihaela


COMANDA SELECT IN PL/SQL
I. Daca comanda SELECT realizeaza o prelucrare care va returna o singura
valoare sau o singura linie de valori, atunci comanda se poate trece direct (cu
clauza INTO variable) in blocul de program.

II. Daca comanda SELECT va genera un output multiplu, atunci se va utiliza o


structura de date de tip CURSOR pentru a prelua datele generate de catre
SELECT.
Obs. Structura de date de tip CURSOR se poate utiliza si in primul caz.

III. Utilizam varianta I in formularea unei comenzi SELECT si apare urmatoarea


situatie:
- Comanda SELECT nu poate genera un rezultat, fiindca nu identifica date. In
aceasta situatie, se declanseaza exceptia NO_DATA_FOUND. Aceasta trebuie
tratata/programata in zone de exceptii a programului.
- Comanda SELECT incearca sa genereze un output multiplu. Nu va putea si se
declanseaza exceptia TOO_MANY_ROWS.
Definitie: CURSOR c IS SELECT camp1, camp2,….. , campn FROM tabela;

A FOR i IN c LOOP
instructiuni cu i.camp1, i.camp2,……., i.campn;
alte instructiuni;
END LOOP;
Variabila i are o structura similara cu structura cursorului, adica este data de campurile
care apar in comanda SELECT. In variabila i sunt preluate pe rand liniile din cursor.

B OPEN c;
--se citeste prima linie de date din cursor cu FETCH, iar datele sunt transferate in
--variabilr
FETCH c INTO variabile;
WHILE c%FOUND LOOP Obs. c%FOUND si c%NOTFOUND
sunt atribute ale cursorului c. Ele
instructiuni cu variabilele si alte instructiuni; iau automat valorile TRUE si sau
--se citeste urmatoarea linie din cursor FALSE in timpul executiei unei
FETCH c INTO variabile; comenzi FETCH
END LOOP;
CLOSE c;
C OPEN c;
LOOP
FETCH c INTO variabile;
EXIT WHEN c%NOTFOUND;
instructiuni cu variabilele si alte instructiuni
END LOOP;
CLOSE c;

Atributul %NOTFOUND atasat cursorului devine TRUE dupa ultima linie.


STUDIU DE CAZ
Sa se defineasca o procedura, care pentru un proiect oarecare,
afiseaza taskurile acestuia

create or replace procedure taskuri_proiect (pproiect varchar2) as


cursor c is
select task_name, budget from proiecte_mm where project = pproiect;
begin
for i in c loop
dbms_output.put_line (i.task_name||' '||i.budget);
end loop;
end;
/

Daca nu exista proiectul pproiect, instructiunea for loop…end loop nu se


executa, dar nu apare eroare. In aceasta situatie, dorim sa afisam
urmatorul mesaj:
Proiect inexistent !!!!!!
create or replace procedure taskuri_proiect (pproiect varchar2) as
cursor c is
select task_name, budget from proiecte_mm where project = pproiect;
vnr number := 0;
begin
select count(task_name) into vnr from proiecte_mm where project = pproiect;
-- daca proiectul nu exista, functia count nu va calcula nimic. Dar, nu apare eroare (exceptia
-- NO_DATA_FOUND).
If vnr > 0 then
for i in c loop
dbms_output.put_line (i.task_name||' '||i.budget);
end loop;
else
dbms_output.put_line (‘Proiect inexistent !!! ‘);
end;
/
Sa se defineasca o functie, care sa returneze bugetul unui
proiect oarecare

create or replace function buget_proiect (pproiect varchar2) return number as


vbuget sit_proiecte.buget_total%type;
begin
select budget_total into vbuget from sit_proiecte where project = pproiect;
-- daca proiectul nu exista, comanda nu va putea localiza o inregistrare si va
-- apare exceptia NO_DATA_FOUND;
return vbuget;
EXCEPTION
when no_data_found then
Return 0;
end; declare
/ vbuget number(4);
Begin
vbuget := buget_proiect(‘pr2’);
End;
/
1. O functie pentru calculul bugetul total.
2. O procedura care afiseaza o lista cu proiectele si bugetul aferent
fiecarui process. Se va utiliza o varianta care apeleaza comanda
FETCH
3. O functie care determina cel mai mic buget al unui proiect.
Functia va fi apelata dintr-o procedura, care va afisa proiectele
cu acest cel mai mic proiect.
Se va afisa intr-un control de tip dataViewGrid urmatoarea situatie cu
angajatii in care se va calcula abaterea salariului fata de sal_min si sal_max
al categoriei (job) in care se incadreaza fiecare.

SELECT empno, ename, emp.job, sal, sal_min,sal_max, round((sal-sal_min)/sal_min*100,2)


as abatere_min, round((sal-sal_max)/sal_max*100,2) as abatere_max
from emp, job_sal
where emp.job=job_sal.job;
Var I. Utilizarea urmatoarei comenzi SELECT in C#

SELECT empno, ename, emp.job, sal, sal_min,sal_max,


Math.Round((sal-sal_min)/sal_min*100,2) as abatere_min,
Math.Round((sal-sal_max)/sal_max*100,2) as abatere_max
from emp, job_sal
where emp.job=job_sal.job;

Var II. Crearea unui obiect de tip Query in baza de date Access si formularea in C# a unui SELECT
asupra acestui Query

SELECT * FROM Query1;


BAZE DE DATE
AVANSATE

prof. univ. dr. MUNTEAN Mihaela


CREATE TABLE angajati(cod_angajat NUMBER(3) PRIMARY KEY,nume VARCHAR2(40),salar NUMBER(6));
CREATE TABLE deplasari(cod_angajat NUMBER(3) REFERENCES angajati(cod_angajat), data_deplasare
DATE, loc_deplasare VARCHAR2(30), cost_transport NUMBER(6), cost_zi NUMBER(5), durata NUMBER(3),
id_deplasare NUMBER(6) PRIMARY KEY);
INSERT INTO angajati VALUES (101, 'pop marius',2000);
INSERT INTO angajati VALUES (102, 'blaga melania',3600);
INSERT INTO angajati VALUES (103, 'ionescu ana',2700);
INSERT INTO angajati VALUES (104, 'kovacs ion',3400);
INSERT INTO deplasari VALUES (101, to_date('20/01/2021','dd/mm/yyyy'),'berlin',30000,200,5,1);
INSERT INTO deplasari VALUES (101, to_date('19/02/2021','dd/mm/yyyy'),'bucuresti',570,80,3,2);
INSERT INTO deplasari VALUES (102, to_date('14/02/2021','dd/mm/yyyy'),'arad',70,80,2,3);
INSERT INTO deplasari VALUES (103, to_date('20/02/2021','dd/mm/yyyy'),'bucuresti',570,80,2,4);
INSERT INTO deplasari VALUES (103, to_date('10/03/2021','dd/mm/yyyy'),'berlin',31000,200,7,5);
INSERT INTO deplasari VALUES (103, to_date('20/03/2021','dd/mm/yyyy'),'oradea',110,80,3,6);
INSERT INTO deplasari VALUES (104, to_date('06/03/2021','dd/mm/yyyy'),'bucuresti',370,80,4,7);
Definitie: CURSOR c IS SELECT camp1, camp2,….. , campn FROM tabela;

A FOR i IN c LOOP
instructiuni cu i.camp1, i.camp2,……., i.campn;
alte instructiuni;
END LOOP;
Variabila i are o structura similara cu structura cursorului, adica este data de campurile
care apar in comanda SELECT. In variabila i sunt preluate pe rand liniile din cursor.

B OPEN c;
--se citeste prima linie de date din cursor cu FETCH, iar datele sunt transferate in
--variabilr
FETCH c INTO variabile;
WHILE c%FOUND LOOP Obs. c%FOUND si c%NOTFOUND
sunt atribute ale cursorului c. Ele
instructiuni cu variabilele si alte instructiuni; iau automat valorile TRUE si sau
--se citeste urmatoarea linie din cursor FALSE in timpul executiei unei
FETCH c INTO variabile; comenzi FETCH
END LOOP;
CLOSE c;
SELECT angajati.cod_angajat,nume, avg(durata), sum(cost_transport * durata*cost_zi)
FROM angajati, deplasari
WHERE angajati.cod_angajat = deplasari.cod_angajat
group by angajati.cod_angajat, nume
ORDER BY nume;
CREATE OR REPLACE PROCEDURE sinteza_deplasari IS
CURSOR c IS SELECT angajati.cod_angajat,nume, avg(durata), sum(cost_transport * durata*cost_zi)
FROM angajati, deplasari
WHERE angajati.cod_angajat = deplasari.cod_angajat
group by angajati.cod_angajat, nume
ORDER BY nume;
vcod number(10); vnume VARCHAR2(40);
vdurata NUMBER(10,2); vcost NUMBER(10,2);
i NUMBER(3); s NUMBER(10);
BEGIN
DBMS_OUTPUT.PUT_LINE ('Nr.crt COD_ANGAJAT NUME ANGAJAT DURATA_MEDIE COST_DEPLASARI');
i:=1; s:=0;
OPEN c;
LOOP
FETCH c INTO vcod,vnume,vdurata,vcost;
EXIT WHEN c%NOTFOUND;
DBMS_OUTPUT.PUT_LINE (i||' '||vcod||' '||vnume||' '||vdurata||' '||vcost);
i:=i+1; s:= s + vcost;
END LOOP;
CLOSE c;
DBMS_OUTPUT.PUT_LINE ('Cost total '||s);
END;
/
CREATE OR REPLACE PROCEDURE sinteza_deplasari_f IS
CURSOR c IS SELECT angajati.cod_angajat,nume, avg(durata), sum(cost_transport * durata*cost_zi)
FROM angajati, deplasari
WHERE angajati.cod_angajat = deplasari.cod_angajat
group by angajati.cod_angajat, nume
ORDER BY nume;
vnume VARCHAR2(40);
vcod number(10);
vdurata NUMBER(10,2); vcost NUMBER(10,2);
vcodf CHAR(10); vnumef CHAR(30); vdurataf CHAR(15); vcostf CHAR(25);
i NUMBER(3); s NUMBER(10);
BEGIN
DBMS_OUTPUT.PUT_LINE ('NR.CRT COD_ANGAJAT NUME ANGAJAT DURATA_MEDIE
COST_DEPLASARI');
i:=1; s:=0;
OPEN c;
LOOP
FETCH c INTO vcod,vnume,vdurata,vcost;
EXIT WHEN c%NOTFOUND;
vcodf := to_char(vcod); vnumef := to_char(vnume); vdurataf := to_char(vdurata); vcostf:= to_char(vcost);
DBMS_OUTPUT.PUT_LINE (i||' '||vcodf||' '||vnumef||' '||vdurataf||' '||vcostf);
i:=i+1; s:= s + vcost;
END LOOP;
CLOSE c;
DBMS_OUTPUT.PUT_LINE ('Cost total '||s);
END;
/
Se introduce un parametru de intrare (localitatea) si se va utiliza parcurgerea cursorului cu
instructiunea FOR I IN c LOOP.
CREATE OR REPLACE PROCEDURE sinteza_deplasari_ff (ploc varchar2) IS
CURSOR c IS SELECT angajati.cod_angajat,nume, avg(durata) as durata_medie, sum(cost_transport * durata*cost_zi) as
costuri
FROM angajati, deplasari
WHERE angajati.cod_angajat = deplasari.cod_angajat AND upper(ploc) = upper(loc_deplasare)
group by angajati.cod_angajat, nume
ORDER BY nume;
vcodf CHAR(10); vnumef CHAR(30); vdurataf CHAR(15); vcostf CHAR(25);
j NUMBER(3); s NUMBER(10);
BEGIN
DBMS_OUTPUT.PUT_LINE ('NR.CRT COD_ANGAJAT NUME ANGAJAT DURATA_MEDIE COST_DEPLASARI');
j:=1; s:=0;
FOR i IN C LOOP
vcodf := to_char(i.cod_angajat); vnumef := to_char(i.nume); vdurataf := to_char(i.durata_medie); vcostf:=
to_char(i.costuri);
DBMS_OUTPUT.PUT_LINE (j||' '||vcodf||' '||vnumef||' '||vdurataf||' '||vcostf);
j:=j+1; s:= s + i.costuri;
END LOOP;
DBMS_OUTPUT.PUT_LINE ('Cost total '||s);
END;
/

execute sinteza_deplasari_ff ('berlin');


Calculul costurilor totale sa se realizare cu ajutorul unei comenzi SELECT.
s:= s + i.costuri;
END LOOP;
SELECT sum(cost_transport * durata*cost_zi) INTO s FROM deplasari WHERE upper(ploc) =
upper(loc_deplasare);
DBMS_OUTPUT.PUT_LINE ('Cost total '||s);
END;
execute sinteza_deplasari_ff ('cucu');

Calculul costurilor totale sa se realizare cu ajutorul unei functii TOTAL_COST.


CREATE OR REPLACE FUNCTION costuri_totale (ploc varchar2) return number as
s number(10,2);
begin
SELECT sum(cost_transport * durata*cost_zi) INTO s FROM deplasari WHERE upper(ploc) =
upper(loc_deplasare);
if s> 0 then return s;
else return 0; begin
end if; dbms_output.put_line (costuri_totale('berlin'));
end; end;
/ /
END LOOP;
s:= costuri_totale(ploc);
DBMS_OUTPUT.PUT_LINE ('Cost total '||s);

execute sinteza_deplasari_ff ('berlin');

execute sinteza_deplasari_ff ('cucy');


CREATE OR REPLACE PROCEDURE sinteza_deplasari_ff (ploc varchar2)IS
CURSOR c IS SELECT angajati.cod_angajat,nume, avg(durata) as durata_medie, sum(cost_transport * durata*cost_zi)
as costuri
FROM angajati, deplasari
WHERE angajati.cod_angajat = deplasari.cod_angajat AND upper(ploc) = upper(loc_deplasare)
group by angajati.cod_angajat, nume
ORDER BY nume;
vnume VARCHAR2(40); vcod number(10);
vdurata NUMBER(10,2); vcost NUMBER(10,2);
vcodf CHAR(10); vnumef CHAR(30); vdurataf CHAR(15); vcostf CHAR(25); j NUMBER(3); s NUMBER(10);
BEGIN
if costuri_totale(ploc) > 0 then
DBMS_OUTPUT.PUT_LINE ('NR.CRT COD_ANGAJAT NUME ANGAJAT DURATA_MEDIE COST_DEPLASARI');
j:=1; s:=0;
FOR i IN C LOOP
vcodf := to_char(i.cod_angajat); vnumef := to_char(i.nume); vdurataf := to_char(i.durata_medie); vcostf:=
to_char(i.costuri);
DBMS_OUTPUT.PUT_LINE (j||' '||vcodf||' '||vnumef||' '||vdurataf||' '||vcostf);
j:=j+1;
END LOOP;
s:= costuri_totale(ploc);
DBMS_OUTPUT.PUT_LINE ('Cost total '||s);
else
dbms_output.put_line ('Nu exista deplasari ');
end if;
END;
/
BAZE DE DATE
AVANSATE

prof. univ. dr. MUNTEAN Mihaela


BILET EXAMEN BAZE DE DATE AVANSATE
I. Se vor crea urmatoarele tabele. Se vor introduce 3 masini si 7 curse.
Masini (cod_masina, tip_masina, anul_fabricatiei)
Curse (id_cursa, data_cursa, cod_masina, distanta, cost)
Codul masinii va lua urmatoarele valori: 111, 222, 333
II. Comanda SELECT: Sa se afiseze o lista cu masinile care NU au efectuat nici o cursa
III. A. sa se defineasca o functie care va determina cea mai mica distanta parcursa.
B. Functia se va utiliza intr-o procedura in care se vor afisa cursele inregistrate pe acesta distanta minima

cod_masina tip_masina id_cursa data_cursa distanta cost


………
………
……..
III. Se va defini o procedura cu un parametru de tip OUT pentru calcululul costului total al tuturor curselor. Procedura
va afisa cursele care au un cost > 30% din costul total.
Se va executa procedura.
 
  
SE VOR SALVA INTR-UN DOCUMENT WORD TOATE COMENZILE.
SE VOR EXECUTA COMENZILE, FUNCTIA SI PROCEDURILE SI SE VOR CAPTA ECRANE CU ACESTE EXECUTII.
UNIVERSITATEA DE VEST DIN TIMISOARA
FACULTATEA DE ECONOMIE SI DE ADMINISTRARE A AFACERILOR
DEPARTAMENTUL DE SISTEME INFORMATIONALE PENTRU AFACERI

SISTEME INFORMATICE
PENTRU ASISTAREA
DECIZIILOR
PROF. UNIV. DR. MIHAELA MUNTEAN
OBIECTE DE TIP TRIGGER
Un trigger (declansatot) este o procedura PL/SQL stocata pe server, care
se execută la apariţia unui eveniment, ce modifică starea anumitor
obiecte din baza de date.
comenzi INSERT, UPDATE, DELETE pe o tabelă;
comenzi INSERT, UPDATE, DELETE pe un
view (cu opţiunea INSTEAD OF);

comenzi CREATE, ALTER, DROP la


nivel de schemă sau bază de date;

comenzi SHUTDOWN, LOGON,


LOGOFF la nivel de schemă sau
bază de date, etc.
CREATE OR REPLACE TRIGGER trigger_name BEFORE|AFTER INSERT|
UPDATE [OF column,…]|DELETE ON table_name
[FOR EACH ROW ]

DECLARE
trigger_variables
BEGIN
trigger_body
END;

DROP TRIGGER trigger_name; - Eliminarea trigger-ului


:OLD si :NEW

 comanda INSERT
:OLD = NULL
:NEW = noua valoare se urmeaza a fi inserata;
 comanda UPDATE
:OLD = valoarea din tabela inainte de actualizare;
:NEW = valoarea noua ce va fi preluata;
 Comanda DELETE
:OLD = valoarea inainte de stergere;
:NEW = NULL
Sa se defineasca un trigger care, ori de cate ori va apare un apartament nou
in oferta imobiliarea, va afiseaza mesajul:

Atentie !!! A aparut un mobil tip ……….in zona ……….


CREATE OR REPLACE TRIGGER mesaj_insert BEFORE INSERT ON
apartamente
FOR EACH ROW
DECLARE
BEGIN
DBMS_OUTPUT.PUT_LINE ('Atentie !!! A aparut un imobil tip
'||:NEW.id_tip||
' in zona '||:NEW.id_zona);
END;
/

Se opteaza pentru un trigger de tip BEFORE INSERT.


Datele, care urmeaza sa fie inserate, se afla temporar in RAM si pot fi identificate prin:

:NEW.ID_AP, :NEW.ID_TIP, :NEW.ID_ZONA, :NEW.PRET_VANZARE, :NEW.ETAJ, :NEW.SUPRAFATA


, :NEW.NR_CAMERE
Sa se defineasca un trigger care atentioneaza orice modifiare a
pretului unui imobil.
Va afisa imobilul, pretul vechi si pretul nou.
CREATE OR REPLACE TRIGGER mesaj_update AFTER UPDATE OF PRET_VANZARE
ON apartamente
FOR EACH ROW
DECLARE
BEGIN
DBMS_OUTPUT.PUT_LINE ('Atentie !!! S-a modificat pretul unui imobil tip
'||:OLD.id_tip||' din zona '||:OLD.id_zona);
DBMS_OUTPUT.PUT_LINE ('Pret vechi '||:OLD.PRET_VANZARE||' Pret nou
'||:NEW.PRET_VANZARE);
END;
/

Avand in vedere ca aceasta comanda UPDATE nu afecteaza campurile id_tip


si id_zona, se poate utilza atat :OLD cat si :NEW pentru ele.
CREATE OR REPLACE TRIGGER mesaj_update AFTER UPDATE
OF PRET_VANZARE ON apartamente
FOR EACH ROW
DECLARE vtip varchar2(30);
vzona varchar2(30);
BEGIN
SELECT tip_apartament into vtip FROM tip WHERE id_tip = :OLD.id_tip;
SELECT nume_zona into vzona FROM zona WHERE id_zona = :OLD.id_zona;
DBMS_OUTPUT.PUT_LINE ('Atentie !!! S-a modificat pretul unui imobil tip '||vtip||' din zona '|
vzona); DBMS_OUTPUT.PUT_LINE ('Pret vechi '||:OLD.PRET_VANZARE||' Pret nou
'||:NEW.PRET_VANZARE);
END;
/

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