Sunteți pe pagina 1din 5

Facultatea de Cibernetic, Statistic i Informatic Economic SGBD Oracle seminarul 4

CURSORUL N PL/SQL

Atunci cnd se execut o comand SQL, Oracle Server deschide o zon de memorie (context area) n care comanda este executat. Cursorul este un pointer ctre aceast zon n PL/SQL se utilizeaz dou tipuri de cursoare: implicit: declarat pentru toate instruciunile PL/SQL de tip LMD (INSERT/UPDATE/DELETE); explicit: declarat i gestionat de programator.

CURSORUL IMPLICIT este declarat de PL/SQL implicit pentru toate comenzile de manipulare a datelor (INSERT, UPDATE, DELETE); dac o instruciune LMD nu afecteaz nici o linie a tabelei nu se genereaz eroare, ns excepia trebuie tratat folosind atributele speciale ale cursorilor; atributele cursorului implicit: SQL%ROWCOUNT SQL%FOUND SQL%NOTFOUND Exemplu Se terge un produs din tabela PRODUSE i se contorizeaz numrul de rnduri terse. SET SERVEROUTPUT ON DECLARE v_rez NUMBER(2); BEGIN DELETE FROM produse WHERE id_produs=111; v_rez:=SQL%ROWCOUNT; DBMS_OUTPUT.PUT_LINE (v_rez || ' randuri sterse'); COMMIT; END; / Se ncearc modificarea denumirii produsului cu codul 3, n cazul n care acest produs nu exist (comanda update nu realizeaz nici o modificare) va fi afiat un mesaj corespunztor. BEGIN UPDATE produse SET denumire_produs='cafea' WHERE id_produs=3; IF SQL%NOTFOUND THEN
1

Facultatea de Cibernetic, Statistic i Informatic Economic SGBD Oracle seminarul 4

DBMS_OUTPUT.PUT_LINE('Nu exista produsul cu acest cod'); END IF; END; / Se terge din tabela EMP_SAL salariatul al crui ID este introdus de utilizator prin intermediul variabilei g_angid: ACCEPT g_angid PROMPT 'Introduceti id-ul salariatului:' VARIABLE nr_sters varchar2(100) DECLARE BEGIN DELETE FROM emp_sal WHERE id_angajat=&g_angid; :nr_sters:=TO_CHAR(SQL%ROWCOUNT)||' INREGISTRARI STERSE'; END; / PRINT nr_sters Rollback; CURSORUL EXPLICIT se folosete pentru a procesa individual fiecare linie (nregistrare) returnat de o instruciune SELECT ce returneaz mai multe nregistrri. mulimea nregistrrilor returnate de o instructiune SELECT este numit mulime rezultat. cursorul pstreaz un pointer ctre linia curent n cadrul unei mulimi rezultat. Verificarea strii unui cursor explicit se realizeaz prin intermediul urmtoarelor atribute: nume_cursor%ISOPEN - evaluat la TRUE n cazul n care cursorul este deschis; nume_cursor %NOTFOUND - evaluat la TRUE n cazul n care cel mai recent FETCH nu a returnat nici o linie; nume_cursor %FOUND - complementul lui %NOTFOUND; nume_cursor %ROWCOUNT - are ca valoare numrul liniilor returnate pn n momentul curent. Prelucrarea cursorului explicit presupune parcurgerea urmtoarelor etape: 1) se declar variabilele n care vor fi ncrcate valorile corespunztoare unei linii din cursor; 2) se declar cursorul explicit, specificndu-se un nume pentru acesta i definindu-se interogarea de procesat n cadrul lui: DECLARE nume_cursor IS SELECT........................; 3) se deschide cursorul prin intermediul instruciunii OPEN, care execut interogarea i legarea tuturor variabilelor referite. nregistrrile returnate de interogare sunt desemnate drept set activ de date, care pot fi de acum ncrcate. OPEN nume_cursor; 4) utilizndu-se instruciunea FETCH, se ncarc linia curent din cursor n variabile. Fiecare ncrcare determin mutarea pointerului cursorului la linia urmtoare din setul activ de date. FETCH nume_cursor INTO var1, var2,..............;
2

Facultatea de Cibernetic, Statistic i Informatic Economic SGBD Oracle seminarul 4

este nchis cursorul prin instructiunea CLOSE, care dezafecteaz setul activ de linii. Cursorul poate fi din nou deschis pentru a stabili un nou set activ de linii. CLOSE nume_cursor; Pentru a procesa liniile unui cursor explicit se definete de obicei o bucl pentru executarea unui FETCH n fiecare iteraie. n final, toate liniile din setul activ sunt procesate i un FETCH executat fr succes poziioneaz atributul %NOTFOUND pe TRUE. naintea primului FETCH, %NOTFOUND se evalueaz la NULL, ca i n cazul n care FETCH nu se execut niciodat cu succes.
5)

