Documente Academic
Documente Profesional
Documente Cultură
Instrucţiunea SELECT în PL/SQL funcţionează doar dacă rezultatul interogării este un singur
tuplu. Situaţia este identică cu SELECT -ul care furnizează o singură înregistrare despre care am
vorbit la interogări. Dacă interogarea returnează mai mult de un tuplu, trebuie să folosim o tabelă
cursor. De exemplu:
Din fericire, un singur tuplu din tabela T1 verifică condiţia ca salarul să fie egal cu 500, şi anume
(BALAJ Maria, 500). Comanda DELETE şterge înregistrarea respectivă, urmând ca INSERT să
o introducă din nou în tabelă, de data asta cu salarul mărit.
Alt exemplu:
DECLARE
v_nr1 NUMBER;
v_nr2 NUMBER;
BEGIN
/* daca primul numar este mai mare ca 1, se inverseaza insereaza o
inregistrare noua in care numerele sunt inversate*/
SELECT nr1,nr2 INTO v_nr1,v_nr2 FROM T2 WHERE nr1>1;
INSERT INTO T2 VALUES (v_nr2,v_nr1);
END;
.
run;
Programele PL/SQL sunt organizate în funcţii, proceduri şi pachete (similare oarecum pachetelor
Java). PL/SQL este bazat pe limbajul de programare Ada şi împarte multe elemente de sintaxă cu
Pascal-ul.
Clauza run execută o declaraţie care crează procedura – nu execută procedura... Pentru a executa
o procedură, este indicat să folosim un bloc PL/SQL în care să invocăm procedura ca o declaraţie
executabilă. De aceea este preferabil NU să folosim blocuri anonime, ci proceduri sau funcţii
denumite.
Execuţia PL/SQL.
Dacă avem un bloc anonim, acesta va fi executat imediat. Dacă utilizăm proceduri şi funcţii,
acest lucru nu se mai întâmplă. Pentru a lansa în execuţie o procedură sau o funcţie, o vom apela
în cadrul unei declaraţii SQL.
declare
2 /* declaratii*/
3 prima_variabila INTEGER;
4 a_doua_variabila VARCHAR2(50);
5 a_treia_variabila DATE;
6 a_patra_variabila BOOLEAN;
7 BEGIN
8 --aici se scriu comenzile efective
9 DBMS_OUTPUT.PUT_LINE('HELLO!');
10 END;
11 /
Observaţii:
DECLARE
...
TYPE t_personal IS RECORD(
Marca personal.marca%TYPE,
Numepren personal.numepren%TYPE,
...
)
rec_personal t_personal;
sau
DECLARE
...
rec_personal personal%ROWTYPE;
Exemplu:
Având tabelele: Facturi (nrfact, datafact) şi Produse (ID, nrfact, denprod, cant, pret) dorim să
numărăm câte produse sunt pe o anume factură specificată prin numărul facturii.
Observaţii:
Lucrul cu cursoare
Se doreşte afişarea numărului de produse pentru fiecare număr de factură în parte. Diferenţa faţă
de exemplul anterior este numărul de înregistrări (multiple, nu o singură valoare).Aşadar, o
instrucţiune SELECT...INTO... poate recupera datele de la (cel mult) un tuplu în variabile
individuale.
Cursoarele permit recuperarea liniilor multiple într-o zonă tampon (buffer) atunci când acestea
sunt deschise utilizându-se comanda OPEN <cursor>. Acestea pot fi traversate secvenţial
utilizându-se comanda FETCH pentru a recupera linii individuale – până când nu mai sunt date,
adică variabila cur_prod%NOTFOUND devine adevărată.
END LOOP;
CLOSE CUR_prod;
END;
/
Executaţi count_dupa_nrfact, adăugând mai multe date tabelei, dacă este necesar.
Cursoare
Un cursor este o variabilă care permite trecerea prin mai multe tupluri ale unei tabele. Putem
scrie un program care să citească şi să proceseze valorile fiecărui tuplu (utilizând un bloc
anonim). Putem, de asemenea, dacă datele sunt salvate într-o tabelă, să actualizăm sau să
ştergem tuplul curent.
Exemplul de mai jos ilustrează un ciclu cu cursor. Acesta utilizează tabela T2, care conţine
perechi de numere întregi. Programul va şterge orice tuplu a cărui prim element este mai mic
decât al doilea, şi va insera inversul tuplului în tabela T2.
1) DECLARE
/* Variabilele de ieşire care vor reţine rezultatele interogării:*/
2) a T2.nr1%TYPE;
3) b T2.nr2%TYPE;
/* Declararea cursorului: */
4) CURSOR T2Cursor IS
5) SELECT nr1, nr2
6) FROM T2
7 WHERE nr1 < nr2;
8
9) BEGIN
10) OPEN T2Cursor;
11) LOOP
/* Regăsirea fiecărei linii ca rezultat al interogării în
variabile PL/SQL */
12) FETCH T2Cursor INTO a, b;
/* Dacă nu mai există înregistrări, ieşirea: */
13) EXIT WHEN T2Cursor%NOTFOUND;
/* Stergerea tuplului curent: */
14) DELETE FROM T2 WHERE CURRENT OF T2Cursor;
/* Insarea tuplului inversat: */
15) INSERT INTO T2 VALUES(b, a);
16) END LOOP;
/* Închiderea cursorului utilizat. */
17) CLOSE T2Cursor;
18) END;
19) .
20) run;
Observaţii:
Linia (1) secţiunea de declarare de variabile.
Linia (2) şi (3) declară variabilele a şi b ca având acelaşi tip cu cel al câmpurilor nr1 şi
nr2 din tabela T2. Deşi ştim că aceste câmpuri sunt de tip INTEGER, este preferabil să
utilizăm opţiunea Type.
Liniile de la (4) la (8) definesc cursorul T2Cursor. Acesta acţionează asupra unui
domeniu definit de o interogare SELECT-FROM-WHERE. Înterogarea selectează doar acele
tupluri din T2 a cărui primă componentă este mai mică decât cea de-a doua componentă.
Linia (9) – începutul secţiunii executabile a programului.
Linia (10) deschide cursorul – un pas esenţial.
Liniile de la (11) la (16) conţin ciclul PL/SQL. Un astfel de ciclu este încadrat între LOOP
şi END LOOP. În corpul ciclului găsim:
o În linia (12) se salvează datele din cursor în variabile. În general, declaraţia FETCH
trebuie să conţină variabile pentru fiecare componentă a tuplului furnizat.
Interogarea dintre liniile (5) şi (7) produce perechi, deci s-au furnizat două
variabile de tipul care trebuia.
o În linia (13), se testează condiţia de ieşire din ciclu. Însemnănatea este evidentă:
%NOTFOUND după numele cursorului este adevărată atunci când nu se mai găsesc
tupluri în cursor.
o În linia (14), DELETE şterge înregistrarea curentă folosind clauza WHERE condiţia
CURRENT OF T1Cursor.
o În linia (15), instrucţiunea INSERT inserează inversul tuplului în tabela T2.
Linia (17) închide cursorul.
Linia (18) închide programul PL/SQL.
Liniile (19) şi (20) forţează programul să se execute.
Aici, <variabila> poate fi orice variabilă, aceasta este locală For-ului şi nu trebuie declarată,
<inceput> şi <final> fiind constante.
Temă: Să se creeze tabelele Facturi (nrfact, datafact) şi Produse (nrcurent, nrfact, denp, cant,
pret, valoare). Să se adauge 3 înregistrări în tabela părinte, pe prima factura 1 înregistrare, pe a
doua 2 iar pe a treia 3 înregistrări. Să se execute cele două proceduri care numără produsele
(prima procedură care necesită ca parametru numărul facturii iar cea de-a doua care afişează
automat pentru toate facturile numărul produselor).