Sunteți pe pagina 1din 5

Laborator 9

Alte exemple de proceduri si functii.


Apelarea repetitiva dintr-un cursor a unei functii stocate anterior. Utilizarea a doua cursoare.
1. CREAREA A TREI TABELE
Crearea tabelelor se regaseste in script.
2. COMPLETAREA CU DATE
Popularea tabelelor cu date se face se realizeaza
in ordinea „parinti”  „copii”.
Trebuie respectata ordinea si tipul campurilor.
BEGIN
Pentru a adauga datele mai rapid, instructiunile au fost
incadrate intr-o procedura.
END;
/

Vom realiza diverse proceduri, deci avem nevoie de activarea afisarii.


SET SERVEROUTPUT ON;
3. Procedura stocata - totalul incasarilor realizate de soferii unei categorii precizata ca parametru
SELECT categ, SUM(incasari) AS total
FROM curse_XY INNER JOIN soferi_XY ON curse_XY.codpers=soferi_XY.codpers
GROUP BY categ
HAVING UPPER(categ)='B';
Transferarea instructiunii SELECT intr-o procedura stocata cu parametru
CREATE OR REPLACE PROCEDURE calc_tot_categ (p_categ soferi_XY.categ%TYPE) AS
v_categ soferi_XY.categ%TYPE;
v_tot NUMBER;
BEGIN
SELECT categ, SUM(incasari) INTO v_categ, v_tot
FROM curse_XY INNER JOIN soferi_XY ON curse_XY.codpers=soferi_XY.codpers
GROUP BY categ
HAVING UPPER(categ)=UPPER(p_categ);
DBMS_OUTPUT.PUT_LINE ('Totalul categoriei '||v_categ||' este '||v_tot);
END;
/
EXECUTE calc_tot_categ('&dati_categoria');
Transferarea instructiunii SELECT intr-o functie cu parametru
CREATE OR REPLACE FUNCTION total_categ (pf_categ soferi_XY.categ%TYPE) RETURN NUMBER AS
vf_total NUMBER;
BEGIN
SELECT SUM(incasari) INTO vf_total
FROM curse_XY INNER JOIN soferi_XY ON curse_XY.codpers=soferi_XY.codpers
GROUP BY categ
HAVING UPPER(categ)=UPPER(pf_categ);
RETURN vf_total;
END;
/
Apelarea functiei dintr-o procedura nestocata.

DECLARE
v_prel_categ soferi_XY.categ%TYPE;
v_tot NUMBER;
BEGIN
v_prel_categ:=UPPER('&dati_categoria');
v_tot:=total_categ(v_prel_categ);
DBMS_OUTPUT.PUT_LINE ('Totalul categoriei '||v_prel_categ||' este '||v_tot);
END;
/

Trecerea la cursor pentru a afisa totalul incasarilor fiecarei categorii; totalul fiecarei categorii se va calcula
repetitiv cu ajutorul functiei stocate total_categ care are ca argument o valoare din cursor; de asemenea, se va
realiza si un total general la sfarsitul tabelului calculat in doua moduri.
-pregatire SELECT
SELECT categ
FROM soferi_XY
GROUP BY categ;
sau
SELECT DISTINCT categ
FROM soferi_XY;
-procedura de calcul al totalului la fiecare categorie si obtinerea, in acelasi timp, si al totalului general.
CREATE OR REPLACE PROCEDURE calc_tot_categ_c1 AS
CURSOR c IS
SELECT DISTINCT categ
FROM soferi_XY;
v_calc NUMBER:=0;
v_tg NUMBER:=0;
BEGIN
FOR i IN c LOOP
v_calc:=total_categ(i.categ);
v_tg:=v_tg+v_calc;
DBMS_OUTPUT.PUT_LINE ('Totalul categoriei '||i.categ||' este '||v_calc);
END LOOP;
DBMS_OUTPUT.PUT_LINE ('--------------------------------------');
DBMS_OUTPUT.PUT_LINE ('Total general '||v_tg);
END;
/
EXECUTE calc_tot_categ_c1;

-Varianta a doua cu cap de tabel si calculul unui total general calculat intr-un SELECT separat;
CREATE OR REPLACE PROCEDURE calc_tot_categ_c2 AS
CURSOR c IS
SELECT DISTINCT categ
FROM soferi_XY;
v_calc NUMBER:=0;
v_tg NUMBER:=0;
BEGIN
DBMS_OUTPUT.PUT_LINE ('Cod categorie Total incasari');
FOR i IN c LOOP
v_calc:=total_categ(i.categ);
DBMS_OUTPUT.PUT_LINE (' '||i.categ||' '||v_calc);
END LOOP;
DBMS_OUTPUT.PUT_LINE ('--------------------------------------');
SELECT SUM(incasari) INTO v_tg
FROM curse_XY;
DBMS_OUTPUT.PUT_LINE ('Total general '||v_tg);
END;
/