Exemple: S se afieze lista cu numele i salariul angajailor din departamentul 60 folosind un cursor explicit: set serveroutput on DECLARE cursor ang_cursor is select id_angajat, nume, salariul from angajati where id_departament=60; ang_id angajati.id_angajat%type; ang_nume angajati.nume%type; ang_sal angajati.salariul%type; BEGIN dbms_output.put_line('Lista cu salariariile angajatilor din departamentul 60'); open ang_cursor; loop fetch ang_cursor into ang_id, ang_nume, ang_sal; exit when ang_cursor%notfound; dbms_output.put_line('Salariatul '||ang_nume||' are salariul: '||ang_sal); end loop; close ang_cursor; end; / Pentru o flexibilitate mai mare se poate utiliza o variabil de tip record pentru ncrcarea valorilor din cursor. Aceast variabil de tip record poate avea aceleai atribute ca i cursorul prin specificarea proprietii %ROWTYPE. n acest caz ncrcarea din cursor se va face direct prin instruciunea fech var_cursor into var_record. Exemplul de mai sus poate fi rescris astfel: set serveroutput on declare cursor ang_cursor is select id_angajat, nume, salariul from angajati where id_departament=60; --tipul record pt incarcarea valorilor cursorului ang_rec ang_cursor%rowtype; begin dbms_output.put_line('Lista cu salariariile angajatilor din departamentul 60'); open ang_cursor; loop fetch ang_cursor into ang_rec; exit when ang_cursor%notfound;
3

Facultatea de Cibernetic, Statistic i Informatic Economic SGBD Oracle seminarul 4

dbms_output.put_line('Salariatul '||ang_rec.nume||' are salariul: '||ang_rec.salariul); end loop; close ang_cursor; end; / S se ncarce n tabela MESAJE primii 5 angajai (id i nume) CREATE TABLE mesaje (cod varchar2(7), nume varchar2(20) ); DECLARE v_id angajati.id_angajat%type; v_nume angajati.nume%type; CURSOR c1 IS SELECT id_angajat, nume FROM angajati; BEGIN OPEN c1; FOR i IN 1..5 LOOP FETCH c1 INTO v_id, v_nume; INSERT INTO mesaje VALUES(v_id, v_nume); END LOOP; CLOSE c1; END; / SELECT * FROM mesaje; Testul de ieire din bucl n acest caz se poate face i cu ajutorul atributului %ROWCOUNT: Delete from mesaje; DECLARE v_id angajati.id_angajat%type; v_nume angajati.nume%type; CURSOR c1 IS SELECT id_angajat, nume FROM angajati; BEGIN OPEN c1; LOOP FETCH c1 INTO v_id, v_nume; EXIT WHEN c1%ROWCOUNT>5 OR c1%NOTFOUND; INSERT INTO mesaje VALUES (v_id, v_nume); END LOOP; CLOSE c1; END; / SELECT * FROM mesaje;

Facultatea de Cibernetic, Statistic i Informatic Economic SGBD Oracle seminarul 4

S se afieze primele 3 comenzi care au cele mai multe produse comandate. n acest caz nregistrrile vor fi ordonate descresctor n funcie de numrul produselor comandate: SET SERVEROUTPUT ON DECLARE CURSOR c_com IS select c.nr_comanda, count(r.id_produs) Numar from comenzi c, rand_comenzi r where c.nr_comanda=r.nr_comanda group by c.nr_comanda order by count(r.id_produs) desc; rec_com c_com%rowtype; BEGIN DBMS_OUTPUT.PUT_LINE('Numarul de produse pentru fiecare comanda:'); IF NOT c_com%ISOPEN THEN OPEN c_com; END IF; LOOP FETCH c_com INTO rec_com; EXIT WHEN c_com%NOTFOUND OR c_com%ROWCOUNT>3; DBMS_OUTPUT.PUT_LINE('Comanda '||rec_com.nr_comanda||' are: '|| rec_com.numar||' produse'); END LOOP; CLOSE c_com; END; /

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

  • Subprograme PL/SQL
    Subprograme PL/SQL
    Document7 pagini
    Subprograme PL/SQL
    Georgiana Florentina Spiridon
    Încă nu există evaluări
  • Instalare Oracle 10g Pe Vista
    Instalare Oracle 10g Pe Vista
    Document11 pagini
    Instalare Oracle 10g Pe Vista
    Badescu Viorel
    Încă nu există evaluări
  • Seminar 7
    Seminar 7
    Document5 pagini
    Seminar 7
    Badescu Viorel
    Încă nu există evaluări
  • Seminar 6
    Seminar 6
    Document7 pagini
    Seminar 6
    Badescu Viorel
    Încă nu există evaluări
  • Seminar 5
    Seminar 5
    Document6 pagini
    Seminar 5
    Badescu Viorel
    Încă nu există evaluări
  • Seminar 3
    Seminar 3
    Document10 pagini
    Seminar 3
    Badescu Viorel
    Încă nu există evaluări
  • SGBD
    SGBD
    Document5 pagini
    SGBD
    Badescu Viorel
    Încă nu există evaluări
  • Seminar 2
    Seminar 2
    Document12 pagini
    Seminar 2
    Badescu Viorel
    Încă nu există evaluări