Sunteți pe pagina 1din 15

Scrierea cursorilor expliciti

Obiective

La finalul acestei lectii, ar trebui sa puteti sa faceti urmatoarele:


 Sa faceti diferenta între un cursor implicit si unul explicit
 Sa utilizati o variabila de înregistrare Pl/SQL
 Sa scieti un ciclu FOR pentru un cursor

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

Orice secventa de instructiuni SQL executata de Server+ul Oracle are un cursor


asociat cu ea:
 Cursori impliciti: Declarati pentru toate instructiunile DML si
PL/SQL.
 Cursori expliciti: Declarati si denumiti de programator.

Cursori impliciti si expliciti

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.

Tipul cursorului Descriere


Implicit Cursorii impliciti sunt declarati de PL/SQL în mod
implicit pentru toateinstructiunile DML si SELECT-urile
PL/SQL, inclusiv pentru cele care returneaza o singura
înregistrare.
Explicit Pentru interogari care returneaza mai mult de o
înregistrare. Cursorii expliciti sunt declarati si denumiti
de programtor si sunt utilizati prin intermediul unor
instructiuni specifice în actiuni executabile în bloc.
Cursori impliciti
Server-ul Oracle deschide în mod implicit un cursor pentru a procesa fiecare instructiune SQL ce
nu a fost asociata cu un cursor declarat explicit. PL/SQL permite referirea la cei mai recent utilizati
cursori ca cursori SQL.
Nu puteti folosi instructiunile OPEN, FETCH, si CLOSE pentru a controla cursorii SQL, dar
puteti folosi atributele cursorului pentru a obtine informatii legate de cea mai recenta instructiune SQL
executata.

Functiile cursorilor expliciti

7369 SMITH CLERK

7566 JONES MANAGER

Cursor 7788 SCOTT ANALYST Articolul curent


7876 ADAMS
CLERK

7902 FORD ANALYST

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.

Functiile cursorilor expliciti


 Pot procesa articolele returnate de o interogare câte unul
 Marcheaza care este linia curenta ce este procesata
 Permite programatorului sa le controleze manual într-un bloc PL/SQL

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?

 Crează o  Identifică  Încarcă linia  Testează  Elibereaz


zonă SQL setul activ curentă în existenţa ă setul
variabile liniilor activ
 Revine la
FETCH dacă
mai există linii

Curosrii expliciti( continuare )


Acum ca am înteles cursorii, din punct de vedere conceptual, sa revedem pasii necesari pentru a-I
utiliza. Sintaxa pentru fiecare dintre pasi poate fi gasita în urmatoarele pagini.

Controlarea cursorilor expliciti folosind patru comenzi


1. Declarati cursorul ,denumindu-l si definind structura interogarii ce trebuie sa fie realizata în
interiorul lui.
2. Deschideti cursorul. Comanda OPEN executa interogarea si leaga toate variabilele folosite.
Liniile returnate de interogare sunt numite setul activ si sunt acum disponibile pentru
încarcare.
3. Încarcati datele din cursor. Comanda FETCH încarca linia curenta din cursor în variabile.
Fiecare încarcare face cursorul sa se deplaseze la urmatoarea linie din setul activ. Astfel
fiecare încarcare acceseaza o linie diferita returnata de interogare. În diagrama fiecare
încarcare testeaza cursorul pentru a vedea daca mai exista linii disponibile. Daca mai sunt
articole, încarca articolul curent în variabile; altfel închide cursorul.
4. Închide cursorul. Comanda CLOSE distruge setul activ de înregistrari. Acum este posibil sa
redeschidem cursorul pentru a aduce un set activ nou.
Controlarea cursorilor expliciti

Deschide cursorul
Pointer
Cursor

Încarcâ o linie din cursor

Pointer
Cursor

Continuă până când devine gol

Pointer
Cursor

Închide cursorul

Cursor

Cursori expliciti( continuare )


Folositi instructiunile OPEN, FETCH, si CLOSE pentru a controla un cursor. Instructiunea OPEN
executa interogarea asociata cursorului, identifica setul de rezultate, si pozitioneaza cursorul înainte de
prima linie. Instructiunea FETCH aduce înregistrarea curenta si avanseaza cursorul la urmatoarea linie.
Când ultima întregistrare a fost procesata, instructiunea CLOSE dezactiveaza cursorul.

