Documente Academic
Documente Profesional
Documente Cultură
Constrangerile pot fi mentionate atat la nivelul fiecarui camp cat si la sfarsit, dupa precizarea campurilor si a
tipurilor lor de date.
Se observa ca in aceasta situatie denumirile constrangerilor sunt alocate de catre Oracle.
Varianta de mai sus prin care se precizeaza cheia primara la sfarsit, poate fi utilizata si la crearea unei chei primare
duble.
Adaugand date asemanatoare in tabela clienti_ABC4, vom observa ca semnalarea erorilor se face prin denumirile
personalizate.
INSERT INTO clienti_ABC4 VALUES (1200,'Popescu','Arad');
1. TABELELE INITIALE
La fiecare din cele 2 tabele clienti este creat cate un tabel facturi, punand in evidenta modul de pozitionare si de
implementare al constrangerilor.
Constrangerile si legatura de subordonare se pot evidentia utilizand schema modelului de date.
Popularea tabelelor cu date se face se realizeaza in ordinea „parinti” „copii”, pentru a respecta integritatea
referentiala.
DESCRIBE clienti_DEF;
Daca sunt campuri ale caror valori se vor adauga ulterior, in instructiunea INSERT trebuie precizate campurile ale
caror valori se completeaza.
Folosim structura de tabele cu DEF1 pentru a nu afecta tabelele cu DEF pe care le vom utiliza si in instructiunile
ulterioare.
ATENTIE! Trebuie respectata integritatea referentiala, clientul cu codul 60 NU EXISTA in tabela parinte clienti_DEF
Adaugam aceleasi date si in tabela facturi_DEF1
Obs: in tabela facturi_DEF1 am adaugat doar facturile clientilor 10,20,30 intrucat doar acesti 3 clienti exista in
tabela parinte clienti_DEF1.
4. Instructiuni DDL
Obs: constrangerea NU ESTE VALIDATA SI ACTIVATA intrucat in tabela clienti_DEF1 a treia inregistrare nu
verifica aceasta noua constrangere.
Modificam constrangerea
UPDATE facturi_DEF1
SET luna=EXTRACT(MONTH FROM datafact);
Actualizarea cu conditie
La a doua inregistrare trebuie sa actualizam cu orasul Timisoara iar la a treia inregistrare trebuie sa punem clientul
Ionescu.
UPDATE clienti_DEF1
SET localit='Timisoara'
WHERE codcl=20;
UPDATE clienti_DEF1
SET dencl='Ionescu'
WHERE codcl=30;
Stergerea cu conditie
Stergerea tabelelor
Aceasta se realizeaza de la tabelele subordonate spre tabelele primare pentru a nu afecta integritatea
referentiala.
- Lista facturilor (nrfact, valoare, datafact) ..doar anumite campuri, intr-o alta ordine a coloanelor.
- Aceeasi lista ordonata descrescator dupa valorile campului valoare cu utilizarea indexului coloanei
Campul nrfact fiind cu valori unice (cheie primara), impiedica posibilitatea gruparii. De aceea trebuie, fie
eliminat, fie „prins” intr-o formula de grupare.
- Intocmirea unui clasament; aici nu se va mai putea utiliza noul nume al campului.
SELECT codcl, SUM(valoare) AS Total, RANK()OVER(ORDER BY SUM(valoare) DESC)
FROM facturi_DEF
GROUP BY codcl;
1. TABELELE INITIALE
Crearea tabelelor se regaseste in script.
2. INSERARE DE 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.
Instructiunile se regasesc in script.
END;
/
3. SELECT din 2 tabele
sau
In cazul interogarilor care contin grupari, campurile alese trebuie sa aiba valori cat mai omogene care sa permita
realizarea gruparilor. Daca se utilizeaza un astfel de camp, este necesara utilizarea unei functii de grupare pentru
acel camp.
Obs: disparitia campului cu valori eterogene nrfact, a dus la posibiltatea realizarii gruparilor pe fiecare client.
De asemenea s-a schimbat si indexul coloanei de grupare.
Daca se chiar doreste utilizarea si a campului nrfact, trebuie sa folosim o functie de grupare, de exemplu COUNT.
Observatii
- Filtrarea din clauza WHERE actioneaza inaintea gruparii datelor iar filtrarea din clauza HAVING actioneaza
dupa ce se fac gruparile si calculele pe grupuri;
- Prin utilizarea variantei JOIN, clauza WHERE ramane doar pentru filtrarea datelor inaintea gruparii;
- Exista situatii in care conditia de filtrare se poate aplica atat inante de grupare cat si dupa grupare, si anume
atunci cand acesta conditie se refera la un camp care nu este „afectat” de operatiunile de grupare si/sau de
calcul de grup
6. Subinterogare
Sa se calculeze media valorilor tuturor facturilor, indiferent de client.
Sa se afiseze apoi o situatie descrescatoare a facturilor care depasesc aceasta medie.
SELECT AVG(valoare)
FROM facturi_DEF;
- Rotunjirea valorii
SELECT ROUND(AVG(valoare),2) AS medie_facturi
FROM facturi_DEF;
OBS: Functiile de tip SUM, COUNT, AVG se pot folosi si fara GROUP BY, dar numai singure, fara campuri simple,
si, in aceasta situatie, calculul se face pentru toate valorile campului respectiv.
Cele doua interogari se pot combina, rezultatul primeia fiind folosit pentru filtrare in cea de-a doua.
SELECT clienti_DEF.codcl, dencl, valoare
FROM clienti_DEF,facturi_DEF
WHERE clienti_DEF.codcl=facturi_DEF.codcl AND valoare>(SELECT ROUND(AVG(valoare),2) AS medie_facturi
FROM facturi_DEF)
ORDER BY valoare DESC;
SELECT clienti_DEF.codcl, dencl, valoare
FROM clienti_DEF,facturi_DEF
WHERE clienti_DEF.codcl=facturi_DEF.codcl AND valoare>(SELECT AVG(valoare)
FROM facturi_DEF)
ORDER BY valoare DESC;
SELECT clienti_DEF.codcl, dencl, valoare
FROM clienti_DEF INNER JOIN facturi_DEF ON clienti_DEF.codcl=facturi_DEF.codcl
WHERE valoare>(SELECT AVG(valoare)
FROM facturi_DEF)
ORDER BY valoare DESC;
Observatii
- atunci cand rezultatul unei subinterogari este folosit ca si criteriu de filtrare (in WHERE sau in HAVING), acest
rezultat trebuie sa fie unic, nu un tabel cu una sau mai multe coloane; cand subinterogarea este folosita in
clauza FROM, atunci rezultatul subinterogarii trebuie sa fie un tabel
- in subinterogare nu este necesara redenumirea campului, rotunjirea valorii, etc intrucat rezultatul (AVG)
este folosit doar pentru comparare, nu este si afisat.
- cand este utilizat JOIN pentru legatura, in WHERE ramane doar filtrarea realizata pe baza subinterogarii.
Laborator 4
Instructiunea SELECT. Filtrari, campuri noi, grupari, duble grupari.
Utilizarea a 3 tabele.
1. TABELELE INITIALE
Crearea tabelelor se regaseste in script.
2. INSERARE DE 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.
Instructiunile se regasesc in script.
END;
/
3. Instructiuni SELECT noi; filtrari utilizand mai multe valori numerice.
- filtrare pe camp numeric VALORI DISCRETE – facturile clientilor 10, 30 SAU 50
SELECT nrfact, clienti_DEF.codcl, dencl, valoare, datafact
FROM clienti_DEF,facturi_DEF
WHERE clienti_DEF.codcl=facturi_DEF.codcl(+) AND (clienti_DEF.codcl=10 OR clienti_DEF.codcl=30 OR
clienti_DEF.codcl=50)
ORDER BY 2,4;
SELECT nrfact, clienti_DEF.codcl, dencl, valoare, datafact
FROM clienti_DEF LEFT JOIN facturi_DEF ON clienti_DEF.codcl=facturi_DEF.codcl
WHERE clienti_DEF.codcl=10 OR clienti_DEF.codcl=30 OR clienti_DEF.codcl=50
ORDER BY 2,4;
Pentru a reduce conditia de filtrare, se poate utiliza IN
SELECT nrfact, clienti_DEF.codcl, dencl, valoare, datafact
FROM clienti_DEF,facturi_DEF
WHERE clienti_DEF.codcl=facturi_DEF.codcl(+) AND clienti_DEF.codcl IN (10,30,50)
ORDER BY 2,4;
UPDATE facturi_DEF
SET cota_tva=
CASE
WHEN nrfact IN (102, 105, 203, 206) THEN 0.05
WHEN nrfact IN (104, 107, 207, 210) THEN 0.10
ELSE 0.19
END;
SELECT * From facturi_DEF;
SELECT nrfact, clienti_DEF.codcl, dencl, valoare, cota_tva, valoare*(1+cota_tva)
FROM clienti_DEF,facturi_DEF
WHERE clienti_DEF.codcl=facturi_DEF.codcl(+)
ORDER BY 2,4;
SELECT nrfact, clienti_DEF.codcl, dencl, NVL(valoare,0) AS valnoua, NVL(cota_tva,0) AS cota_noua,
valnoua*(1+cota_noua) AS Valoare_cu_TVA
FROM clienti_DEF LEFT JOIN facturi_DEF ON clienti_DEF.codcl=facturi_DEF.codcl
ORDER BY 2,4;
SELECT nrfact, clienti_DEF.codcl, dencl, NVL(valoare,0) AS valnoua, NVL(cota_tva,0) AS cota_noua,
valnoua*(1+NVL(cota_tva,0)) AS Valoare_cu_TVA
FROM clienti_DEF LEFT JOIN facturi_DEF ON clienti_DEF.codcl=facturi_DEF.codcl
ORDER BY 2,4;
SELECT nrfact, clienti_DEF.codcl, dencl, NVL(valoare,0) AS valnoua, NVL(cota_tva,0) AS cota_noua,
NVL(valoare,0)*(1+NVL(cota_tva,0)) AS Valoare_cu_TVA
FROM clienti_DEF LEFT JOIN facturi_DEF ON clienti_DEF.codcl=facturi_DEF.codcl
ORDER BY 2,4;
OBS: seminarul trecut am vazut ca noul nume al unui camp calculat nu poate fi folosit in conditiile de filtrare.
Conform exemplelor de mai sus, noul nume nu poate fi utilizat nici in calculul unui alt camp.
5. Grupari pe camp calculat
- totalul general – NU contine nicio grupare, deci NU are nevoie de optiunea GROUP BY
SELECT SUM(valoare*(1+cota_tva)) AS Total_brut_general
FROM facturi_DEF;
- subtotaluri – presupun obtinerea de valori partiale, pe subgrupuri obtinute prin gruparea in functie de
valorile unuia sau mai multor campuri; de exemplu subtotaluri lunare; in aceasta situatie se poate pune in
discutie si un anumit criteriu de ordonare
OBS: daca se doreste ordonare descrescatore la fiecare criteriu, optiunea DESC trebuie precizata la fiecare camp.
- Combinatia grupare – filtrare pe camp calculat– clientii cu total facturi peste 10000
OBSERVATII
- Filtrarea din clauza WHERE actioneaza inaintea gruparii datelor iar filtrarea din clauza HAVING actioneaza
dupa ce se fac gruparile;
- Se pot utiliza la filtrarea datelor inaintea gruparii, adica in WHERE, atat campuri care apar in SELECT, cat si
campuri care nu apar in SELECT intrucat, din cauza eterogenitatii valorilor lor, ar face ca gruparea sa nu se
realizeze. In exemplul de mai sus se observa ca datafact nu apare intre campurile SELECT, ea fiind utilizata
doar ca si criteriu de filtrare.
6. Grupari, calcule, subinterogari
SELECT MAX(valoare) AS Maxim_facturi, ROUND(AVG(valoare),2) AS Medie_facturi
FROM facturi_DEF;
OBS: NU avem GROUP BY intrucat sunt doar valori calculate pentru intreaga coloana de valori.
- Utilizarea lui MAX
Sa se determine factura cu valoarea cea mai mare si sa se afiseze clientul / clientii care are / au facturi cu
aceasta valoare.
OBS: maximul general este maximul maximelor fiecarui client. Maximul calculat mai sus se va utiliza in
subinterogare
- intrucat e o dubla grupare, campul localit trebuie sa dispara din SELECT dar trebuie sa ramana in GROUP
BY intrucat gruparea dupa localitate este cea care da totalurile partiale.
Obs: utilizarea tabelei clienti_DEF este necesara doar pentru ca se face gruparea dupa campul localit
- utilizarea celei de-a doua interogari ca subinterogare in prima interogare; intrucat filtrarea se face pe
campul SUM, conditia de filtrare se pune in clauza HAVING
OBS: subinterogarea de mai sus poate fi valorificata mai bine daca se doreste afisarea localitatilor care au un volum
de vanzari mai mare de 50% din cel mai mare volum de vanzari, ordonate descrescator in functie de aceste valori.
Sa se determine si sa se afiseze lunile care au totalul facturilor mai mare decat media acestor totaluri.
Obs: intrucat media s-a utilizat doar pentru comparare, nu fost necesara rotunjirea acesteia la doua zecimale.
TEMA:
- ADAUGAREA IN TABELA incasari_DEF A UNUI CAMP NUMIT TRIMESTRU AL CARUI CONTINUT SA FIE
COMPLETAT AUTOMAT CU CUVINTELE primul, al doilea, al treilea, al patrulea IN FUNCTIE DE LUNA DATEI
INCASARII
- 5 INSTRUCTIUNI SELECT CAT MAI INEDITE, FOLOSIND GRUPARI, DUBLE GRUPARI, FILTRARI PENTRU
DIVERSE CAMPURI EXISTENTE SAU CALCULATE, DIN TOATE CELE 3 TABELE.
Astept raspunsurile intr-un document WORD atat instructiunile cat si capturi ale executiei acestora.
Documentul se va incarca pe platforma, in sectiunea dedicata.
Termen: 03.04.2023
Laborator 5
FILTRARI, GRUPARI, SUBINTEROGARI, ALIAS, PROCEDURI
1. TABELELE INITIALE
Crearea tabelelor se regaseste in script.
2. INSERAREA DATELOR
Se pot utiliza pentru a simplifica scrierea unor interogari complexe in care sunt implicate mai multe tabele
Legatura intre aliasuri si denumirea tabelelor se realizeaza O SINGURA DATA, in clauza FROM, aliasurile putand fi
utilizate oriunde in SELECT, atat inainte cat si dupa FROM
SELECT empno, ename, a.deptno, dname
FROM emp a, dept b
WHERE a.deptno=b.deptno;
Acelasi lucru cu INNER JOIN
Folosind aliasuri nu mai trebuie acordata atentie situatiei in care campul apare in mai multe tabele, putandu-se folosi
denumirea tabelului la fiecare camp ales in SELECT.
Acest aspect ajuta in special in instructiunele SELECT mai complexe, in care sunt implicate date din mai multe tabele.
Instructiunea de mai sus se poate scrie si astfel.
SELECT a.empno, a.ename, a.deptno, b.dname
FROM emp a INNER JOIN dept b ON a.deptno=b.deptno;
Un alt mare avantaj al utilizarii aliasurilor este posibilitatea scrierii de interogari de tip SELF JOIN adica de stabilire a
unei legaturi dintre un tabel si el insusi.
BEGIN
SELECT COUNT(e.empno),e.mgr,m.ename,m.job INTO v_nr_sbd,v_cod_mgr,v_nume_mgr,v_fct_mgr
FROM emp e INNER JOIN emp m ON e.mgr = m.empno
WHERE e.mgr=7698
GROUP BY e.mgr, m.ename, m.job;
DBMS_OUTPUT.PUT_LINE ('Cod manager '||v_cod_mgr);
DBMS_OUTPUT.PUT_LINE ('Nume manager '||v_nume_mgr);
DBMS_OUTPUT.PUT_LINE ('Functie manager '||v_fct_mgr);
DBMS_OUTPUT.PUT_LINE ('Numar subordonati '||v_nr_sbd);
END;
/
- Transformarea procedurii anterioare in procedura stocata.
CREATE OR REPLACE PROCEDURE afis_sbd IS
v_nr_sbd NUMBER;
v_cod_mgr emp.mgr%TYPE;
v_nume_mgr emp.ename%TYPE;
v_fct_mgr emp.job%TYPE;
BEGIN
SELECT COUNT(e.empno),e.mgr,m.ename,m.job INTO v_nr_sbd,v_cod_mgr,v_nume_mgr,v_fct_mgr
FROM emp e INNER JOIN emp m ON e.mgr = m.empno
WHERE e.mgr=7698
GROUP BY e.mgr, m.ename, m.job;
DBMS_OUTPUT.PUT_LINE ('Cod manager '||v_cod_mgr);
DBMS_OUTPUT.PUT_LINE ('Nume manager '||v_nume_mgr);
DBMS_OUTPUT.PUT_LINE ('Functie manager '||v_fct_mgr);
DBMS_OUTPUT.PUT_LINE ('Numar subordonati '||v_nr_sbd);
END;
/
Procedura se compileaza si se stocheaza iar pentru executarea ei este nevoie de instructiunea
EXECUTE afis_sbd;
- Transformarea procedurii anterioare in procedura stocata cu parametru
CREATE OR REPLACE PROCEDURE afis_sbd_p (p_cod NUMBER) IS
v_nr_sbd NUMBER;
v_cod_mgr emp.mgr%TYPE;
v_nume_mgr emp.ename%TYPE;
v_fct_mgr emp.job%TYPE;
BEGIN
SELECT COUNT(e.empno),e.mgr,m.ename,m.job INTO v_nr_sbd,v_cod_mgr,v_nume_mgr,v_fct_mgr
FROM emp e INNER JOIN emp m ON e.mgr = m.empno
WHERE e.mgr=p_cod
GROUP BY e.mgr, m.ename, m.job;
DBMS_OUTPUT.PUT_LINE ('Cod manager '||v_cod_mgr);
DBMS_OUTPUT.PUT_LINE ('Nume manager '||v_nume_mgr);
DBMS_OUTPUT.PUT_LINE ('Functie manager '||v_fct_mgr);
DBMS_OUTPUT.PUT_LINE ('Numar subordonati '||v_nr_sbd);
END;
/
Parametrul se precizeaza in denumirea procedurii iar in corpul procedurii el se poate utiliza in filtrari, calcule.
EXECUTE afis_sbd_p(7698);
EXECUTE afis_sbd_p(7566);
EXECUTE afis_sbd_p(7839);
La comunicarea unui cod gresit, fie ca nu exista (7200), fie ca nu are functie de manager (7499) apare eroarea de
mai jos.
EXECUTE afis_sbd_p(7200);
EXECUTE afis_sbd_p(7499);
BEGIN
SELECT COUNT(e.empno),e.mgr,m.ename,m.job INTO v_nr_sbd,v_cod_mgr,v_nume_mgr,v_fct_mgr
FROM emp e INNER JOIN emp m ON e.mgr = m.empno
WHERE e.mgr=p_cod
GROUP BY e.mgr, m.ename, m.job;
END;
/
EXECUTE afis_sbd_p_err(7839);
EXECUTE afis_sbd_p_err(7200);
EXECUTE afis_sbd_p_err(7499);
DECLARE
codpersoana NUMBER;
BEGIN
codpersoana := &dati_codul_persoanei;
afis_sbd_p_err(codpersoana);
END;
/
Laborator 6
Alte exemple de interogari si proceduri bazate pe ele.
Se va crea o noua structura tabelara si se va completa cu date
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;
/
Obs:
- din date se observa ca exista studenti care nu au sustinut toate examenele intr-o anumita sesiune;
- studentul cu matricola 60 nu a sustinut niciun examen; la disciplina 330 nu s-au sustinut exemene.
- am pus si examene sustinute dar la care a fost nota 4; tabela de examinari are cheie primara distincta ceea
ce permite posibilitatea reexaminarii.
- prima cifra din codul disciplinei (1, 2 sau 3) se refera la anul in care se studiaza materia; am pus cate 2 materii
in fiecare an de studiu.
3. CERINTE DE LUCRU
EXECUTE afis_max_p(20);
EXECUTE afis_max_p(40);
SELECT MAX(COUNT(matr_st))
FROM ex_XY
WHERE nota>4
GROUP BY matr_st;
PORNIND DE LA A 2-A INTEROGARE, SA SE CREEZE O PROCEDURA STOCATA PENTRU A AFISA SITUATIA UNUI
STUDENT PENTRU CARE SE COMUNICA NUMARUL MATRICOL.
BEGIN
EXECUTE afis_sstd;
TRANSFORMAREA PROCEDURII IN PROCEDURA CU PARAMENTRU DE INTRARE
BEGIN
SELECT stud_XY.matr_st, nume_st, spec,
ROUND(AVG(nota),2),
COUNT(ex_XY.matr_st)
INTO v_matr_st, v_nume_st, v_spec_st, v_medie, v_nr_ex
FROM stud_XY INNER JOIN ex_XY ON stud_XY.matr_st=ex_XY.matr_st
WHERE nota>4 AND stud_XY.matr_st=p_matr
GROUP BY stud_XY.matr_st, nume_st, spec;
DBMS_OUTPUT.PUT_LINE ('Matricola student: '||v_matr_st);
DBMS_OUTPUT.PUT_LINE ('Nume student: '||v_nume_st);
DBMS_OUTPUT.PUT_LINE ('Specializare: '||v_spec_st);
DBMS_OUTPUT.PUT_LINE ('Media: '||v_medie);
DBMS_OUTPUT.PUT_LINE ('Numar examene: '||v_nr_ex);
END;
/
EXECUTE afis_sstd_p(30);
EXECUTE afis_sstd_p(&dati_matricola);
Laborator 7
Proceduri, exceptie si functie. Utilizare parametru de iesire. Definire si utilizare cursor.
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;
/
3. Determinarea si afisarea sumei creditelor obtinute la o anumita disciplina de catre toti studentii
SELECT disc_XY.cod_disc, den_disc, SUM(nr_credite) AS totalcredite
FROM disc_XY INNER JOIN ex_XY ON disc_XY.cod_disc=ex_XY.cod_disc
WHERE nota>4
GROUP BY disc_XY.cod_disc, den_disc
ORDER BY 1;
-LIMITAREA LA O INREGISTRARE
SELECT disc_XY.cod_disc, den_disc, SUM(nr_credite) AS totalcredite
FROM disc_XY INNER JOIN ex_XY ON disc_XY.cod_disc=ex_XY.cod_disc
WHERE nota>4 AND disc_XY.cod_disc=120
GROUP BY disc_XY.cod_disc, den_disc
ORDER BY 1;
-ACTIVAREA AFISARII REZULTATELOR PROCEDURILOR
SET SERVEROUTPUT ON;
-PORNIND DE LA ACEASTA INTEROGARE, VOM CREA PROCEDURI A CAROR COMPLEXIATAE VA CRESTE GRADUAL
-procedura nestocata
DECLARE
v_cod_disc disc_XY.cod_disc%TYPE;
v_den_disc disc_XY.den_disc%TYPE;
v_total NUMBER;
BEGIN
SELECT disc_XY.cod_disc, den_disc, SUM(nr_credite) INTO v_cod_disc, v_den_disc, v_total
FROM disc_XY INNER JOIN ex_XY ON disc_XY.cod_disc=ex_XY.cod_disc
WHERE nota>4 AND disc_XY.cod_disc=120
GROUP BY disc_XY.cod_disc, den_disc
ORDER BY 1;
DBMS_OUTPUT.PUT_LINE ('La disciplina cu codul '||v_cod_disc||' denumita '||v_den_disc||' s-au obtinut
'||v_total||' credite');
END;
/
-transformarea in procedura stocata
EXECUTE calc_crdt1;
-transformarea in procedura stocata cu parametru
CREATE OR REPLACE PROCEDURE calc_crdt1_p (p_cod disc_XY.cod_disc%TYPE) IS
v_cod_disc disc_XY.cod_disc%TYPE;
v_den_disc disc_XY.den_disc%TYPE;
v_total NUMBER;
BEGIN
SELECT disc_XY.cod_disc, den_disc, SUM(nr_credite) INTO v_cod_disc, v_den_disc, v_total
FROM disc_XY INNER JOIN ex_XY ON disc_XY.cod_disc=ex_XY.cod_disc
WHERE nota>4 AND disc_XY.cod_disc=p_cod
GROUP BY disc_XY.cod_disc, den_disc
ORDER BY 1;
DBMS_OUTPUT.PUT_LINE ('La disciplina cu codul '||v_cod_disc||' denumita '||v_den_disc||' s-au obtinut
'||v_total||' credite');
END;
/
-apelare directa
EXECUTE calc_crdt1_p(110);
EXECUTE calc_crdt1_p(&dati_codul);
DECLARE
v_slct_cod disc_XY.cod_disc%TYPE;
BEGIN
v_slct_cod:=&dati_codul;
DBMS_OUTPUT.PUT_LINE ('Situatia disciplinei cu codul '||v_slct_cod);
calc_crdt1_p(v_slct_cod);
END;
/
-OBS - numele variabilelor, parametrilor din procedura apelanta nu sunt legate de denumirile variabilelor si
parametrilor din procedura apelata
-sa se modifice procedura de mai sus, astfel incat sa cuprinda si situatia in care este comunicat un cod gresit.
DECLARE
v_slct_cod disc_XY.cod_disc%TYPE;
BEGIN
v_slct_cod:=&dati_codul;
DBMS_OUTPUT.PUT_LINE ('Situatia disciplinei cu codul '||v_slct_cod);
calc_crdt1_p_ex(v_slct_cod);
END;
/
-transformarea procedurii calc_crdt1_p in functie si utilizarea informatiei pe care o returneaza functia
CREATE OR REPLACE FUNCTION f_calc_crdt1_p (p_cod disc_XY.cod_disc%TYPE) RETURN NUMBER IS
v_cod_disc disc_XY.cod_disc%TYPE;
v_den_disc disc_XY.den_disc%TYPE;
v_total NUMBER;
BEGIN
SELECT disc_XY.cod_disc, den_disc, SUM(nr_credite) INTO v_cod_disc, v_den_disc, v_total
FROM disc_XY INNER JOIN ex_XY ON disc_XY.cod_disc=ex_XY.cod_disc
WHERE nota>4 AND disc_XY.cod_disc=p_cod
GROUP BY disc_XY.cod_disc, den_disc
ORDER BY 1;
DBMS_OUTPUT.PUT_LINE ('La disciplina cu codul '||v_cod_disc||' denumita '||v_den_disc||' s-au obtinut
'||v_total||' credite');
RETURN v_total;
END;
/
-apelarea functiei se poate face doar dintr-o procedura sau alta functie si presupune definirea unei variabile care
sa preia rezultatul returnat de functie, in situatia aceasta totalul de credite.
DECLARE
v_slct_cod disc_XY.cod_disc%TYPE;
v_prel_tot NUMBER;
BEGIN
v_slct_cod:=&dati_codul;
DBMS_OUTPUT.PUT_LINE ('Situatia disciplinei cu codul '||v_slct_cod);
v_prel_tot:=f_calc_crdt1_p(v_slct_cod);
DBMS_OUTPUT.PUT_LINE ('Aici se afiseaza totalul de '||v_prel_tot||' credite returnat de functie');
END;
/
-daca se doreste ca rezultatul totalului de credite sa fie extras din procedura, este necesar ca procedura sa aiba
parametru de iesire; punctul de pornire va fi tot procedura calc_crdt1_p
DECLARE
v_slct_cod disc_XY.cod_disc%TYPE;
v_prel_tot NUMBER;
BEGIN
v_slct_cod:=&dati_codul;
DBMS_OUTPUT.PUT_LINE ('Situatia disciplinei cu codul '||v_slct_cod);
calc_crdt1_p_io(v_slct_cod,v_prel_tot);
DBMS_OUTPUT.PUT_LINE ('Aici se afiseaza totalul de '||v_prel_tot||' credite returnat de procedura cu parametru
de iesire');
END;
/
EXECUTE calc_crdt1_cs;
TEMA
SA SE SCRIE O INTEROGARE CARE SA AFISEZE
SA SE AFISEZE ACEASTA SITUATIE UTILIZAND O PROCEDURA STOCATA CU CURSOR, CONFORM MODELULUI DIN
SEMINAR.
PORNIND TOT DE LA INTEROGAREA INITIALA, SA SE TRANSFORME IN INTEROGARE PENTRU O DISCIPLINA IAR APOI
SA SE CONSTRUIASCA PROGRESIV PROCEDURILE DE AFISARE CU PARAMETRU, CU FUNCTIE, CONFORM
SEMINARULUI, PRECUM SI PROCEDURILE ANONIME DE APELARE ALE ACESTORA.
SUPLIMENTAR, LA VARIANTA CU PARAMETRU DE IESIRE SAU LA VARIANTA CU FUNCTIE, IN UNA DIN PROCEDURILE
APELANTE SA SE AFISEZE, DUPA CAZ, MESAJUL
TERMEN 30.04.2023!!
Laborator 8
Alte modalitati de utilizare a cursorului in proceduri si functii.
Obs:
- prima cifra din codul disciplinei (1, 2 sau 3) se refera la anul in care se studiaza materia; am pus cate 2 materii
in fiecare an de studiu.
SET SERVEROUTPUT ON;
3. Alte variante de implementare a cursorului
- procedura stocata cu cursor – varianta 2
CREATE OR REPLACE PROCEDURE calc_crdt1_cs2 IS
CURSOR c IS
SELECT disc_XY.cod_disc, den_disc, SUM(nr_credite)
FROM disc_XY INNER JOIN ex_XY ON disc_XY.cod_disc=ex_XY.cod_disc
WHERE nota>4
GROUP BY disc_XY.cod_disc, den_disc
ORDER BY 1;
v_cod_disc disc_XY.cod_disc%TYPE;
v_den_disc disc_XY.den_disc%TYPE;
v_total NUMBER;
BEGIN
DBMS_OUTPUT.PUT_LINE ('Cod disciplina Denumire disciplina Numar credite');
OPEN c;
LOOP
FETCH c INTO v_cod_disc, v_den_disc, v_total;
EXIT WHEN c%NOTFOUND;
DBMS_OUTPUT.PUT_LINE (' '||v_cod_disc||' '||v_den_disc||' '||v_total);
END LOOP;
CLOSE c;
END;
/
EXECUTE calc_crdt1_cs2;
- procedura stocata cu cursor – varianta 3
4. Uilizarea unei functii in care se adauga un camp denumit an_st, precum si calcularea unui total al creditelor la
sfarsitul tabelului; de asemenea se vor adauga si linii grafice de separare a informatiilor. Totalul creditelor se
va utiliza ulterior in procedura apelanta, pentru a calcula o valoare medie a creditelor pe fiecare disciplina.
Se va utiliza functia SUBSTR a carei sintaxa este SUBSTR(string, start_position [, length ])
DBMS_OUTPUT.PUT_LINE ('-----------------------------------------------------------------------');
DBMS_OUTPUT.PUT_LINE ('Cod disciplina Denumire disciplina Numar credite An studiu');
DBMS_OUTPUT.PUT_LINE ('-----------------------------------------------------------------------');
FOR i IN c LOOP
DECLARE
v_prel_tot_cr NUMBER;
v_nrdisc NUMBER;
v_med NUMBER;
BEGIN
v_prel_tot_cr:=f_calc_crdt1_cs_tot;
DBMS_OUTPUT.PUT_LINE ('Total credite '||v_prel_tot_cr);
DBMS_OUTPUT.PUT_LINE ('-----------------------------------------------------------------------');
SELECT COUNT(DISTINCT cod_disc) INTO v_nrdisc
FROM ex_XY;
v_med:=ROUND(v_prel_tot_cr/v_nrdisc,2);
DBMS_OUTPUT.PUT_LINE ('Medie '||v_med);
END;
/
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;
/
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.
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
EXECUTE list_inc;
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.
Laborator 10
Alte exemple de blocuri de proceduri si functii. Utilizarea unor variabile de tip obiect predefinit.
Vom realiza diverse proceduri si functii, deci avem nevoie de activarea afisarii.
SET SERVEROUTPUT ON;
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;
/
3. Crearea si utilizarea comparativa a unei proceduri cu doi parametrii de iesire versus o functie cu un
parametru de iesire.
Interogari pregatitoare
SELECT EXTRACT(MONTH FROM data_cursa) AS luna, SUM(incasari), COUNT(id_cursa)
FROM curse_XY
GROUP BY EXTRACT(MONTH FROM data_cursa);
SELECT EXTRACT(MONTH FROM data_cursa) AS luna, SUM(incasari), COUNT(id_cursa)
FROM curse_XY
GROUP BY EXTRACT(MONTH FROM data_cursa)
HAVING EXTRACT(MONTH FROM data_cursa)=1;
SELECT SUM(incasari), COUNT(id_cursa)
FROM curse_XY
GROUP BY EXTRACT(MONTH FROM data_cursa)
HAVING EXTRACT(MONTH FROM data_cursa)=1;
Preluarea interogarii in functie de unde incercam sa returnam doua valori
CREATE OR REPLACE FUNCTION sit_lun_f1 (p_luna NUMBER) RETURN NUMBER AS
v_tot_inc NUMBER;
v_nrc NUMBER;
BEGIN
SELECT SUM(incasari), COUNT(id_cursa) INTO v_tot_inc,v_nrc
FROM curse_XY
GROUP BY EXTRACT(MONTH FROM data_cursa)
HAVING EXTRACT(MONTH FROM data_cursa)=p_luna;
RETURN v_tot_inc;
RETURN v_nrc;
END;
/
Utilizarea functiei
DECLARE
v_prel_luna NUMBER;
v1 NUMBER;
v2 NUMBER;
BEGIN
v_prel_luna:=&dati_luna;
v1:=sit_lun_f1(v_prel_luna);
v2:=sit_lun_f1(v_prel_luna);
DBMS_OUTPUT.PUT_LINE ('Totalul lunii '||v_prel_luna||' este '||v1||' iar numarul de curse este '||v2);
END;
/
CREATE OR REPLACE FUNCTION sit_lun_f2 (p_luna NUMBER, p_nrc OUT NUMBER) RETURN NUMBER AS
v_tot_inc NUMBER;
BEGIN
SELECT SUM(incasari), COUNT(id_cursa) INTO v_tot_inc,p_nrc
FROM curse_XY
GROUP BY EXTRACT(MONTH FROM data_cursa)
HAVING EXTRACT(MONTH FROM data_cursa)=p_luna;
RETURN v_tot_inc;
END;
/
Utilizarea functiei
DECLARE
v_prel_luna NUMBER;
v1 NUMBER;
v2 NUMBER;
BEGIN
v_prel_luna:=&dati_luna;
v1:=sit_lun_f2(v_prel_luna, v2);
DBMS_OUTPUT.PUT_LINE ('Totalul lunii '||v_prel_luna||' este '||v1||' iar numarul de curse este '||v2);
END;
/
O alta metoda prin care se pot obtine doua sau mai multe valori din apelarea unei functii, este prin definirea unui
nou tip de variabila obiect care sa incapsuleze in campuri distincte aceste valori.
Aceasta functie poate fi utilizata suucesiv, prin apelare dintr-un cursor, pentru a calcula aceste informatii pentru
fiecare luna.
DECLARE
CURSOR c_luna IS
SELECT EXTRACT(MONTH FROM data_cursa) AS luna
FROM curse_XY
GROUP BY EXTRACT(MONTH FROM data_cursa)
ORDER BY 1;
v1_2 OB_INF;
BEGIN
DBMS_OUTPUT.PUT_LINE ('Luna Suma Nr_curse');
DBMS_OUTPUT.PUT_LINE ('------------------------------------');
FOR i IN c_luna LOOP
v1_2:=sit_lun_f3(i.luna);
DBMS_OUTPUT.PUT_LINE (' '||i.luna||' '||v1_2.v_ob1||' '||v1_2.v_ob2);
END LOOP;
END;
/
DECLARE
CURSOR c_luna IS
SELECT EXTRACT(MONTH FROM data_cursa) AS luna
FROM curse_XY
GROUP BY EXTRACT(MONTH FROM data_cursa)
ORDER BY 1;
v1_2 OB_INF;
v_nluna VARCHAR2(15);
BEGIN
DBMS_OUTPUT.PUT_LINE (' Luna Suma Nr_curse');
DBMS_OUTPUT.PUT_LINE ('--------------------------------------------');
FOR i IN c_luna LOOP
v1_2:=sit_lun_f3(i.luna);
v_nluna:=TO_CHAR(TO_DATE(i.luna, 'MM'), 'MONTH','NLS_DATE_LANGUAGE = romanian');
DBMS_OUTPUT.PUT_LINE (' '||v_nluna||' '||v1_2.v_ob1||' '||v1_2.v_ob2);
END LOOP;
END;
/
Punrea in evidenta a functionarii trigger-ului, prin realizarea unor operatiuni de adaugare/stergere, respectiv
modificare.
LEFT JOIN
(SELECT ctl_XY.cod_p, den_prod, tip_op, SUM(cant) AS Total_vanz
FROM ctl_XY INNER JOIN detalii_misc_XY ON ctl_XY.cod_p=detalii_misc_XY.cod_p
GROUP BY ctl_XY.cod_p, den_prod, tip_op
HAVING UPPER (tip_op)='V'
ORDER BY 1) tv
ON ta.cod_p=tv.cod_p;
- 4c) subinterogari
- toate aprovizionarile cu pretul sub media preturilor de aprovizionare
- subinterogarea trebuie sa returneze doar o valoare
- testarea subinterogarii
SELECT AVG(pret)
FROM detalii_misc_XY
WHERE UPPER (tip_op)='A';
- utilizarea subinterogarii intr-o selectie simpla
-stabilirea categoriei pentru care totalul valoric al aprovizionarilor este cel mai mare
- testare subinterogarii
SELECT SUBSTR(cod_p,1,1), tip_op, SUM(cant*pret)
FROM detalii_misc_XY
WHERE UPPER(tip_op)='A'
GROUP BY SUBSTR(cod_p,1,1),tip_op
ORDER BY SUBSTR(cod_p,1,1);
- filtrarea doar a unei valori si anume a maximului
SELECT SUBSTR(cod_p,1,1), tip_op, MAX(SUM(cant*pret))
FROM detalii_misc_XY
WHERE UPPER(tip_op)='A'
GROUP BY SUBSTR(cod_p,1,1),tip_op;
BEGIN
SELECT categ, tip_op, SUM(cant*pret) INTO v_categ,v_tip_op,v_suma
FROM ctl_XY INNER JOIN detalii_misc_XY ON ctl_XY.cod_p=detalii_misc_XY.cod_p
WHERE UPPER(tip_op)='A'
GROUP BY categ, tip_op
HAVING SUM(cant*pret)=(SELECT MAX(SUM(cant*pret))
FROM detalii_misc_XY
WHERE UPPER(tip_op)='A'
GROUP BY SUBSTR(cod_p,1,1),tip_op)
;
2) Pornind de la prima si a treia interogare a punctului 4c), scrieti o procedura fara parametru, cu cursor,
care sa afiseze urmatoarea situatie.
Laborator 13
Recapitulare finala partea 2. Functii, proceduri, parametrii. Apelarea acestora.
1. Definirea tabelelor
Crearea tabelelor se regaseste in script.
2. Adaugarea datelor
Popularea tabelelor cu date se face se
realizeazain ordinea „parinti” „copii”.
BEGIN
Pentru a adauga datele mai rapid, instructiunile au fost
incadrate intr-o procedura.
END;
/
OBS:
- produsul cu codul 32 exista doar in tabela catalog iar produsul cu codul 31 doar s-a achizitionat
UPDATE ctl_XY
SET categ=
CASE
WHEN SUBSTR(cod_p,1,1) ='1' THEN 'alimente'
WHEN SUBSTR(cod_p,1,1) ='2' THEN 'electronice'
WHEN SUBSTR(cod_p,1,1) ='3' THEN 'jucarii'
END;
Activarea afisarii.
SET SERVEROUTPUT ON;
3. Functia si apelarea ei
- 3a) functii cu parametri
Testare SELECT
DECLARE
v_expl misc_XY.explicatii%TYPE;
v_prel_tot1 NUMBER :=0;
v_prel_tot2 NUMBER :=0;
v_prel_nrl NUMBER :=0;
BEGIN
v_expl:='&Dati_factura';
v_prel_tot1:=calc_fact_XY1(v_expl);
v_prel_tot2:=calc_fact_XY2(v_expl,v_prel_nrl);
IF v_prel_tot1>0 THEN
DBMS_OUTPUT.PUT_LINE('Factura '||v_expl||' are totalul '||v_prel_tot1);
DBMS_OUTPUT.PUT_LINE('Factura '||v_expl||' are totalul '||v_prel_tot2||' si numarul de linii '||v_prel_nrl);
ELSE
DBMS_OUTPUT.PUT_LINE('Factura inexistenta!!');
END IF;
END;
/
- 3c) imbunatatirea procedurii prin afisarea liniilor facturii si utilizarea celei de-a doua functii pentru afisarea
informatiilor despre fiecare factura
Testare SELECT
SELECT ctl_XY.cod_p AS cod, den_prod AS den, cant, pret, cant*pret AS val
FROM ctl_XY INNER JOIN detalii_misc_XY ON ctl_XY.cod_p = detalii_misc_XY.cod_p INNER JOIN misc_XY ON
detalii_misc_XY.cod_misc = misc_XY.cod_misc
WHERE UPPER(explicatii) = 'FACT1';
Transpunere SELECT in cursor
CREATE OR REPLACE PROCEDURE sit_fact_XY1(p_proc_expl misc_XY.explicatii%TYPE) AS
v_prel_tot NUMBER :=0;
v_prel_nrl NUMBER :=0;
CURSOR c_linie IS
SELECT ctl_XY.cod_p AS cod, den_prod AS den , cant, pret, cant*pret AS val
FROM ctl_XY INNER JOIN detalii_misc_XY ON ctl_XY.cod_p = detalii_misc_XY.cod_p INNER JOIN misc_XY ON
detalii_misc_XY.cod_misc = misc_XY.cod_misc
WHERE UPPER(explicatii) = UPPER(p_proc_expl);
BEGIN
v_prel_tot:=calc_fact_XY2(p_proc_expl,v_prel_nrl);
IF v_prel_tot>0 THEN
DBMS_OUTPUT.PUT_LINE('Factura '||p_proc_expl||' are totalul '||v_prel_tot||' si numarul de linii '||v_prel_nrl);
DBMS_OUTPUT.PUT_LINE('---------------------------------------------------------------------');
DBMS_OUTPUT.PUT_LINE('Cod produs Denumire Cantitate Pret Valoare');
DBMS_OUTPUT.PUT_LINE('---------------------------------------------------------------------');
FOR i IN c_linie LOOP
DBMS_OUTPUT.PUT_LINE(' '||i.cod||' '||i.den||' '||i.cant||' '||i.pret||' '||i.val);
END LOOP;
DBMS_OUTPUT.PUT_LINE('================================================================');
ELSE
DBMS_OUTPUT.PUT_LINE('Factura inexistenta!!');
END IF;
END;
/
Apelarea procedurii-varianta 1
EXECUTE sit_fact_XY1('&Dati_factura');
Apelarea procedurii-varianta 2 - se comunica de la tastatura doar numarul facturii
EXECUTE sit_fact_XY1('fact'||&dati_nr_facturii);
DECLARE
v_tipop detalii_misc_XY.tip_op%TYPE;
v_operatie VARCHAR2(30);
BEGIN
v_tipop:=UPPER('&A_sau_V');
CASE v_tipop
WHEN 'A' THEN v_operatie:='APROVIZIONARI';
WHEN 'V' THEN v_operatie:='VANZARI';
ELSE v_operatie:='OPERATIUNE NECUNOSCUTA';
END CASE;
DBMS_OUTPUT.PUT_LINE ('Situatia de '||v_operatie);
DBMS_OUTPUT.PUT_LINE('-----------------------------------------------');
sit_actXY1(v_tipop);
END;
/
Apelarea unei proceduri ce are si parametrii de iesire nu se mai poate face direct, cu EXECUTE, intrucat este nevoie
cel putin de o variabila care sa preia informatia din parametrul de iesire. De aceea este nevoie cel putin de o
procedura nestocata, in care realizam atat utilzarea raspunsului de la tastatura cat si preluarea informatiei aduse
de parametru de iesire.
DECLARE
v_tipop detalii_misc_XY.tip_op%TYPE;
v_operatie VARCHAR2(30);
v_prel_totgen NUMBER;
BEGIN
v_tipop:=UPPER('&A_sau_V');
CASE v_tipop
WHEN 'A' THEN v_operatie:='APROVIZIONARI';
WHEN 'V' THEN v_operatie:='VANZARI';
ELSE v_operatie:=v_tipop||' OPERATIUNE NECUNOSCUTA';
END CASE;
DBMS_OUTPUT.PUT_LINE ('Situatia de '||v_operatie);
DBMS_OUTPUT.PUT_LINE('-----------------------------------------------');
sit_actXY2(v_tipop, v_prel_totgen);
IF v_prel_totgen>0 THEN
DBMS_OUTPUT.PUT_LINE ('Totalul '||v_operatie||' este '||v_prel_totgen);
END IF;
END;
/
Transformarea procedurii de mai sus intr-o procedura cu cursor care parcurge toate tipurile de operatiuni.
SELECT DISTINCT tip_op
FROM detalii_misc_XY;
DECLARE
CURSOR c_prel IS
SELECT DISTINCT tip_op
FROM detalii_misc_XY;
v_operatie VARCHAR2(30);
v_prel_totgen NUMBER;
BEGIN
FOR j IN c_prel LOOP
CASE UPPER(j.tip_op)
WHEN 'A' THEN v_operatie:='APROVIZIONARI';
WHEN 'V' THEN v_operatie:='VANZARI';
END CASE;
DBMS_OUTPUT.PUT_LINE ('Situatia de '||v_operatie);
DBMS_OUTPUT.PUT_LINE('-----------------------------------------------');
sit_actXY2(UPPER(j.tip_op), v_prel_totgen);
DBMS_OUTPUT.PUT_LINE ('Totalul '||v_operatie||' este '||v_prel_totgen);
DBMS_OUTPUT.PUT_LINE('=============================================');
END LOOP;
END;
/
OBS: instructiunile ELSE..IF...nu mai sunt necesare intrucat nu pot exista alte operatiuni decat A sau V, care sunt
preluate din tabel prin cursor si nu comunicate de la tastatura.