EXECUTE calc_tot_categ_c2;

4. Intrucat oricare dintre soferi poate efectua curse cu oricare dintre vehiculele din parc, sa se afiseze totalul
incasarilor pe fiecare din combinatiile POSIBILE!! dintre soferi si vehicule, ordonate alfabetic dupa numele
soferilor si apoi dupa id_ul auto; daca acest total este zero, sa se afiseze un mesaj in care se precizeaza ca
acel sofer nu a efectuat curse cu acel vehicul.

Construirea functiei de calcul a totalului incasarilor pe fiecare sofer si auto.

CREATE OR REPLACE FUNCTION total_sf_auto (p_cp soferi_XY.codpers%TYPE, p_id parc_XY.id_auto%TYPE)


RETURN NUMBER AS
v_tot_f NUMBER;
BEGIN
SELECT SUM(incasari) INTO v_tot_f
FROM curse_XY
GROUP BY codpers,id_auto
HAVING codpers=p_cp AND id_auto=p_id;

RETURN v_tot_f;

EXCEPTION
WHEN NO_DATA_FOUND THEN
RETURN 0;

END;
/
Afisarea tuturor combinatiilor posibile--produs cartezian, relatie fara WHERE

SELECT codpers,id_auto,nume,nrauto
FROM soferi_XY,parc_XY
ORDER BY nume,id_auto;
Procedura de apelare a functiei de mai sus

CREATE OR REPLACE PROCEDURE list_inc AS


CURSOR c IS
SELECT codpers,id_auto,nume,nrauto
FROM soferi_XY,parc_XY
ORDER BY nume,id_auto;
v_total NUMBER;
BEGIN
DBMS_OUTPUT.PUT_LINE (' Nume sofer Nr auto Suma');
FOR i IN c LOOP
v_total:=total_sf_auto(i.codpers,i.id_auto);
IF v_total > 0 THEN
DBMS_OUTPUT.PUT_LINE (' '||i.nume||' '||i.nrauto||' '||v_total);
ELSE
DBMS_OUTPUT.PUT_LINE (' '||i.nume||' '||i.nrauto||' nu a efectuat curse');
END IF;
END LOOP;
END;
/

EXECUTE list_inc;

5. Procedura de mai sus poate fi imbunatatita


prin utilizarea a doua cursoare legate intre ele,
astfel incat numele soferului sa apara o singura
data; prin aceasta metoda se poate obtine o
situatie mai amanuntita, dupa cum urmeaza.

CREATE OR REPLACE PROCEDURE list_inc_supl AS

CURSOR c1 IS
SELECT codpers,nume
FROM soferi_XY
ORDER BY nume;

v_trs_cod soferi_XY.codpers%TYPE;

CURSOR c2 IS
SELECT codpers,id_auto,nrauto
FROM soferi_XY,parc_XY
WHERE codpers=v_trs_cod
ORDER BY nume,id_auto;

v_total NUMBER;
contor NUMBER :=0;
v_tot_sof NUMBER :=0;
BEGIN
DBMS_OUTPUT.PUT_LINE (' Nume sofer Nr auto Suma');
DBMS_OUTPUT.PUT_LINE ('-------------------------------------------------------------');
FOR i IN c1 LOOP
DBMS_OUTPUT.PUT_LINE (' '||i.nume);
v_tot_sof:=0;
v_trs_cod:=i.codpers;
FOR j IN c2 LOOP
v_total:=total_sf_auto(j.codpers,j.id_auto);
IF v_total > 0 THEN
DBMS_OUTPUT.PUT_LINE (' '||j.nrauto||' '||v_total);
contor:=contor+1;
ELSE
DBMS_OUTPUT.PUT_LINE (' '||j.nrauto||' nu a efectuat curse');
END IF;
v_tot_sof:=v_tot_sof+v_total;
END LOOP;
DBMS_OUTPUT.PUT_LINE ('-------------------------------------------------------------');
DBMS_OUTPUT.PUT_LINE (' Total sofer '||v_tot_sof);
DBMS_OUTPUT.PUT_LINE ('-------------------------------------------------------------');
END LOOP;
DBMS_OUTPUT.PUT_LINE (' Combinatii realizate '||contor);
END;
/

EXECUTE list_inc_supl;

Obs:
Cand se utilizeaza doua cursoare interconectate, este necesara declararea unei variabile intre declararile celor
doua cursoare, variabila ce este utilizata pentru transferul valorii ce provine de la primul cursor si intervine in cel
de-al doilea cursor.

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