Documente Academic
Documente Profesional
Documente Cultură
Obiective
Introducere
În aceasta lectie veti vedea care sunt diferentele între un cursor implicit si unul explicit. Veti afla
deasemenea când si de ce sa folositi un cursor explicit.
S-ar putea sa aveti nevoie sa folositi un SELECT de mai multe articole in PL/SQL pentru a
parcurge mai multe linii. Pentru a realiza asta trebuie sa declarati si sa controlati cursori expliciti, care
sunt folositi în cicluri, inclusiv ciclul FOR pentru cursori.
Despre cursori
Server-ul Oracle foloseste anumite zone de lucru ,numite zone private SQL ,pentru aexecuta
instructiuni SQL si pentru a stoca informatiile de procesare. Puteti folosi cursorii PL/SQL pentru a numi o
zona privata SQL si pentru a accesa informatiile stocate în ea. Cursorul redirecteaza toate fazele de
procesare.
Cursori expliciti
Folositi cursorii expliciti pentru a procesa fiecare articol returnat de o instructiune SELECT cu
rezultate multiple.
Setul de articole returnat de o interogare cu rezultate multiple se numeste set de rezultate.
Dimensiunea sa este numarul de articole care s+au potrivit criteriului de cautare. Diagrama din arata cum
un cursor explicit marcheaza linia curenta din setul de rezultate. Aceasta permite programului
dumneavoastra sa proceseze fiecare linie, pe rând.
Un program PL/SQL deschide un cursor, proceseaza liniile returnate de interogare, si apoi închide
cursorul. Cursorul marcheaza pozitia curenta intr-un set de rezultate.
Nota: Încarcarea pentru un cursor implicit este o încarcare de vector, si existenta unei a doua linii arunca
exceptia TOO_MANY_ROWS( prea multe linii ). În plus, puteti folosi cursorii expliciti pentru a realiza
încarcari multiplesi pentru a executa , din nou, interogari din zona de lucru deja parcurse.
Controlarea cursorilor expliciti
No
DECLARE EMPT
OPEN FETCH Z CLOSE
Y?
Deschide cursorul
Pointer
Cursor
Pointer
Cursor
Pointer
Cursor
Închide cursorul
Cursor
Declararea cursorului
Sintaxa
Nota: A nu se include clauza INTO în declaratia cursorului ea apare mai târziu în instructiunea FETCH.
Declararea cursorului
Exemplu
DECLARE
CURSOR c1 IS
SELECT empno, ename
FROM emp;
CURSOR c2 IS
SELECT *
FROM dept
WHERE deptno = 10;
DECLARE
v_empno emp.empno%TYPE;
v_ename emp.ename%TYPE;
CURSOR c1 IS
SELECT empno, ename
FROM emp;
Nota: Puteti folosi variabile în interogare, dar trebuie sa le declarati înainte de instructiunea CURSOR.
Deschiderea cursorului
Sintaxa
OPEN nume_cursor
Instructiunea OPEN
Deschide un cursor pentru a executa o interogare si a identifica setul de rezultate, care contine
toate înregistrarile care întrunesc criteriile de cautare. Acum cursorul pointeaza la prima linie din setul de
rezultate.
În sintaxa,
nume_cursor este numele cursorului declarat anterior
Nota: Daca interogarea nu are nici un rezultat atunci când cursorul este deschis, PL/SQL nu arunca
exceptie. Totusi se poate testa starea cursorului dupa fiecare încarcare.
Pentru cursorii declarati folosind clauza FOR UPDATE, instructiunea OPEN blocheaza aceste
înregistrari.
Încarcarea datelor din cursor
Sintaxa
Instructiunea FETCH
Instructiunea FETCH încarca articolele din setul de rezultate câte unul. Dupa fiecare încarcare,
cursorul avanseaza la urmatoarea linie din setul de rezultate.
În sintaxa,
nume_cursor este numele cursorului declarat anterior
variabila este o variabila de iesire
nume_înregistrare este numele înregistrarii în care datele încarcate sunt depuse. Variabila
înregistrare poate fi declarata folosind atributul %ROWTYPE.
Sfaturi
Încarca valorile înregistrarii curente în variabilele de iesire.
Se introduc acelasi numar de variabile în clauza INTO a instructiunii FETCH ca numarul de coloane
de iesire a instructiunii SELECT si se asigura ca tipurile de date sunt compatibile.
Se pozitioneaza fiecare variabila astfel încât sa corespunda coloanelor.
Alternativ, se defineste o înregistarea pentru cursor si referentiaza înregistrarea în clauza FETCH
INTO.
Se testeaza daca cursorul contine linii. Daca o încarcare nu aduce nici o valoare, nu mai sunt articole
de procesat în setul activ si nu sa înregistrat nici o eroare.
Exemple
...
OPEN defined_cursor
LOOP
FETCH defined_cursor INTO defined_variables
EXIT WHEN . . .;
...
Procesează datele încărcate
...
END;
Instructiunea FETCH
Folositi instructiunea FETCH pentru a încarca valorile înregistrarii curente în variabilele de iesire.
Dupa încarcare, puteti utiliza variabilele în alte instructiuni. Pentru fiecare coloana returnata de
interogarea asociata cursorului, trebuie sa fie o valoare corespunzatoare în lista INTO. Deasemenea,
tipurile lor de data trebuie sa fie compatibile.
Închiderea cursorului
Sintaxa
CLOSE cursor_name
În sintaxa,
cursor_name este numele cursorului declarat anterior
Nu încercati sa încarcati date dintr-un cursor dupa ce a fost închis, deoarece va fi aruncata
exceptia INVALID_CURSOR.
...
FOR i IN 1..10 LOOP
FETCH c1 INTO v_empno, v_ename;
....
END LOOP;
CLOSE c1;
END;
Atributul %ISOPEN
Exemplu
Exemplu
Aduceti primii zece angajati unul câte unul.
DECLARE
v_empno emp.empno%TYPE;
v_ename emp.ename%TYPE;
CURSOR c1 IS
SELECT empno, ename
FROM emp;
BEGIN
OPEN c1;
LOOP
FETCH c1 INTO v_empno, v_ename;
EXIT WHEN c1%ROWCOUNT > 10 OR c1%NOTFOUND;
...
END LOOP;
CLOSE c1;
END ;
Nota: Înainte de prima încarcare %NOTFOUND are valoarea NULL. Deci daca FETCH nu se executa cu
succes ciclul nu se mai termina. Pentru siguranta folositi urmatoarea instructiune:
EXIT WHEN c1%NOTFOUND OR c1%NOTFOUND IS NULL;
Daca folositi %ROWCOUNT, adaugati un test pentru cazul când nu exista linii în cursor folosind
atributul %NOTFOUND, pentru ca numaratorul de linii nu este incrementat daca FETCH nu încarca nici
o linie.
Cursori si înregistrari
Procesati înregistrarile din setul activ în mod convenabil încarcând valorile într-
o înregistrare PL/SQL.
Exemplu
...
CURSOR c1 IS
SELECT empno, ename
FROM emp;
emp_record c1%ROWTYPE;
BEGIN
OPEN c1;
...
FETCH c1 INTO emp_record;
Cursori si Înregistrari
Ati vazut deja ca puteti defini înregistrari care sa foloseasca structura coloanelor dintr-o tabela.
Puteti deasemenea defini o înregistrare bazata pe lista coloanelor selectate într-un cursor explicit. Acesta
este un mod convenabil de a procesa liniile setului activ pentru ca le încarcati direct în înregistrare.
Sintaxa
Sfaturi
Nu declarati înregistrarea care controleaza ciclul. Domeniul de valabilitate este numai în
cadrul ciclului.
Testati atributele cursorului în cadrul ciclului daca este necesar.
Folositi parametri pentru cursor, daca sunt necesari, în parantezele ce urmeza dupa numele
cursorului din instructiunea FOR.
Nu folositi cilul FOR pentru cursori atunci când operatiile cursorului trebuie realizate manual.
Nota: Puteti defini o interogare la începutul ciclului. Expresia interogarii reprezinta o instructiune
SELECT, si cursorul este intern pentru ciclul FOR. Pentru ca cursorul nu a fost declarat cu un nume nu
puteti sa-i testati atributele.
Aduce angajatii unul câte unul pâna nu a mai ramas nici un angajat.
Exemplu
DECLARE
CURSOR c1 IS
SELECT empno, ename
FROM emp;
BEGIN
FOR emp_record IN c1 LOOP
-- deschidere şi încărcare implicită
IF emp_record.empno’7839 THEN
...
END LOOP; -- închidere implicită
END ;
Utilizarea ciclului FOR pentru cursori cu subinterogari
BEGIN
FOR emp_record IN (SELECT empno , ename FROM emp ) LOOP
-- deschidere şi încărcare implicită
IF emp_record.empno’7839 THEN
...
END LOOP; -- închidere implicită
END ;
Sumar
Tipuri de cursoare
- Cursoare implicite: Folosite pentru toate instructiunile DML si
interogarile cu un singur articol ca rezultat
- Cursori expliciti: Utilizati pentru interogari ce au ca rezultate
zero, unul, sau mai multe articole
Utilizarea cursorilor expliciti.
Evaluarea starii cursorului folosind atributele cursorilor.
Utilizarea ciclurilor FOR penrtu cursori.
Practice overview
Practice overview
Aceasta parte practica aplica cunostintele despre cursori pentru a procesa un numar de articole
dintr-o tabela si a popula o alta tabela cu rezultate, folosind un ciclu FOR pentru cursori.
Practica 21
1. Creati un bloc PL/SQL care sa determine primii angajati în ordinea salariilor.
a. Introduceti un numar n ca intrare de la utilizator cu un parametru de substitutie PL/SQL.
b. În ciclu, luati ultimele nume si salari a primilor n persoane relativ la salarii din tabela EMP.
c. Puneti numele si salariile în tabela TOP_DOGS.
d. Presupuneti ca nu exista doi angajai cu acelasi salar.
e. Testati o varietate de cazuri speciale cum ar fi: n=0 , când n este mai mare decât numarul de
angajati din tabela EMP. Goliti tabela TOP_DOGS dupa fiecare test.
Va rugam introduceti numarul de angajati din topul celor mai bine platiti angajati:
NAME SALARY
-------------- ---------------
KING 5000
FORD 3000
SCOTT 3000
JONES 2975
BLAKE 2850
2. Considerati cazul în care câtiva angajati au acelasi salar. Daca o persoana este afisata, atunci toate
persoanele cu acelasi salar trebuie deasemenea afisate.
a. De exemplu, daca un utilizator introduce o valoare de doi pentru n, atunci KING, FORD si
SCOTT ar trebui afisati (Acesti angajati sunt uniti pentru cel de-al doilea salariu mare ).
b. Daca utilizatorul introduce o valoare de 3, atunci KING, FORD, SCOTT si JONES trebuie afisati.
c. Stergeti toate înregistrarile din tabela TOP_DOGS si testati practic.
Va rugam introduceti numarul de angajati din topul celor mai bine platiti angajati:
2
NAME SALARY
-------------- ---------------
KING 5000
FORD 3000
SCOTT 3000
Va rugam introduceti numarul de angajati din topul celor mai bine platiti angajati:
3
NAME SALARY
-------------- ---------------
KING 5000
FORD 3000
SCOTT 3000
JONES 2975