Sunteți pe pagina 1din 8

Prof. Negrilescu Nicolae Col. Nat.

Vlaicu Voda

CURSOARE SQL SERVER


Specificul bazelor de date relaionale, i al limbajului SQL n particular, este modul de operare asupra relaiilor ca un tot unitar. Orice operaie, se face asupra setului complet de tuple care satisface anumite condiii. Cursoarele constituie un mod complementar de lucru prin care se permite accesul la tuple, una cte una, i prelucrarea independent a fiecrei tuple n parte. Prin introducerea cursoarelor se aduce o extensie util limbajului SQL care este astfel ntregit cu toate facilitile specifice limbajelor navigaionale: - poziionare pe o anumit tupl; - modificri ale tuplei de la poziia curent; - deplasare cursor nainte-napoi; - prelucrarea subsetului de tuple ncepnd de la poziia curent .a.m.d. De remarcat c nu este indicat folosirea cursoarelor n operaiile obinuite care se pot rezolva prin fraze SQL. Cursoarele au fost introduse ca o extensie i nu ca alternativ la frazele SELECT, UPDATE .a.m.d. care sunt, n general, mult mai rapide. O prelucrare bazat pe cursoare se desfoar n mai multe faze dup cum urmeaz: 1. Declararea unui cursor - unui nume de cursor i se asociaz setul de tuple rezultat corespunztor unei fraze SELECT; de asemenea se specific o serie de caracteristici ale cursorului. 2. Deschiderea cursorului - se execut fraza SELECT asociat, realizndu-se ceea ce se numete popularea cursorului. 3. ncrcarea cursorului - se poziioneaz cursorul n dreptul unei tuple i se realizeaz accesul la coninutul acesteia. 1. Prelucrare - se execut operaiile specifice aplicaiei. 4. nchiderea cursorului - se terge setul de tuple cu care s-a populat cursorul, dar se menine cursorul n sine mpreun cu definiia sa. 5. Dealocarea cursorului - se terge cursorul mpreun cu definiia sa.

Instruciunea DECLARE CURSOR


Definete atributele unui cursor i setul de tuple cu care se populeaz DECLARE nume_cursor [ INSENSITIVE ] [ SCROLL ] CURSOR FOR fraz_select [ FOR { READ ONLY | UPDATE [ OF list_ coloane] } ]

unde:
nume_cursor - este numele cursorului; INSENSITIVE - definete un cursor care creeaz o copie temporar a setului

de tuple corespunztor. Modificrile ulterioare asupra datelor originale nu sunt reflectate n datele din cursor. Sunt interzise operaiile de actualizare. Dac este omis opiunea INSENSITIVE, atunci modificrile din tabelele de baz se vor reflecta la nivelul cursorului.
SCROLL - indic faptul c toate opiunile de navigare-accesare date

(FIRST, LAST, PRIOR, NEXT, RELATIVE, ABSOLUTE) sunt permise. n lipsa acestei opiuni, NEXT este singura opiune de navigare permis.
fraz_select - definete setul de tuple corespunztor cursorului; READ ONLY - interzice operaiile de actualizare date la nivelul cursorului; UPDATE [OF list_ coloane]- indic coloanele care pot fi modificate n

cursor. Numai coloanele specificate n lista OF list_ coloane pot fi modificate. Dac aceast list lipsete, atunci, implicit, toate coloanele sunt modificabile.

Instruciunea OPEN
Deschide un cursor i populeaz cursorul prin executarea frazei SELECT specificat n declaraia cursorului. Sintaxa: OPEN nume_cursor unde: nume_cursor - este numele unui cursor declarat anterior; Observaie: Dup deschiderea unui cursor variabila sistem @@CURSOR_ROWS conine numrul de tuple ncrcate de ultima operaie OPEN.

Instruciunea FETCH
Acceseaz o tupl dintr-un cursor i ncarc coninutul acesteia ntr-un set de variabile. Sintaxa: FETCH [ NEXT | PRIOR | FIRST | LAST | ABSOLUTE { n | @nvar } | RELATIVE { n | @nvar } ] FROM nume_cursor [ INTO lista_variabile ] Unde:

NEXT - mut poziia curent la tupla urmtoare i ncarc coninutul acesteia.

Dac FETCH NEXT este prima operaie de ncrcare a unui cursor, atunci va ncrca prima tupl a cursorului. NEXT este opiunea implicit de ncrcare.
PRIOR - mut poziia curent la tupla precedent i ncarc coninutul acesteia.