Declararea cursorului

Sintaxa

CURSOR nume_cursor IS instrucţiune_select;

 Nu se include clauza INTO în declaratia cursorului


 Daca este necesara procesarea înregistrarilor într-o anumita ordine clauza
ORDER BY este necesara.

Declararea cursorilor expliciti


Folositi instructiunea CURSOR pentru a declara un cursor explicit. Puteti utiliza variabile în
interiorul interogarii, dar trebuie sa le declarati înainte de instructiunea CURSOR.
În sintaxa:
nume_cursor este un identificator PL/SQL
instructiune_select este o instructiune SELECT fara cluza INTO

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;

Declararea cursorilor expliciti


Aducerea angajatilor unul câte unul.

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

 Deschide cursorul pentru a executa interogarea si a indentifica setul activ.


 Daca interogarea nu returneaza nici o linie, nu este aruncata nici o exceptie.
 Foloseste atributele cursorului pentru a testa iesirea dupa o încarcare.

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

OPEN este o instructiune ce realizeaza urmatoarele operatii:


1. Aloca memorie dinamic pentru o zona context care poate contine, eventual, informatii de
procesare critice.
2. Parcurge instructiunea SELECT.
3. Leaga variabilele de intrare – ceea ce înseamna ca seteaza valorile lor obtinând adresele lor de
memorie.
4. Identifica setul de rezultate – ceea ce înseamna setul de înregistrari ce satisface criteriile de
cautare. Înregistrarile din setul rezultat nu sunt încarcate în variabile când instructiunea OPEN
e executata. Abia instructiunea FETCH încarca înregistrarile.
5. Pozitioneaza pointer+ul chiar înainte de prima linie din setul activ.

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

FETCH nume_cursor INTO [ variabila1 , variabila2, . . . ]


| nume_înregistrare ];

 Încarca valorile înregistrarii curente în variabilele de iesire.


 Se introduc acelasi numar de variabile
 Se pozitioneaza fiecare variabila astfel încât sa corespunda coloanelor
 Se testeaza daca cursorul contine linii

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.

Nota: Instructiunea FETCH realizeaza urmatoarele operatii:


1. Avanseaza pointerul la urmatoarea înregistrare la setul activ.
2. Citeste datele pentru înregistrarea curenta în variabilele PL/SQL de iesire.
3. Iese din ciclul FOR al cursorului daca pointerul este pozitionat la sfârsitul setului activ.
Încarcarea datelor din cursor

Exemple

FETCH c1 INTO v_empno, v_ename

...
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.

Încarca primii zece angajati unul câte unul.


DECLARE
v_empno emp.empno%TYPE;
v_ename emp.ename%TYPE;
i NUMBER := 1;
CURSOR c1 IS
SELECT empno , ename
FROM emp;
BEGIN
OPEN c1;
FOR i IN 1..10 LOOP
FETCH c1 INTO v_empno, v_ename;
...
END LOOP;
END ;

Închiderea cursorului

Sintaxa

CLOSE cursor_name

 Închide cursorul dupa terminarea procesarii înregistrarilor.


 Redeschide cursorul, daca e necesar.
 Nu încercati sa încarcati date dintr-un cursor dupa ce a fost închis
Instructiunea CLOSE
Instructiunea CLOSE închide cursorul, si setul de rezultate devine nedefinit. Închideti cursorul
dupa ce ati terminat de procesat instructiunea SELECT. Acest pas permite cursorului sa fie redeschis daca
este necesar. Astfel se poate stabili un set activ de câteva ori.

Î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.

Nota: Instructiunea CLOSE elibereaza zona de context.


Desi este posibil de terminat un bloc PL/SQL fara a închide cursorul ar trebui sa va obisnuiti sa
închideti cursorii declarati explicit pentru a elibera resursele.
Exista un numar maxim de cursori deschisi pe utilizator, numar ce este determinat de parametrul
OPEN_CURSORS în câmpul de parametri ai bazei de date. Standard OPEN_CURSORS = 50.

...
FOR i IN 1..10 LOOP
FETCH c1 INTO v_empno, v_ename;
....
END LOOP;
CLOSE c1;
END;

Atributele cursorilor expliciţi

