Sunteți pe pagina 1din 17

PROIECT BAZE DE DATE

DESCRIEREA PROBLEMEI

În realizarea proiectului am aplicat cunoștințele dobândite pe parcursul


seminarelor și cursurilor la materia Baze de date, într-o problemă cu caracter economic.
Pentru a ține evidența operațiunilor efectuate în gestionarea unei cofetării, în acest proiect am
ulitizat o bază de date Oracle.

Baza de date este alcătuită din 7 tabele: ANGAJATI2, CLIENTI2, FURNIZORI,


PRODUSE2, TRANZACTIE2, DETALII_TRANZACTIE2, MATERIIPRIME.

Pentru crearea tabelelor și definirea legăturilor dintre ele, s-a obținut o astfel de
bază de dată:

 Tabela ANGAJATI2 cuprinde informații despre angajații care lucrează în cofetărie. În


tabelă se regăsesc date referitoare la nume, prenume, funcția, data angajării, salariu,
email și data nașterii.
 Tabela ClLIENTI2 cuprinde date despre clienții care cumpără din cofetărie. Prin date
facem referire la nume, prenume, număr de telefon și adresă.
 Tabela FURNIZORI cuprinde furnizorii care sunt activi și disponibili în procesul de
livrare a materiilor prime pentru cofetărie și regăsim datele: denumirea firmei,
reprezentantul firmei, număr de contact și email.
 Tabela PRODUSE2 conține denumirea, pretul la care produsele sunt date spre
vânzare, clientul care a cumpărat si materiile prime utilizate în procesul fabricării.
 Tabela TRANZACTIE2 conține date referitoare la data tranzacției pe care a efectuat-o
un angajat.
 Tabela DETALII_TRANZACTIE2 cuprinde tranzacția efectuată, dar și detaliile
despre aceasta, precum denumirea și cantitatea produselor achiziționate de client.
 Iar tabela MATERIIPRIME cuprinde denumirea materiilor prime si prețul la care au
fost achiziționate de la furnizori pentru a produce produsele finite comercializate de
cofetărie.
SCHEMA FINALĂ A BAZEI DE DATE

TEMA 1

--Adaugarea unui produs nou si modificarea unui nume cu id-ul 10, daca acesta exista.
BEGIN
INSERT INTO PRODUSE2 VALUES(8,'Ecler',10,4,5);
UPDATE angajati2
SET nume='Sorin'
WHERE id_angajat=10;
IF SQL%NOTFOUND THEN
DBMS_OUTPUT.PUT_LINE('Nu exista acest id');
END IF;
END;
/
--Cursor explicit
--Se afiseaza numele, prenumele angajatilor cu salariul 1200 folosind un cursor explicit si
variabile scalare
DECLARE
CURSOR ang_cursor IS SELECT nume, prenume, salariu FROM ANGAJATI2 WHERE
salariu=1200;
v_num angajati2.nume%type;
v_pren angajati2.prenume%type;
v_sal angajati2.salariu%type;
BEGIN
DBMS_OUTPUT.PUT_LINE('Angajatii cu salariul=1200');
OPEN ang_cursor;
LOOP
FETCH ang_cursor INTO v_num, v_pren, v_sal;
EXIT WHEN ang_cursor%NOTFOUND;
DBMS_OUTPUT.PUT_LINE('Angajatul '|| v_num ||' ' || v_pren ||' are salariul '||v_sal);
END LOOP;
END;
/

--Cursor explicit
--Sa se afiseze produsele si cantitatea achizitionarii
DECLARE
cursor c_com IS
SELECT p.denumire,d.cantitate
FROM produse2 p, detalii_tranzactie2 d
WHERE p.id_produs=d.id_produs
ORDER BY cantitate;