Dac FETCH PRIOR este prima operaie de ncrcare a unui cursor, atunci nu se ncarc nimic i cursorul rmne poziionat pe prima tupl.
FIRST - mut poziia curent la prima tupl i ncarc coninutul acesteia. LAST - mut poziia curent la ultima tupl i ncarc coninutul acesteia. ABSOLUTE {n | @nvar} - poziionare absolut pe tupla din poziia n sau

@nvar de la nceput dac n sau @nvar este pozitiv. Dac n sau @nvar este negativ poziionarea se face fa de sfritul cursorului (valoarea -1 poziioneaz pe ultima tupl din cursor!). Dac n sau @nvar este 0 nu se ncarc nimic.
RELATIVE [n | @nvar] - poziionare relativ fa de tupla curent. Cu n sau

@nvar avnd valoarea 0 se ncarc tupla curent, valoarea 1 corespunde opiunii NEXT, iar -l corespunde opiunii PRIOR.
nume_cursor - este numele unui cursor declarat anterior. INTO @list_variabile - permite ncrcarea coninutului tuplei curente ntr-un

set de variabile locale. Fiecare variabil din list este asociat, n ordine, cte unui atribut din relaia cu care s-a ncrcat cursorul. Corespondena trebuie s fie unu la unu ca numr i ca tip de dat pn la nivelul conversiilor implicite suportate de SQL Server.

Variabila sistem @@FETCH_STATUS


Returneaz starea ultimei operaii FETCH executat asupra unui cursor. Valorile posibile ale variabilei @@FETCH_STATUS i semnificaia acestora este dat n urmtorul tabel: @@FETCH_STATU S 0 -1 -2 Observaii: Deoarece @@FETCH_STATUS este o variabil global testarea sa trebuie fcut imediat dup operaia a crei stare vrem s o aflm, naintea oricrei alte operaii FETCH care modific la rndul ei variabila @@FETCH_STATUS.
2.

Descriere Instruciunea FETCH s-a executat cu succes. Instruciunea FETCH a euat sau cursor n afara setului rezultat. Lips tupl ncarcat

Variabila @@FETCH_STATUS poate avea valoarea -2 n cazul unui cursor fr opiunea 1NSENSITIVE, dac ntre timp un utilizator concurent a ters tupla pe care s-a ncercat poziionarea prin ultima operaie FETCH.

Instruciunea CLOSE
nchide un cursor deschis i elibereaz setul rezultat asociat. Un cursor nchis poate fi redeschis din nou printr-o instruciune OPEN care calculeaz o nou valoare actualizat a setului rezultat. Instruciunea CLOSE se poate executa numai asupra unui cursor deschis. Sintaxa: CLOSE nume_cursor unde: nume_cursor - este numele unui cursor deschis anterior;

Instruciunea DEALLOCATE
terge o referin la un cursor. La tergerea ultimei referine ctre un cursor toate structurile de date i resursele asociate cursorului vor fi eliberate. Sintaxa: DEALLOCATE nume_cursor unde:
nume_cursor - este numele unui cursor declarat anterior;

Observaii:
1.

Instruciunea DEALLOCATE elimin asocierea dintre un cursor i numele su sau variabila cursor care refer cursorul. Dac numele cursor sau variabila este singura care refer cursorul, atunci cursorul este dealocat i toate resursele folosite de acesta sunt eliberate. 2. Putem asocia o variabil cursor cu un cursor n dou moduri: a. Prin atribuirea unui nume cursor unei variabile cursor. De exemplu: DECLARE @cursor_furnizor CURSOR DECLARE cursor_furnizor CURSOR FOR SELECT * FROM tFurnizori SET @cursor_furnizor = cursor_furnizor b. Prin asocierea unei definiii de cursor direct unei variabile cursor. De exemplu: DECLARE @cursor_furnizor CURSOR

SET

@cursor_furnizor= CURSOR FOR SELECT * FROM tFurnizori

3. Variabila cursor poate fi folosit in locul numelui cursorului n instruciunile Open, Fetch, Close, Deallocate 4. Un cursor este meninut i se transmite de la un batch la altul (sau de la o procedur la alta!) pn la nchiderea i dealocarea sa. n schimb o variabil cursor exist doar n batch-ul n care a fost creat i dispare la terminarea acesteia.

Exemple de utilizare a cursoarelor