Obţinerea informaţiilor de stare despre un cursor

Atribut Tip Descriere


%ISOPEN Boolean Evaluat la TRUE dacă cursorul este
deschis
%NOTFOUND Boolean Evaluat la TRUE dacă ultima
încărcare nu a adus nici o
înregistrare
%FOUND Boolean Evaluat la TRUE dacă ultima
încărcare a adus o înregistrare;
complementarul lui %NOTFOUND
%ROWCOUNT Number Evaluează numărul de înregistrări
aduse oână în acel moment.
Atributele cursorilor expliciti
Ca si la cursorii impliciti, exista patru atribute pentru obtinerea informatiilor de starepentru un
cursor. Când sunt adaugate la un cursor sau o variabila de tip cursor, aceste atribute returneaza informatii
importante despre executia unei instructiuni de manipulare a datelor.

Nota: Nu puteti apela atributele cursorilor direct în instructiuni SQL.

Controlarea încarcarilor multiple

 Procesati câteva înregistrari dintr-un cursor explicit utilizând un ciclu.


 Încarcati o înregistrare cu fiecare iteratie.
 Folositi atributul %NOTFOUND pentru a face testul e încarcare esuata.
 Folositi un atribut de cursor explicit pentru a testa succesul încarcarii.

Controlarea încarcarilor multiple din cursori expliciti


Pentru a procesa mai multe linii dintr-un cursor explicit, deobicei definiti un ciclu care sa realizeze
încarcarea pe fiecare iteratie. În final toate liniile sun procesate si încarcarea esuata seteaza
%NOTFOUND pe TRUE. Folositi atributele cursorului explicit pentru a testa succesul fiecarei încarcari
înainte de a mai face vreo referire la cursorul respectiv. Daca omiteti un criteriu de iesire va rezulta un
ciclu infinit.

Atributul %ISOPEN

 Încarca înregistrarile numai când cursorul este deschis.


 Foloseste atributul %ISOPEN înainte de a realiza o încarcare, pentru a vedea
daca cursorul este deschis

Exemplu

IF NOT c1%ISOPEN THEN


OPEN c1;
END IF;
LOOP
FETCH c1. . .

Atributele cursorului explicit


 Puteti încarca înregistrari numai când cursorul este deschis. Folositi atributul %ISOPEN
pentru a testa daca cursorul este deschis.
 Încarcati liniile într-un ciclu. Folositi atributele cursorului pentru a determina iesirea din ciclu.
 Folositi atributul %ROWCOUNT pentru a determina numarul exact de înregistrari, încarcati
înregistrarile într-un FOR numeric, sau încarcati înregistrarile într-un ciclu simplu si
determinati când trebuie iesit.
Nota: %ISOPEN returneaza starea cursoruluis TRUE daca este deschis, FALSE daca nu.

Atributele %NOTFOUND si %ROWCOUNT

 Folositi %ROWCOUNT pentru a obtine numarul exact de linii.


 Folositi %NOTFOUND pentru a determina când sa iesiti din ciclu.

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.

Ciclul FOR pentru cursori

Sintaxa

FOR record_name IN cursor_name LOOP


statement1;
statement2;
...
ENDLOOP;

 Modalitate mai rapida de a procesa cursorii expliciti


 Realizeaza implicit open, fetch si close
 A nu se declara înregistrarea; este declarata implicit.

Ciclul FOR pentru cursori


Un ciclu FOR pentru cursori proceseaza articolele dintr-un cursor explicit. Este o modalitate mai
simpla pentru ca cursorul este deschis , articolele sunt încarcate cate unul pentru fiecare iteratie din ciclu,
si cursorul este automat închis atunci când articolele au fost procesate. Ciclul se termina automat când
ultimul articol a fost încarcat.
În sintaxa,
record_name este numele înregistrarii declarate implicit
cursor_name este un identificator PL/SQL pentru cursorul anterior declarat

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.

Ciclul FOR pentru cursori

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

Nu este nevoie sa se declare cursorul


Exemplu

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

 Declararea si utilizarea cursorilor expliciti pentru a interoga articolele dintr-o


tabela.
 Utilizarea ciclurilor FOR penrtu cursori.
 Aplicarea atributelor cursorilor pentru a le verifica starea

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

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