BEGIN
FOR rec_com in c_com LOOP
DBMS_OUTPUT.PUT_LINE('Produsul: '||rec_com.denumire||', '||'a fost achizitionat la o
cantitate de: '||rec_com.cantitate);
END LOOP;
END;
/

--Cursor explicit
--Se afiseaza in ordine angajatii cu id-ul in intervalul 1-9, atata timp cat salariul acestora
este mai mare de 1200
DECLARE
v_id angajati2.id_angajat%type;
v_nume angajati2.nume%type;
v_sal angajati2.salariu%type;
CURSOR c IS SELECT id_angajat, nume, salariu FROM angajati2;
BEGIN
OPEN c;
FOR i IN 1..9 LOOP
FETCH c INTO v_id, v_nume, v_sal;
SELECT salariu INTO v_sal FROM angajati2 WHERE id_angajat=i;
DBMS_OUTPUT.PUT_LINE('Salariatul cu codul '||i||' are salariul: '||v_sal);
EXIT WHEN v_sal<1200;
END LOOP;
END;
/

--Cursor implicit
--Se afiseaza reprezentantul care au furnizat materiile prime folosite in biscuiti
BEGIN
FOR row IN (
SELECT DISTINCT f.reprezentant_firma
FROM furnizori2 f
JOIN materiiprime m ON f.id_furnizor = m.id_furnizor
JOIN produse2 p ON m.id_materii = p.id_materii
WHERE p.denumire = 'Biscuiti'
) LOOP
DBMS_OUTPUT.PUT_LINE('Reprezentantul: ' || row.reprezentant_firma);
END LOOP;
END;
/

--Cursor implicit

--Se afiseaza tranzactia pe care a desfasurat-o un angajat citit de la tastatura


DECLARE

id_angajat angajati2.id_angajat%TYPE := &id;

BEGIN

FOR tranz IN (

SELECT t.id_tranzactie, t.data_tranzactie

FROM tranzactie2 t

WHERE t.id_angajat = id_angajat

) LOOP

DBMS_OUTPUT.PUT_LINE('Angajatul cu ID-ul ' || id_angajat || ' a desfășurat tranzacția cu ID-ul '


|| tranz.id_tranzactie || ' la data de ' || TO_CHAR(tranz.data_tranzactie, 'DD.MM.YYYY'));

END LOOP;

END;

TEMA 2
--Exceptie implicita
--Sa se afiseze produsul cu id ul 9. Să se trateze eroarea apărută în cazul în care nu există
nici un angajat cu acest cod.
DECLARE
v_den produse2.denumire%type;
BEGIN
SELECT denumire INTO v_den
FROM produse2
WHERE id_produs=9;
DBMS_OUTPUT.PUT_LINE(v_den);
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('Nu exista produsul cu acest id');
END;
/

--Exceptie implicita
-- Programul trebuie să verifice dacă clientul cu ID-ul specificat există în tabela "Clienti" și
să adauge înregistrarea în tabela "detalii_tranzactie2" numai dacă clientul există. Daca nu,
atunciridicati o excepție implicită care să afișeze un mesaj corespunzător indicând că
clientul nu există în baza de date. Adaugati o alta exceptie daca mai apare o eroare
neasteptata.
DECLARE
v_id_client detalii_tranzactie2.id_client%TYPE := &id_client; -- ID-ul clientului
v_count NUMBER;
BEGIN
-- Verifică dacă clientul există în tabela "Clienti"
SELECT COUNT(*) INTO v_count FROM Clienti2 WHERE id_client = v_id_client;

IF v_count = 0 THEN
RAISE NO_DATA_FOUND;
END IF;
INSERT INTO detalii_tranzactie2 (id_client)
VALUES (v_id_client);

COMMIT;
DBMS_OUTPUT.PUT_LINE('Inregistrarea a fost adaugata cu succes in tabela
detalii_tranzactie2!');
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('Eroare: Clientul cu ID-ul ' || v_id_client || ' nu exista in baza de
date!');
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('Eroare: O eroare neasteptata a aparut in timpul adaugarii
înregistrarii!');
END;

--Exceptie explicita
--Sa se adauge un angajat nou
DECLARE
val_insuficiente EXCEPTION;
PRAGMA EXCEPTION_INIT(val_insuficiente, -00001);
BEGIN
INSERT INTO angajati2(id_angajat, functia) VALUES(10, NULL);
EXCEPTION
WHEN val_insuficiente THEN
DBMS_OUTPUT.PUT_LINE('Nu ati precizat informatii suficiente pentru angajat');
DBMS_OUTPUT.PUT_LINE(SQLERRM);
END;
/
--Excepție explicită
--Să se modifice denumirea materiei prime cu id ul 8
DECLARE
invalid_mat EXCEPTION;
BEGIN
UPDATE materiiprime
SET denumire='Foietaj'
WHERE id_materii=8;
IF SQL%NOTFOUND THEN
RAISE invalid_mat;
END IF;
EXCEPTION
WHEN invalid_mat THEN
DBMS_OUTPUT.PUT_LINE('Nu exista materia prima cu acest ID');
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('A aparut o eroare! Nu se poate actualiza denumirea materiei
prime!');
END;
/

TEMA 3
--Subprograme- Proceduri
--Afisare nume si salariul pentru angajatul cu id nr. 2.
CREATE OR REPLACE PROCEDURE Angajat
(p_id_angajat IN angajati2.id_angajat%type,
p_nume OUT angajati2.nume%type,
p_salariu OUT angajati2.salariu%type)
IS
BEGIN
Select nume, salariu into p_nume, p_salariu from angajati2 where id_angajat=p_id_angajat;
DBMS_OUTPUT.PUT_LINE(' Angajatul '||p_nume||' are salariul de: '||p_salariu);
END;
/

SET SERVEROUTPUT ON
DECLARE
v_nume angajati2.nume%type;
v_salariu angajati2.salariu%type;
BEGIN
Angajat(2, v_nume, v_salariu);
END;
/

--Calcularea salariului mediu al tuturor angajatilor


CREATE OR REPLACE PROCEDURE calculeaza_salariu_mediu IS
salariu_mediu NUMBER;
BEGIN
SELECT AVG(salariu) INTO salariu_mediu FROM angajati2;
DBMS_OUTPUT.PUT_LINE('Salariul mediu al angajatilor este: ' || salariu_mediu);
END;
/
BEGIN
calculeaza_salariu_mediu;
END;
/
EXECUTE calculeaza_salariu_mediu;

--Funcția verifica_salariul returnează TRUE/FALSE daca salariatul are salariul mai


mare/mai mic sau egal cu salariul mediu si NULL daca salariatul nu exista
CREATE OR REPLACE FUNCTION verifica_salariul
(p_id_angajat IN angajati2.id_angajat%type, p_sal_mediu IN number)
RETURN Boolean
IS
v_salariul angajati2.salariu%type;
BEGIN
SELECT salariu into v_salariul from angajati2 where id_angajat=p_id_angajat;
IF v_salariul > p_sal_mediu then
return true;
ELSE
return false;
end if;
EXCEPTION
WHEN no_data_found THEN
return NULL;
end;
/
show errors

SET SERVEROUTPUT ON

DECLARE
v_sal_mediu number;
BEGIN
SAL_MEDIU (v_sal_mediu);

IF (verifica_salariul(6, v_sal_mediu) IS NULL) then


dbms_output.put_line('Angajat cu ID invalid!');
elsif (verifica_salariul(11, v_sal_mediu)) then
dbms_output.put_line('Salariatul are salariul mai mare decat media!');
else
dbms_output.put_line(' Salariatul are salariul mai mic decat media!');
end if;
IF (verifica_salariul(5, v_sal_mediu) IS NULL) then
dbms_output.put_line('Angajat cu ID invalid!');
elsif (verifica_salariul(110, v_sal_mediu)) then
dbms_output.put_line('Salariatul are salariul mai mare decat media!');
else
dbms_output.put_line(' Salariatul are salariul mai mic decat media!');
end if;

IF (verifica_salariul(14, v_sal_mediu) IS NULL) then


dbms_output.put_line('Angajat cu ID invalid!');
elsif (verifica_salariul(104, v_sal_mediu)) then
dbms_output.put_line('Salariatul are salariul mai mare decat media!');
else
dbms_output.put_line(' Salariatul are salariul mai mic decat media!');
end if;
END;
/

--Functii
--Afisarea cantitatii >10 din tabela detalii_tranzactie2
CREATE OR REPLACE FUNCTION afiseaza_cantitatea RETURN NUMBER IS
v_cantitate NUMBER := 0;
BEGIN
SELECT SUM(cantitate) INTO v_cantitate FROM detalii_tranzactie2 WHERE cantitate > 10;
RETURN v_cantitate;
END;
/
DECLARE
v_cantitate NUMBER;
BEGIN
v_cantitate := afiseaza_cantitatea();
DBMS_OUTPUT.PUT_LINE('Cantitatea de produse vândute cu o cantitate mai mare de 10
este: ' || v_cantitate);
END;
/
SELECT afiseaza_cantitatea() AS "Cantitate" FROM DUAL;

--Sa se calculeze varsta unui angajat al carui id este citit de la tastatura


CREATE OR REPLACE FUNCTION calcul_varsta_angajat(
p_id_angajat IN angajati2.id_angajat%TYPE
) RETURN NUMBER IS
v_varsta NUMBER;
BEGIN
SELECT FLOOR(MONTHS_BETWEEN(SYSDATE, data_nastere)/12)
INTO v_varsta
FROM angajati2
WHERE id_angajat = p_id_angajat;
RETURN v_varsta;
END;
/

DECLARE
v_id_angajat angajati2.id_angajat%TYPE;
v_varsta NUMBER;
BEGIN
v_id_angajat := &ID_ANGAJAT;
v_varsta := calcul_varsta_angajat(v_id_angajat);
DBMS_OUTPUT.PUT_LINE('Varsta angajatului cu ID-ul ' || v_id_angajat || ' este ' ||
v_varsta || ' ani.');
END;
/

--Pachete

--Creati un pachet in pl/sql o functie care returneaza numarul de produse cumparate de


catre un client al carui id este dat ca parametru. Tratati cazul în care nu exista clientul
specificat.

CREATE OR REPLACE PACKAGE pachet_produse AS


FUNCTION numar_produse_cumparate(p_client_id IN NUMBER) RETURN NUMBER;
END pachet_produse;
/

CREATE OR REPLACE PACKAGE BODY pachet_produse AS


FUNCTION numar_produse_cumparate(p_client_id IN NUMBER) RETURN NUMBER AS
v_numar_produse NUMBER := 0;
BEGIN
SELECT SUM(cantitate) INTO v_numar_produse
FROM detalii_tranzactie2
WHERE id_client = p_client_id;

RETURN v_numar_produse;
EXCEPTION
WHEN NO_DATA_FOUND THEN
RETURN 0;
END numar_produse_cumparate;
END pachet_produse;
/

DECLARE
v_numar_produse NUMBER;
BEGIN
v_numar_produse := pachet_produse.numar_produse_cumparate(2);

DBMS_OUTPUT.PUT_LINE('Numărul total de produse cumpărate: ' || v_numar_produse);


END;
/

--Creati un pachet in pl/sql care sa contina o procedura care a returneaza primii 3 angajati
cu cel mai mare salariu.

CREATE OR REPLACE PACKAGE pachet_angajati AS


PROCEDURE top_trei_angajati_cu_salariu;
END pachet_angajati;
/

CREATE OR REPLACE PACKAGE BODY pachet_angajati AS


PROCEDURE top_trei_angajati_cu_salariu AS
BEGIN
FOR angajat IN (SELECT *FROM (SELECT *FROM angajati2
ORDER BY salariu DESC
)
WHERE ROWNUM <= 3
) LOOP
DBMS_OUTPUT.PUT_LINE('Angajat ID: ' || angajat.id_angajat || ', Salariu: ' ||
angajat.salariu);
END LOOP;
END top_trei_angajati_cu_salariu;
END pachet_angajati;
/

BEGIN
pachet_angajati.top_trei_angajati_cu_salariu;
END;
/

TEMA 4

--Declansatori

--Exemplul de inserare să introducă un angajat cu un salariu de 6000, ceea ce declanșează


declanșatorul și afișează mesajul de eroare.

CREATE OR REPLACE TRIGGER trg_angajati2_salariu


BEFORE INSERT ON angajati2
FOR EACH ROW
BEGIN
IF :NEW.salariu > 5000 THEN
DBMS_OUTPUT.PUT_LINE('Nu se permite inserarea angajatului cu salariu mai mare decat
5000.');
RAISE_APPLICATION_ERROR(-20001, 'Nu se permite inserarea angajatului cu salariu mai
mare decat 5000.');
END IF;
END;
/

-- Exemplu de inserare care declanșează declanșatorul


INSERT INTO angajati2 (id_angajat, nume, salariu)
VALUES (1, 'Marian Iulica ', 6000);

--Un declansator care să se activeze după ștergerea unei înregistrări din tabela
"furnizori2". Declanșatorul va șterge automat toate înregistrările corespunzătoare din
tabela "materii_prime" care au același id_furnizor cu înregistrarea ștearsă.

CREATE OR REPLACE TRIGGER trig_stergere_furnizor


AFTER DELETE ON furnizori2
FOR EACH ROW
BEGIN
DELETE FROM materii_prime
WHERE id_furnizor = :OLD.id_furnizor;

COMMIT;
END;
/

-- Să se creeze o restricție în tabela "angajati2" care să nu permită angajarea unui angajat


cu vârsta sub 18 ani.

CREATE OR REPLACE TRIGGER verificare_varsta


BEFORE INSERT ON angajati2
FOR EACH ROW
BEGIN
IF MONTHS_BETWEEN(SYSDATE, :NEW.data_nastere) / 12 < 18 THEN
RAISE_APPLICATION_ERROR(-20001, 'Angajatul trebuie să aibă minim 18 ani.');
END IF;
END;
/

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