l. Secvena de mai jos folosete un cursor pentru a accesa, pe rnd, fiecare furnizor cu scopul de a trimite acestora cte un email: DECLARE @Den varchar(30) DECLARE @Localitate varchar(30)

DECLARE cursor_furnizor CURSOR FOR SELECT DenFurn, Localitate FROM tFurnizori OPEN cursor_furnizor FETCH NEXT FROM cursor_furnizor INTO @Den, @Localitate WHILE @@FETCH_STATUS=0 BEGIN // Prelucrarea tuplei Print @Den + + @Localitate FETCH NEXT FROM cursor_furnizor INTO @Den, @Localitate END CLOSE cursor__furnizor DEALLOCATE cursor_furnizor GO Urmtoarea secven afieaz numele furnizorilor n ordinea invers a apariiei lor fizice n tabela furnizor. De remarcat c setul rezultat

asociat cursorului este parcurs de la coad la cap, ceea ce impune folosirea unui cursor cu opiunea SCROLL. DECLARE @Den varchar(30) DECLARE cursor_furnizor CURSOR SCROLL FOR SELECT DenFurn FROM tFurnizori OPEN cursor_furnizor FETCH LAST FROM cursor_furnizor INTO @Den WHILE @@FETCH_STATUS=0 BEGIN Print Numele furnizorului este: + @Nume FETCH PRIOR FROM cursor_furnizor INTO @Den END CLOSE cursor_furnizor DEALLOCATE cursor_furnizor GO 3. Operaia implementat de secvena de cod de la exemplul 1 ar putea fi una de lung durat, mai ales dac numrul furnizorilor este mare. ntre timp ar putea s apar noi furnizori i se dorete ca i acetia s primeasc mesajele cuvenite, dar fr a mai retrimite mesaje celor care deja le-au primit. Procedura de mai jos folosete poziionarea absolut a cursorului cursor_furnizor pentru a ncepe prelucrarea ncepnd cu furnizorul indicat prin parametrul @primul. Acest parametru este folosit i pentru a determina ci dintre furnizori au fost prelucrati i este ntors ca parametru de ieire la terminarea procedurii. CREATE PROCEDURE Prelucrare (@primul int OUTPUT) AS BEGIN DECLARE @Den varchar(30) DECLARE @Localitate varchar(30)

DECLARE cursor_furnizor CURSOR FOR SELECT DenFurn, Localitate FROM tFurnizori OPEN cursor_furnizor

FETCH ABSOLUTE @primul FROM cursor_furnizor INTO @Den, @Localitate WHILE @@FETCH_STATUS=0 BEGIN // Prelucrarea tuplei Print @Den + + @Localitate @primul=@primul+1 FETCH NEXT FROM cursor_furnizor INTO @Den, @Localitate END CLOSE cursor__furnizor DEALLOCATE cursor_furnizor END

Sincronizarea cursoarelor cu comenzile DELETE i UPDATE DELETE FROM denumire_tabel WHERE CURRENT OF denumire_cursor Efectueaz tergerea poziionat. Stergerea se refer la tupla aflat la pozitia curent a cursorului. CURRENT OF denumire_cursor precizeaz cursorul deschis utilizat de delete, cursor ce trebuie s permit actualizarea (precizat prin clauza for update) UPDATE denumire_tabel SET coloana=expresie, ,coloana=expresie WHERE CURRENT OF denumire_cursor Efectueaz actualizarea poziionat. Actualizarea se refer la tupla corespunztoare poziiei curente a cursorului. CURRENT OF denumire_cursor precizeaz cursorul deschis utilizat de update, cursor ce trebuie s permit actualizarea (precizat prin clauza for update)

Exercitiul 3 Scriptul urmator realizeaza stergerea angajatilor cu salariul mai mare decat 10000, majorarea salariilor angajatilor departamentului d1 cu 20% si a salariilor celorlalti angajati cu 10%

declare @codDep as char(10) declare @sal numeric(5,0) declare cursorModiSal cursor for select codDep,salariu from tAngajati for update Open cursorModiSal Fetch next from cursorModiSal into @codDep, @sal while @@fetch_status=0 begin if @sal>10000 begin delete from tAngajati where current of cursorModiSal goto urmatorul end if @codDep='d1' update tAngajati set salariu=salariu*1.20 where current of cursorModiSal else update tAngajati set salariu=salariu*1.10 where current of cursorModiSal urmatorul: Fetch next from cursorModiSal into @codDep, @sal end close cursorModiSal deallocate cursorModiSal