internetul Windows. Android

Utilizați cursoare și cicluri în tranzacții-SQL. Cursoare în cursoare MySQL din SQL Server

1) concept cursor
În cererile interactive SQL, cu o singură linie și multi-linie nu variază. În SQL încorporat, aceste solicitări sunt efectuate în moduri diferite. Întrebările cu o singură dată returnează o linie și am luat în considerare deja. Când rezultatul executării interogării nu este o singură linie, SQL încorporat trebuie să furnizeze o aplicație cu posibilitatea de primire liniară a rezultatelor interogării. Pentru aceasta, sunt utilizate cursorii. Sub cursor înseamnă o variabilă asociată cu solicitarea. Valoarea sa este fiecare șir care satisface cererea. Ca variabile, cursorii trebuie descrise înainte de a le folosi. Spre deosebire de vizualizări, cursorii sunt proiectați să se alinieze.

2) anunțul cursorului

Declara. [{}] [[Nu.] Sul] Cursor. [{Cu | fără.} Hold.] Pentru [Pentru {Citiți numai | actualizare [De. ]}]

3) Cuvinte cheie
. Sensibil | Insensibil | Aenitiv - Modificările setului rezultat sunt vizibile Este interzisă (fixă utilizând o copie a setului de date) DBMS-ul în sine face o decizie de a face o copie (reală în mod implicit).
. Cu | fără a ține - Frunze deschise Închide cursorul dacă operatorul comitetului sa întâlnit.
. Sul - [interzice] pentru a extrage liniile de rezultate într-o ordine arbitrară.
. Pentru citire numai - determină cursorul numai pentru citire.
. Pentru actualizarea. - Numai coloanele specificate blochează de la actualizare.

4) Anunț cursor în SQL Server

Declara. Cursor. [Local Global] [Forward_ONly | Scroll.] [Static | Keyset | Dynamic | Fast_forward] [Citiți_Only | Scroll_locks | Optimist] Pentru [Pentru actualizare. [De. ]]

. Static. - Specifică cursorul care creează o copie temporară a datelor pentru a utiliza cursorul. Toate solicitările cursorului se referă la tabelul temporar specificat din baza de date tempdb, astfel încât schimbarea tabelelor de bază nu afectează datele returnate de probe pentru acest cursor, iar cursorul în sine nu permite modificări.
. Cheie. - indică faptul că apartenența sau ordinea de caractere în cursor nu se schimbă după deschiderea sa. Un set de chei care definesc în mod evident șirurile este construit într-un tabel din baza de date tempdb numită Keyset.
. Dinamic - Specifică cursorul care afișează toate modificările de date efectuate în șirurile de caractere de săgeți când vizualizați acest cursor. Valorile datelor, ordinea, precum și apartenența la rânduri în fiecare probă pot varia. Parametrul absolut de eșantionare nu este acceptat de cursoare dinamice.
. Repede inainte - Specifică cursorul Forward_ONly, Citit_Only, pentru care optimizarea performanței este activată. Parametrul Fast_forward nu poate fi specificat cu parametrii de defilare sau pentru_update.
. Scroll_locks. - indică faptul că actualizările sau eliminarea poziționată, efectuate prin cursor, vor fi garantate pentru a avea succes. SQL Server Blocks Strings Pe măsură ce cursorul este citit pentru a asigura disponibilitatea acestora pentru modificările ulterioare. Parametrul Scroll_locks nu poate fi specificat cu parametrul Fast_forward sau static.
. Optimist - Indică faptul că actualizările sau ștergerile poziționate realizate prin cursor nu vor fi executate dacă șirul a fost actualizat de la citirea cursorului. Serverul SQL nu blochează șirurile, deoarece acestea sunt citite în cursor. În schimb, pentru a determina dacă șirul a fost modificat după citirea cursorului, valorile coloanei de timp ale Coloanelor sunt comparate (sau verificări, dacă nu există coloană de orificii). Dacă șirul a fost modificat, schimbarea sau îndepărtarea poziționată nu este posibilă. Parametrul optimist nu poate fi specificat cu parametrul Fast_forward.

5) Cursor de deschidere

6) extragerea rândurilor de la cursor

Fetch. [{Următor | înainte | primul | ultima ||{Absolut | relativ. }}]
Din. În

7) Opțiuni de poziționare cursor
. Următor | înainte | primul | ultima | - În următorul | Precedent | Primul | Ultimul șir al setului rezultat.
. Relativ ± N. - pe un șir cu o compensare pozitivă sau negativă față de linia curentă.
. Absolut ± N. - pe un șir cu un număr absolut specific specific de poziții de la începutul sau la sfârșitul cursorului.

Notă: În SQL Server, în loc de N, este permisă o variabilă întregătoare.

8) Cursor de închidere

9) Note privind cursorii
. Dacă cursorul conține mai multe linii, este necesar să se organizeze un ciclu de recuperare a datelor de la acesta cu o verificare periodică pentru realizarea ultimului șir.
. Spre deosebire de tabelele și observațiile șirului de cursor sunt comandate fie în mod explicit folosind secțiunea Comanda prin.sau în conformitate cu acordurile adoptate într-un anumit DBMS.
. Cursoarele se aplică, de asemenea, eșantionului din tabele de grupuri de caractere care pot fi actualizate sau șterse una.
. Pentru ca cursorul să fie actualizat, acesta trebuie să îndeplinească aceleași criterii ca și prezentarea, adică nu conține partiții Uniune, Ordinul, Grupul, distinct.

10) Exemplu pentru ștergerea datelor din cursor

exec SQL Declarați cursul cursorului pentru selectarea * de la client
Unde rating.
// Print (@ F1 + '' + Convertire (Varchar (5), @ F2))
EXEC SQL DELETE DE LA CLIENT
Unde curent de cur1; ) - date pentru eliminarea de la cursor
nu_done:
EXEC SQL CURSE CURSIA CURSULUI; - Închideți curentul
Ieșire ();

11) Un exemplu de creștere a Comisiei

exec SQL Declar Curcutul cursorului pentru selectarea * de la vânzători
Unde snum în (selectați snum de la client unde rating \u003d 300); - Determinați cursorul
EXEC SQL Curcutul cursorului deschis; - Efectuați cursorul
În timp ce (sqlca.sqlcode \u003d\u003d 0) (- Creați o buclă pentru a actualiza datele din tabel
EXEC SQL Fetch Curcust în: Id_num,: Vânzător: loc,: Comm;
EXEC SQL Actualizarea vânzătorilor set Comm \u003d Comm + .01 unde este curent
de curcust; ) - date pentru actualizarea pentru a lua de la cursor
EXEC SQL Curcutul cursorului Curcutului; - Închideți curentul

Seect S.Name, Max (S.City) ca oraș, suma (O.AMT) ca AMT de la vânzătorii S Comenzile Inner One pe S.Snum \u003d O.SNUM Grupul de către s.Name Comandă de 2

Declarați cursorul de derulare pentru selectați S.Name, max (S.City) ca oraș, suma (O.Amt) ca AMT de la vânzătorii s.snum \u003d O.SNUM Grupul de către s.name Comanda by 2
Deschide cursul deschis.
FETCH Următorul de la Cur1
În timp ce @@tch_status \u003d 0
Începe.
FETCH Următorul de la Cur1
Sfârșit.
Închideți cursul.
Dealocați cur1.

Echipa Cursor declară ne permite să ne ajutăm să extragem înregistrări de la masă pentru manipulare. Acest lucru permite prelucrarea construcțiilor în locul prelucrării tradiționale a seturilor de date, care este efectuată de SQL.

În prima abordare, următorii pași sunt utilizați atunci când lucrați cu cursorul.

Cursorul este creat de comanda Declare. Cursorul se deschide cu comanda deschisă.

Operațiile cursorului sunt fabricate utilizând comanda Fetch. Cursorul se închide cu comanda apropiată.

Comanda Cursor declară indică instrucțiunea SELECT. Fiecare linie returnată de instrucțiunea SELECT poate fi eliminată și prelucrată individual. În exemplul următor pentru Oracle, cursorul este declarat în blocul de anunț împreună cu alte câteva variabile. După aceea, în următorul începe ... capăt, cursorul se deschide, este eșantionat pentru el, iar cursorul se închide.

Cursor Title_Price_Cursor este selectat Titlu, preț de preț

Prețul de grilie nu este nul; title_price_val titlu_price_crive Rowtype; Numărul nou_price (10.2);

Deschideți titlul_price_crive;

Fetch title_price_cur-sma în titlu_price_val;

new_Price: \u003d "titlu_price_val.price" * 1.25 Inserare în valori noi_title_price

(titlu_price_val.title, New_Price) Închide title_price_crivesor; Sfârșit;

Deoarece acest exemplu utilizează PL / SQL, nu vom explica în această carte în această carte. Cu toate acestea, un anunț al cursorului este vizibil în mod clar în blocul declarați. În blocul executabil PL / SQL, cursorul este inițializat de comanda Open, valorile sunt preluate de comanda Fetch și, în final, cursorul se închide cu comanda apropiată.

Instrucțiunea Selectați este baza cursorului, astfel încât o bună practică este testarea completă înainte de includerea în instrucțiunile cursorului declară. Instrucțiunea selectată poate funcționa cu o masă sau o reprezentare de bază. Prin urmare, cursorii de citire numai pot lucra cu idei inutile. Instrucțiunea SELECT poate conține sugestii, cum ar fi comanda, gruparea și având, dacă aceste oferte nu actualizează tabelul sursă. Dacă cursorul este definit ca pentru actualizare, se recomandă ștergerea unor astfel de sugestii din instrucțiunea SELECT.

Cursoarele locale sunt adesea folosite ca parametri de ieșire ai procedurilor stocate. Prin urmare, în procedura stocată, puteți defini și completa cursorul și îl puteți transfera la sarcina de pachete sau procedura stocată.

În următorul exemplu simplu pentru DB2, vom declara cursorul care vizualizează departamentele, numele departamentelor și numerele managerilor din admin_group "HO1".

Declarați cursorul dept_cursor.

Pentru selectați Dept_nbr, Dept_Name, MGR_NBR

Unde admin_group \u003d "x01"

Ordine de d "EPT_NAME ASC, DEPT_NBR desc, MGR_NBR desc;

În exemplul următor, serverul Microsoft SQL este anunțat și se deschide cursorul pentru tabelul editorilor. Cursorul selectează prima înregistrare de la tabelul editorilor, instrucțiunea de selectare corespunzătoare și introduceți-o într-un alt tabel. Apoi merge la următoarea înregistrare, apoi la următoarea - până când toate înregistrările sunt procesate. În cele din urmă, cursorul se închide și eliberează memoria (comanda Deallocate este utilizată numai la Microsoft SQL Server).

Declarați @publisher_name Varchar (20)

Declarați Cursorul pub_cursor pentru selectați pub_name de la editori în cazul în care țara "SUA"

FETCH Următorul de la PUB_CRSOR în editor_name

În timp ce @s\u003e fetch_status \u003d 0

Introduceți în valori străine_publishers ("J\u003e editor_name)

Închide PUB_CURSOR DEALLODE PUB_CRSOR

În acest exemplu, puteți vedea că cursorul mișcă setul de înregistrări. (Acest exemplu este destinat numai pentru a demonstra această idee, deoarece în realitate există o modalitate mai bună de a rezolva această sarcină, și anume introducerea, selectați instrucțiunea.)


Cursor - Referință la zona de memorie contextuală. În unele implementări ale limbajului de programare SQL (Oracle, Microsoft SQL Server), setul rezultat și indicatorul curent de înregistrare asociat cu acesta este îndeplinit. Ar fi spus că cursorul este un tabel virtual care este un depozit alternativ de date. În acest caz, cursorul vă permite să vă reveniți la datele dvs. cu privire la datele matricei obișnuite.
Cursorii sunt utilizați în procedurile stocate. Teorii frumoase, să luăm în considerare un exemplu:
Avem o bază de date (baza nu este bună puțin, este una dintre lucrările mele de laborator, dar profesorul nostru în baze de date a insistat asupra unei astfel de structuri)
/ * Date bancare * /
Creați tabelul `Bank" (

`BankName` Varchar (50) Collate UTF8_BIN nu NULL Implicit",


Cheia primară ("Bankid")

) Motor \u003d Innodb
Setul de caractere "UTF8" Collate "UTF8_BIN";
/ * Date de depozit * /
Creați tabelul `BankDistribution" (
`Bankid` Integer (11) Nu NULL,
`Persendent` Integer (11) Implicit ,
`Contribyamount` zecimal (10,0) nu nul,
"Integerul clientului (11) nu este nul,
Cheie primară ("Bankid", "clientid"),
Cheie `Bankid" ("Bankid"),
Cheie `clientid" (`clientid`),
Constrângere "bankdistribution_fk" cheie străină ("bankid") referințe "banca" ("bankid"),
Constrângere "bankdistribution_fk1" cheie străină ("clientid") referințe `client" (`clientid")
) Motor \u003d Innodb
/ * Date de deponente * /
Creați tabelul `client"
`Clientid` Integer (3) Nu NULL Auto_increment,
`CreditCardad` Bigent (10) Nu NULL,
`Prenume` Varchar (50) Collate utf8_bin nu Null implicit"
`Nume` Varchar (50) Collat \u200b\u200bUTF8_BIN nu NULL este implicit",
`FirstName` Varchar (50) Collate utf8_bin nu Null Implicit",
`Telefon` Varchar (50) Collate UTF8_BIN nu NULL este implicit",
`Adresa` Varchar (50) Collate utf8_bin nu Null Implicit",
`Safeid` Integer (5) Nu NULL,
Cheie primară ("clientid", "creditcardid"),
Cheie `clientid" ("clientid")

) Motor \u003d Innodb
Auto_increment \u003d 11 set de caractere "UTF8" Collate "UTF8_BIN"

Să presupunem că trebuie să ajungem la rândul său în fiecare bancă și să producem un fel de acțiuni cu el, am putea ajuta în acest sens

Selectați "banca". * De la "Limită de bancă" Număr_name_name_sapsy, 1
. Astfel, folosind limita numere_name_nam_pisi, 1, eliminăm într-un ciclu de la masa bancară la toate înregistrările și producerea acțiunilor de care avem nevoie, în timp ce crește valoarea numărului_name_nam_name la 1. Acum vom face același lucru, dar folosind cursorul
Începe.
/ * variabile unde extragem datele * /
Declară integer vbankid;
Declarați VankName Varchar (50);
Declară Vaddress Varchar (50);
Declarați ViChone Varchar (50);
/ * Variabil Hadler - A * /
Declararea implicită între Integer 0;
/ * Anunț cursor * /
Declarați cursorul de faliment pentru selectarea "băncii"
/ * Numirea de manipulare care este explicată chiar mai jos * /
Declarați Continuați Handler pentru SQLSTATE "02000" SET DONE \u003d 1;
/ * Cursor de deschidere * /
Deschiderea de bancă deschisă;
/ * Eliminați datele * /
În timp ce ați făcut \u003d 0 do

Facem acțiunea de care avem nevoie
Sfârșitul în timp ce;
/ * Închidere cursor * /
Închideți banii apropiați;
Sfârșit;

* Acest cod sursă a fost evidențiat cu evidența codului sursă.

EROARE: 1329 SQLSTATE: 02000 (ER_SP_FETCH_NO_DATA)

Mesaj: Nu există date - rânduri zero preluate, selectate sau procedate

SQLState: 02000 Declanșatoare Când se atinge sfârșitul cursorului sau când selectați sau actualizați returnează un șir gol.

Următoarea linie am anunțat cursorul declarați Cursor_name pentru cursorul Select_Statement;
Deschideți cursorul Cursor_Name deschis;
Apoi, nu ajungem la sfârșitul cursorului (în timp ce ați făcut \u003d 0 fac) prin extragerea datelor și le procesați.
Înainte de a părăsi procedura stocată, trebuie să închideți cursorul. Închideți Cursor_name;

Nu pare nimic complicat. Dar cu sqlstate "02000" o mulțime de capcane sunt conectate.

În timp ce ați făcut \u003d 0 do
Fetch BankCursor în Vankid, VankName, Vaddress, Vaddress;

Selectați (contribuitori) în VCONTRIBUEAMOUNTSUM de la bancnote în cazul în care BankiD \u003d Vankid Limit 1;
Faceți o acțiune
Sfârșitul în timp ce;

* Acest cod sursă a fost evidențiat cu evidența codului sursă.


Totul este bine și drept în termeni de sintaxă. Dar nu există un punct de vedere logic. Se poate întâmpla astfel încât deponenții să nu deschidă conturi într-un fel de bancă, apoi pentru seleributeamoummtsum de la BankDistributeimountsum de la bancnote în cazul în care BankiD \u003d Vankid Limit 1; SQLState va funcționa: 02000, variabila făcută va fi setată în 1, iar ciclul de timp se va termina mai devreme decât ne-am așteptat. Acest lucru poate fi evitat prin adoptare după cum urmează.
În timp ce ați făcut \u003d 0 do
Fetch BankCursor în Vankid, VankName, Vaddress, Vaddress;
/ * Extras pentru bancă suma oricărui din depozitele sale * /


dacă (vcontributeamountsum\u003e 0) atunci
/ * Extras pentru bancă suma oricărui din depozitele sale * /

terminați dacă;
Faceți o acțiune
Sfârșitul în timp ce;

* Acest cod sursă a fost evidențiat cu evidența codului sursă.


Am verificat prima solicitare și dacă există depozite (dacă nu există vcontributeamountsum \u003d\u003d 0) și numai dacă există, extragem datele.

Acum, să spunem că trebuie să vindecăm suma totală în conturi în diferite bănci pentru fiecare client
Declarați cursorul ClientSummCursor pentru suma selectată

Declarați cursorul ClientSummCursor pentru suma selectată ("bankdistribuția"), "bankdistribuții"), "Bankdistribution" `Clientid";

Deschideți clientul deschis;
În timp ce ați făcut \u003d 0 do
Fetch BankCursor în Vankid, VankName, Vaddress, Vaddress;
/ * Extras pentru bancă suma oricărui din depozitele sale * /
Selectați Sount (contribuitori) în VCONTRIBUEAMOUNTSUMOM de la bancare, în cazul în care BankID \u003d Limita Vbankid 1;
/ * Verificați dacă există contribuții în această bancă * /
dacă (vcontributeamountsum\u003e 0) atunci
/ * Extras pentru bancă suma oricărui din depozitele sale * /
Selectați Contribuyamount în VCONTIRIBUEAMOUNTSUM de la bancnote în cazul în care BankID \u003d Limita Vbankid 1;
terminați dacă;


Face unele acțiuni.
Sfârșitul în timp ce;

* Acest cod sursă a fost evidențiat cu evidența codului sursă.

Aceeași situație poate apărea atunci când datele din cursorul CrientsummCurse se vor termina mai devreme decât datele din bander, vor funcționa SQLSTATE: 02000, variabila făcută va fi instalată în 1, iar ciclul de timp se va termina mai devreme decât ne-am așteptat. Acest lucru poate fi evitat prin adoptare după cum urmează.

Deschideți clientul deschis;
În timp ce ați făcut \u003d 0 do
Fetch BankCursor în Vankid, VankName, Vaddress, Vaddress;
/ * Extras pentru bancă suma oricărui din depozitele sale * /
Selectați Sount (contribuitori) în VCONTRIBUEAMOUNTSUMOM de la bancare, în cazul în care BankID \u003d Limita Vbankid 1;
/ * Verificați dacă există contribuții în această bancă * /
dacă (vcontributeamountsum\u003e 0) atunci
/ * Extras pentru bancă suma oricărui din depozitele sale * /
Selectați Contribuyamount în VCONTIRIBUEAMOUNTSUM de la bancnote în cazul în care BankID \u003d Limita Vbankid 1;
terminați dacă;
/ * Înainte de extragerea datelor din cel de-al doilea cursor, ne amintim de starea SQLSTATE * /
Setați Old_status \u003d făcut;
/ * Eliminați datele de care avem nevoie * /
Fetch clientSummCursul în VSUM, VCIENTID;
/ * Verificarea dacă datele au fost preluate, nu au fost împiedicate cu sqlstate 0200 * /
dacă (terminat \u003d 0) atunci
Face unele acțiuni.
terminați dacă;
/ * Înainte de sfârșitul lui Eastanov, valoarea variabilei efectuate * /
setați Done \u003d Old_status;
Sfârșitul în timp ce;

* Acest cod sursă a fost evidențiat cu evidența codului sursă.

Mulțumesc tuturor în fața acestui loc, sper că acest lucru va părea că cineva util.

Rebeca M. Riordan "Cursoare în Transact-SQL"

Internet University of Informațional Technologies

http://www.intuit.ru.

Curs de instruire: "Programare în Microsoft SQL Server 2000"

Cursorul este un obiect temporar SQL special destinat utilizării în programe și proceduri stocate. Cu aceasta, este posibil să treceți prin setul de rânduri de interogare în ciclu, citirea individuală și procesarea fiecărui rând. În procedurile stocate, folosirea cursorilor, puteți efectua calcule complexe care sunt dificil de exprimat utilizând sintaxa SELECT SELECT. Materialul teoretic mare al lecției este completat de exemple foarte bune. În particular, se ia în considerare utilizarea funcției CURSOR_STATUS, descrierea variabilelor @@ cursor_rows și @@tch_Status și multe altele.

O sa inveti:

  • cursor;
  • deschideți cursorul;
  • închideți cursorul;
  • eliberați cursorul;
  • utilizați o comandă simplă de preluare;
  • eșantionarea șirului în variabile;
  • pentru a selecta un șir în poziția absolută;
  • pentru a selecta un șir la poziția sa relativă;
  • efectuați o modificare a poziției;
  • efectuați o îndepărtare a poziției;
  • utilizați variabila globală @@ cursor_rows pentru a determina numărul de rânduri într-un cursor multiple;
  • utilizați variabila globală @@tch_Status pentru a determina rezultatele comenzii de preluare;
  • utilizați caracteristica Cursor_Status pentru a solicita starea cursorului.

Una dintre proprietățile caracteristice ale bazelor de date relaționale este că acțiunile sunt efectuate deasupra seturilor de șiruri de caractere. Setul poate fi gol, sau conține doar un singur șir, dar este încă considerat a fi un set. Aceasta este o proprietate necesară și utilă pentru operațiunile relaționale, dar uneori nu poate fi prea convenabilă pentru aplicații.

De exemplu, deoarece nu există posibilitatea de a specifica un anumit șir într-un set, vizualizarea la utilizatorul corzilor una la un moment dat poate provoca dificultăți. Chiar dacă extensiile tranzacționate-SQL furnizate de limbă SQL standard vă permit să implementați multe oportunități de programare, cu toate acestea, operațiunile rămân dificile, laborioase sau chiar imposibil de îndeplinit pe baza principiilor de lucru cu seturi.

Pentru a face față acestor situații, cursorii sunt furnizați în SQL. Cursorul este un obiect care indică un anumit șir într-un set. În funcție de esența cursorului pe care l-ați creat, puteți muta cursorul în setul și modificați sau ștergeți datele.

Conceptul de cursori

Microsoft SQL Server acceptă într-adevăr două tipuri diferite de cursori: cursoare tranzacționate-SQL și cursoare API (cursoare de programare de programare). Cursorii API sunt creați în interiorul aplicației utilizând obiecte de date Microsoft ActiveX (ADO), OLE DB, ODBC sau DB-Bibliotecă. Fiecare dintre aceste API-uri suportă mai multe caracteristici diferite și utilizează o altă sintaxă. Aici nu vom discuta în detaliu cursorii API; Dacă intenționați să le utilizați, consultați documentația corespunzătoare din API și limba de programare pe care o veți aplica.

Cursoarele TRANSACTION-SQL sunt create utilizând comanda Declare Cursor. Atât obiectul cursorului cât și multe linii pe care indică faptul că ar trebui să existe pe server. Astfel de cursoare sunt numite cursoare de servere. Dacă utilizați cursorul de server din aplicația conectată la serverul SQL prin intermediul rețelei, fiecare operație cu cursorul necesită interacțiune bilaterală a rețelei. Bibliotecile API-Cursor care suportă cursoarele serverului suportă, de asemenea, cursorul clientului care există în sistemul client și cade liniile pe care le procesează pe client.

Multe linii pe care indică cursorul este determinată utilizând comanda SELECT. La crearea unui cursor TRANSACT-SQL la comanda SELECT, mai multe restricții sunt suprapuse:

comanda SELECT nu poate returna mai multe seturi de rezultate;

comanda SELECT nu poate conține o expresie pentru a crea un nou tabel;

comanda SELECT nu poate conține o calculare sau calculată pe fraza utilizată pentru a agregate rezultatele. (Cu toate acestea, poate conține funcții de agregare, de exemplu, AVG.)

Caracteristicile cursorilor

Transact-SQL acceptă mai multe tipuri diferite de cursori. Aflați diferitele caracteristici ale fiecăruia dintre cursoare este o sarcină destul de plictisitoare, dar poate fi facilitată, dacă luați în considerare fiecare tip de cursor, trei caracteristici mai mult sau mai puțin independente: capacitatea de a reflecta modificările datelor sursă, Abilitatea de a derula o varietate de șiruri de caractere, precum și capacitatea de a modifica liniile setate.

Reflectarea schimbărilor

Abilitatea cursorului de a reflecta modificările datelor se numește sensibilitatea cursorului. Să presupunem că ați creat un cursor de operator:

Selectați * din uleiurile în care stânga (numele uleiului, 1) \u003d "B" Baza de date de aromoterapie va returna patru linii așa cum se arată în figura 1. Dacă în procesul de utilizare a cursorului dvs., acesta adaugă valoarea descrierii pentru elementul Bergamot sau adăugați un șir pentru elementul Bayberry, ce se va întâmpla cu o multitudine de șiruri de caractere la care indică cursorul dvs.?

Smochin. 1. Baza de date de aromoterapie conține patru linii începând cu literele B.

Când creați cursorul, două tipuri de sensibilitate pot fi definite independent: Cum se schimbă ce rânduri sunt incluse în set (set de mai multe) și reflectarea modificărilor din liniile sursă.

Scrolling.

Cea de-a doua caracteristică a cursorului este abilitatea de a derula atât înainte cât și înapoi sau doar înainte. Aici este dilema Solenit pentru programare: viteza împotriva flexibilității. Cursoare consecutive (numai înainte) funcționează mult mai repede, dar au o flexibilitate mai mică.

Actualizați

Ultima caracteristică utilizată pentru clasificarea cursorilor este capacitatea de a actualiza șirul cu cursorul. Din nou, cursorii "citiți numai" sunt de obicei mai productivi, dar au mai puține flexibilitate.

Tipuri de cursori

TRANSACT-SQL suportă patru tipuri diferite de cursori: cursoare statice, cheie, dinamice și acces rapid sau foc. Fiecare tip de cursor stochează diverse date referitoare la liniile la care indică, în plus, fiecare tip de cursor se caracterizează prin diferite combinații ale caracteristicilor discutate în secțiunea anterioară.

Cursoare statice

Cursorul static face un instantaneu al datelor setat de către instrucțiunea SELECT și le stochează în baza de date TEMPDB. Aceasta "nu se simte" schimbări în structură sau în valorile datelor, iar deoarece orice modificări vor fi reflectate numai în copiile, acest cursor se deschide întotdeauna în modul "Citește numai". Cursoare statice pot fi declarate ca fiind consistente sau ca derulare.

Cursuri cheie

Cursorul cheie copiază numai acele coloane în baza de date tempdb care sunt identificate în mod unic fiecare șir. Pentru a putea anunța cursorul cheie, fiecare tabel, care este în definiția instrucțiunii SELECT, trebuie să aibă un indice unic care să stabilească cheia tastei.

Cursoarele cheie pot fi modificate și au mod "numai pentru citire". Ele pot fi, de asemenea, derulare sau secvențială.

Apartenența la cursorul cheie este fixată în momentul anunțului cursorului. Dacă se adaugă un șir în timpul starea deschisă a cursorului care satisface starea de selecție, acesta nu va fi adăugat la set. În exemplul nostru anterior, stânga (nume de ulei, 1) \u003d "B" a fost utilizată ca stare de selecție, noua linie cu numele de ulei "Bayberry Field" nu va fi adăugată la șirurile legate de câmpul cursor.

În mod similar, dacă schimbarea este introdusă într-un șir, care nu va îndeplini condiția de membru în set, de exemplu, înlocuirea "busuioc" pe "Kumquat", șirul va rămâne în continuare membru al setului. Chiar dacă șirul este eliminat, acesta rămâne în continuare un membru al setului, dar SQL Server returnează NULL pentru toate valorile coloanei.

Deși apartenența într-un cursor multiplu după deschiderea cursorului rămâne fixă, cu toate acestea, modificările valorilor datelor efectuate tabelelor sursă sunt reflectate. De exemplu, schimbarea valorii câmpului Descriere pentru șirul de bergamot va fi returnată cursorului. Cu toate acestea, modificările seturilor multiple de taste sunt reflectate în cursoare numai dacă sunt efectuate în interiorul cursorului. În continuarea exemplului anterior, dacă valoarea câmpului de ulei a fost schimbată de la "busuioc" la "kumquat" în interiorul cursorului, cursorul va reveni "Kumquat". Dacă schimbarea a fost făcută de un alt utilizator, cursorul va reveni în continuare "busuioc".

Consiliu. După cum vom vedea în secțiunea următoare, crearea cursorului și deschiderea cursorului sunt operațiuni diferite. Pentru a actualiza conținutul cursorului cheie, puteți închide și re-deschide.

Cursuri dinamice

Cursorul dinamic se comportă ca și cum fiecare dată fiecare acces la șir a re-efectuat instrucțiunea SELECT. (De fapt, totul se întâmplă oarecum diferit, dar această performanță vă permite să judecați mai bine lucrarea cursorilor dinamice.) Cursoarele dinamice reflectă modificările legate de ambele valori ale datelor inițiale, indiferent dacă aceste modificări sunt făcute în cursor sau făcute de către Cursor un alt utilizator.

Pentru cursoarele dinamice există o limită: instrucțiunea de selectare utilizată pentru a defini cursorul poate conține comanda cu fraza numai dacă există un indice care include coloanele utilizate în ordinea cu fraza. Dacă declarați cursorul cheie utilizând comanda cu expresia care nu acționează indexul, SQL Server convertește cursorul la cheie.

Cursuri de acces rapid

Serverul SQL acceptă o formă optimizată specială a unui cursor nemărginit care permite citirii numai. Această vizualizare a cursorului este declarată utilizând cuvântul cheie Fast_forward, și cel mai adesea se numește cursor "Firehose".

Pompierii Cursoarele sunt foarte eficiente, dar când sunt utilizate, există două restricții importante. În primul rând, dacă ați utilizat coloane cu tipul de date text, NText sau de imagine în fraza Selectare și de sus, expresia SQL Server convertește cursorul la cheie.

În al doilea rând, dacă instrucțiunea selectată, pe care ați folosit-o pentru a determina cursorul, conține tabele care au declanșatoare și mese care nu au declanșatoare, cursorul este transformat în static. Declanșatoarele sunt scripturile TRANSACTION-SQL care sunt executate automat de către server atunci când execută tabelul de operator de manipulare a datelor (DML). Mai multe detalii considerăm declanșatoare în clasa 29, acum vom acorda atenție la următorul punct: Dacă cineva adaugă un declanșator la unul dintre mesele folosite de cursor, aplicația dvs. poate opri brusc execuția, deoarece SQL Server convertește un cursor mai rapid în mai puțin rapid.

Utilizarea cursorilor

Utilizarea cursorilor ca utilizarea variabilelor locale - le declarați, setați valoarea, apoi utilizați. Cu toate acestea, spre deosebire de variabilele locale care sunt distruse automat atunci când este de ieșire câmpul de acțiune, trebuie să eliberați în mod explicit șirul utilizat de cursor și apoi să distrugeți cursorul.

Crearea cursorilor

Primul pas în utilizarea cursorului este crearea sa. Cursorii tranzacționați-SQL sunt creați utilizând operatorul cursorului declarați.

Atenţie! Serverul SQL acceptă două metode diferite de creare a cursorului: utilizând sintaxa SQL-92 și utilizând sintaxa TRANSACT-SQL. Sintaxa SQL-92 se potrivește cu standardul ANSI, dar are o funcționalitate mai mică decât sintaxa TRANSACT-SQL, care este considerată aici.

Operatorul cursorului declarați are următoarea sintaxă:

Declarați numele cursorului

[vizibilitate]

[Sul]

[Lacăt]

Pentru operator_sets.

Rețineți că toți parametrii care determină caracteristicile cursorului - vizibilitate, tip etc. - sunt opționale. Valorile implicite pentru acești parametri sunt complexi și pot indica sau nu specifică modalități de a interacționa cu înregistrările sursei sau vizualizările, precum și opțiunile pentru lucrul cu baza de date. Pentru a face percepția operatorului mai confortabil, este mai bine să setați în mod explicit toți parametrii de care aveți nevoie. În același timp, veți ști exact ce obțineți.

Vizibilitatea cursorului este determinată utilizând cuvintele cheie ale local sau globale, care au același efect ca și cuvintele cheie @Local_table sau @@ Global_table atunci când se declară mese temporare.

Consiliu. Serverul SQL va închide și va elibera cursorul local atunci când părăsi limitele zonei de acțiune (vizibilitate), dar este mai bine să o faceți întotdeauna în mod clar.

Parametrul de derulare vă permite să utilizați cuvintele cheie Forward_ONly și derulați, care sunt specificate, respectiv, posibilitatea de a se deplasează numai de la început până la capăt sau în orice direcție.

Parametrul de tip definește tipul de cursor creat. Iată cuvintele cheie ale static, keyset, dinamic și rapid_forward. Parametrul de tip Fast_forward și parametrul de derulare înainte de difuzare se exclud reciproc.

Parametrul de blocare determină dacă șirurile pot fi modificate de cursor și, dacă este cazul, alți utilizatori să le modifice. Dacă se utilizează cuvântul cheie Citit_Only, cursorul nu poate modifica datele sursă. Cu toate acestea, alți utilizatori pot modifica datele sau puteți face acest lucru utilizând instrucțiunea de actualizare. Dacă parametrul de blocare specificat Scroll_locks, actualizările pot fi efectuate numai de cursor. Toate celelalte declarații de actualizare, atât în \u200b\u200binteriorul aceluiași pachet, cât și de alți utilizatori nu vor fi executați.

Ultima opțiune de blocare, optimistă, vă permite să actualizați șirurile atât în \u200b\u200bcursor cât și în afara acesteia. Aceasta este opțiunea cea mai flexibilă, dar există întotdeauna probabilitatea ca modificarea făcută de cursor să fie finalizată dacă șirul a fost modificat după ce citește cursorul.

Parametrul Type_Warning prescrie serverul SQL pentru a trimite un mesaj de avertizare clientului dacă tipul cursorului este convertit de tipul specificat la un alt tip. Acest lucru este posibil dacă declarați un cursor care nu acceptă instrucțiunea selectată specificată.

Parametrul operator_selfs, specificat în fraza pentru, este obligatoriu. Specifică liniile care vor fi incluse în multe cursori.

Expresia pentru actualizare este opțională. În mod implicit, cursorurile sunt modificate dacă parametrul READ_ONLY nu este specificat, dar în acest caz este mai bine să utilizați această frază pentru a fi încrezător în rezultatul rezultat. Puteți utiliza secțiunea de nume_stolbets pentru a specifica anumite linii pentru care admite o modificare. Dacă coborâți secțiunea de nume_lbs, modificarea poate fi efectuată pentru toate coloanele specificate în instrucțiunea SELECT.

Cursor variabiles.

Transact-SQL vă permite să declarați variabile, cum ar fi cursorul. În acest caz, sintaxa standard declarată nu creează un cursor; Trebuie să setați în mod explicit variabila pentru cursor utilizând cuvântul cheie set.

Declarați cursorul Mycursor.

Pentru selectarea numelui de ulei din uleiuri

Declară cursorul @mycursorvariabil

Set @mycursorvariable \u003d MyCrsor

Această sintaxă este utilă dacă doriți să creați variabile care pot fi atribuite diferitelor cursori. Acest lucru poate fi necesar dacă creați o procedură generalizată pentru a lucra cu seturi de rezultate diferite.

Puteți declara o variabilă cursor și apoi utilizați-o pentru a crea direct un cursor.

Declarați @MyCurSorbiable Cursor Set @mycursorVariable \u003d Cursor local Fast_Forward pentru selectați Nume de ulei din uleiuri

Când utilizați o astfel de sintaxă, cursorul nu are un identificator, iar referința la acesta poate fi efectuată numai prin variabila.

Deschiderea unui cursor

Declarația cursorului creează un obiect cursor, dar nu creează un set de înregistrări pe care cursorul va manipula (cursorul multiplu). Multe cursori nu sunt create până când nu deschideți cursorul. După o sintaxă suficient de complexă a operatorului de cursor declarați, sintaxa operatorului pare destul de transparentă:

Deschideți cursor_ili_named.

Cuvântul cheie global ajută la evitarea conflictelor: Dacă cursorul a declarat cu cuvântul cheie local, iar cursorul anunțat cu cuvântul cheie global au același identificator, legăturile cursorului vor fi detectate în mod implicit la cursorul local dacă nu ați utilizat globalul cuvânt cheie. Ca și în alte cazuri similare, este mai bine să specificați în mod explicit un cuvânt cheie dacă deschideți cursorul global.

Cursor de închidere

După terminarea utilizării cursorului, trebuie să o închideți. Operatorul apropiat eliberează resursele utilizate pentru a menține o multitudine de cursor și, de asemenea, eliberează toate încuietorile implicate pe șiruri dacă ați utilizat parametrul Derrollock în declarația declarație. Închiderea sintaxei de comandă este aproape identică cu Sintaxa Operatorului Open - Numai cuvântul cheie se modifică:

Închideți cursor_ili_named.

Cursorul de eliberare

Ultimul operator în succesiunea acțiunilor legate de crearea cursorului este operatorul deformocalizat. Sintaxa este, de asemenea, simplă:

Deallococare cursor_ili_named.

Cu toate acestea, există o subtilitate: Operatorul DelLoca îndepărtează identificatorul sau variabila cursorului, dar nu elimină neapărat cursorul în sine. Cursorul în sine nu este șters până când toți identificatorii la care se referă vor fi eliberați sau vor înceta să acționeze (când părăsesc gama de acțiune). Luați în considerare următoarele exemple:

Crearea unui Cursor Cursor Cursor declarați pentru selectați * din uleiuri - Crearea unei variabile de cursor declară @curSorvariable Cursor - Crearea unui set de înregistrări ale cursorului Mycursor deschis - Scopul setului @CrSorvariable \u003d Cursor variabil curentă curentă

După eliberarea cursorului, identificatorul de mycursori nu mai este asociat cu o multitudine de cursor, dar din moment ce variabila @CrSorvariable, cursorul și multe cursor nu sunt scutite de setul de cursor. Dacă sunteți în mod clar eliberat, de asemenea, variabila cursorului, cursorul și multe cursori vor exista până când variabila își va pierde acțiunea.

Manipularea șirurilor folosind cursorul

Cursorii înșiși nu ar face nici un interes dacă nu ați putea exercita anumite acțiuni cu ajutorul lor. TRANSACT-SQL acceptă trei comenzi diferite pentru a lucra cu cursorii: Fetch, Update și Ștergere.

Comanda Fetch recuperează șirul specificat dintr-o varietate de corzi de cursor. În versiunea sa simplă, comanda Fetch are următoarea sintaxă:

FETCH CURSOR_ILI_NAME.

În acest format de înregistrare, un șir este returnat poziției cursorului (linia curentă).

Utilizați o comandă simplă

  1. Accesați folderul SQL 2000 pas cu pas din directorul rădăcină, evidențiați scriptul numit SimpleCursor și faceți clic pe Deschidere (Deschidere).
  2. Analizor de interogare va descărca scriptul la fereastra de interogare.

Consiliu. Puteți observa că acest script este executat mai mult decât instrucțiunea de selectare corespunzătoare. Faptul este că crearea și deschiderea cursorului necesită un timp suplimentar. Nu utilizați niciodată cursorul dacă instrucțiunea selectată este suficientă pentru a executa sarcina.

Comanda Fetch nu numai că va returna șirul direct, dar vă permite să salvați valori din coloana returnată în variabile. Pentru a salva rezultatele comenzii de preluare în variabilă, utilizați următoarea sintaxă:

Fetch Cursor_yli_nament în List_name

List_name este o listă de identificatori variabili separați prin virgule. Înainte de a executa comanda Fetch, trebuie să declare variabile. List_name ar trebui să conțină o variabilă pentru fiecare coloană care apare în instrucțiunea SELECT, care definește cursorul. Tipul de date al variabilei trebuie să coincidă sau să fie compatibil cu tipul de date al coloanei.

Selectați rândurile cu înregistrarea acesteia în variabile.

În toate exemplele anterioare, operatorul de preluare a fost utilizat pentru a returna linia curentă. Sintaxa operatorului de preluare oferă, de asemenea, un număr de cuvinte cheie pentru a specifica un alt șir. Când utilizați aceste cuvinte cheie, operatorul de preluare va returna un șir specificat și va face curentul.

Aceste cuvinte cheie vă oferă posibilitatea de a stabili o poziție absolută într-un cursor multiplu. Cuvintele cheie, prima și ultima returnare primele și ultimele șiruri de caractere, respectiv, în timp ce Absolut N stabilește un șir care este situat pe N șiruri de la început (dacă n pozitiv) sau la capăt (dacă n este negativ) un set de înregistrări ale cursorului. Valoarea N poate fi exprimată ca o constantă (3) sau ca variabilă (@therow).

Selectați linii prin poziția lor absolută.

  1. Evidențiați scriptul numit FetchAbsolute și faceți clic pe Deschidere (Deschidere). Analizor de interogare va descărca scriptul la fereastra de interogare.

În plus față de cuvintele cheie, care dau capacitatea de a extrage șiruri în poziția absolută, operatorul de preluare oferă trei cuvinte cheie care vă permit să extrageți șiruri de caractere în funcție de linia curentă. Următorul operator de preluare returnează următoarea linie, operatorul prealabil preluat returnează linia anterioară, iar operatorul relativ de preluare returnează un șir care este situat pe no șiruri de la curent. La fel ca operatorul Absolut Net, operatorul relativ Fetch poate seta șirurile care precedă curentul dacă N este negativ, iar șirurile care urmează cele curente dacă n este pozitiv.

Selectați rândurile de poziție relativă

  1. Evidențiați scriptul numit FetchRelativ și faceți clic pe Deschidere (Deschidere). Analizor de interogare va descărca scriptul la fereastra de interogare.

Dacă cursorul are un tip Forward_Only sau Past_forward, numai cuvântul cheie poate fi utilizat pentru a specifica poziția. De fapt, dacă cursorul se referă la unul dintre aceste tipuri, următorul cuvânt cheie nu este necesar. SQL Server presupune că fiecare declarație de preluare este de fapt o declarație următoare.

Utilizați declarația următoare pentru un cursor de mare viteză

  1. Evidențiați scriptul numit Fetchfirehose și faceți clic pe Deschidere (Deschidere). Analizor de interogare va descărca scriptul la fereastra de interogare.

Apăsați butonul Run interogare din bara de instrumente Query Analyzer Query Analyzer. Analizor de interogare va solicita.

Modificarea și îndepărtarea corzilor prin cursoare

Dacă cursorul dvs. este modificabil. Schimbarea valorilor inițiale într-un cursor multiple este destul de simplă. Se oferă o formă specială a frazei în care este furnizată o expresie care sprijină modificarea prin cursor:

Actualizați table_ili_presentation Set List_Modificare în cazul în care curentul de cursor_ili_named

Aceasta se numește o actualizare a poziției. Transact-SQL acceptă, de asemenea, îndepărtarea pozițională care are următorul formular de înregistrare:

Ștergeți table_ili_relasting unde este curent de cursu_ieli_tervened

Efectuați o actualizare a poziției

  1. Evidențiați scriptul numit PozițieDupdate și apăsați butonul Deschidere. Analizor de interogare va descărca scriptul la fereastra de interogare.

Faceți clic pe butonul Execute Query din bara de instrumente Analyzer Query Analyzer Query. Analizor de interogare va solicita. Vă rugăm să rețineți că sunt afișate două panouri de rețea. Primul este creat de operatorul de preluare și conține conținutul inițial al coloanelor. Al doilea este rezultatul executării instrucțiunii SELECT și conține valoarea câmpului de descriere după o modificare.

Monitorizarea cursorilor tranzacționați-SQL

Transact-SQL oferă două variabile globale și caracteristici care vă ajută să monitorizați lucrarea și starea cursorului dvs. Variabila @@ cursor_rows returnează numărul de rânduri într-o multitudine a ultimului cursor deschis în conexiune. Valorile returnate @@ Cursor_rows sunt prezentate în tabelul 1.

Variabila @@tch_Status returnează informații despre execuția ultimei comenzi Fetch. Tabelul 2 prezintă valorile returnate de variabila @@tch_Status.

În cele din urmă, Transact-SQL oferă funcția Cursor_Status. Această caracteristică are următoarea sintaxă:

Cursor_status (tip, cursor_ini_named) poate avea "local", "global" sau "variabil", iar Cursor_im_name este un identificator cursor sau variabil de cursor, care este necesar pentru care doriți să obțineți. Rezultatele returnate de funcția Cursor_Status sunt prezentate în Tabelul 3.

Utilizați caracteristicile de monitorizare ale cursorului

  1. Evidențiați scriptul de stareFunctions și faceți clic pe Deschidere (Deschideți). Analizor de interogare va descărca scriptul la fereastra de interogare.

Versiune tipărită

Explicit Cursor este comanda SELECT, definită în mod explicit în secțiunea ADS-uri program. Când declarați un cursor explicit, i se atribuie un nume. Pentru introducerea, actualizarea, îmbinarea și ștergerea comenzilor, cursoarele explicite nu pot fi determinate.

Prin definirea comenzii SELECT ca cursor explicit, programatorul primește controlul asupra principalelor etape ale eșantionului de informații din baza de date Oracle. Definește când deschideți cursorul (deschis) când să selectați un șir (preluați) de la acesta, cât de mult să selectați rândurile și când doriți să închideți cursorul utilizând comanda Închidere. Informațiile despre starea curentă a cursorului sunt disponibile prin atributele sale. Este detaliat mare de control care face cursoare explicite un instrument neprețuit pentru un programator.

Luați în considerare un exemplu:

1 FUNCTION JEALOSY_LEVEL (2 NAME_IN IN FRIENDS.NAME% TIP) RETURN NUOR 3 AS 4 CURSORUL JEALOUSY_CUR 5 este 6 Selectați locația de la prieteni 7 unde este numele \u003d superior (name_in); 8 8 jealousy_rec jealousy_cur% Rowtype; 9 numărul de retval; 10 începe 11 deschis jealousy_cur; 13 12 Fetch jelozy_cur în jealousy_rec; 15 13 Dacă jealousy_cur% a găsit 14 apoi 15 dacă jealousy_rec.locație \u003d "Puerto Rico" 16 apoi retval: \u003d 10; 17 Elsif jealousy_rec.Location \u003d "Chicago" 18 apoi Retval: \u003d 1; 19 sfârșitul dacă; 20 de sfârșit dacă; 24 21 Închideți jealousy_cur; 26 22 Retov Retval; 23 Excepție 24 Când alții, apoi 25, dacă jealousy_cur% izopen, atunci 26 închis jealousy_cur; 27 sfârșitul dacă; 28 capăt;

În mai multe secțiuni apropiate, fiecare dintre operațiunile listate este considerată în detaliu. Termenul "cursor" din ele se referă la cursoare explicite, cu excepția cazului în care opusul este indicat în mod clar în text.

Anunțarea unui cursor explicit

Pentru a face capacitatea de a utiliza un cursor explicit, acesta trebuie anunțat în secțiunea PL / SQL Block AD sau pachetul:

Cursor_name [([parametru [, parametru ...])] [Return Specification_Select] este comanda_select];

Aici numele cursorului este numele cursorului anunțat; SpeedIPHISHCIA_T? IT - Secțiunea opțională Returnare; Komahdasect - orice SQL permisibil Selectați. Cursorul poate, de asemenea, să treacă parametrii (vezi următoarea "Cursor Setări"). În cele din urmă, după comanda Selectați ... Pentru comanda de actualizare, puteți seta o listă de coloane de actualizare (vezi mai jos). După anunț, cursorul se deschide cu comanda deschisă, iar selectarea rândurilor de la acesta este efectuată de comanda Fetch.

Câteva exemple de anunțuri de cursoare explicite.

  • Cursorul fără parametri. Setul rezultat de linii din acest cursor este un set de identificatori ai companiei selectați din toate rândurile tabelului:
Cursor Company_Cur este selectat Company_id de la companie;
  • Cursor cu parametri. Setul rezultat de linii din acest cursor conține un singur șir cu numele companiei care corespunde valorii parametrului transmis:
Cursor name_cur (companie_id_in în număr) se selectează numele de la companie_id_in;
  • Return Cursor.. Setul rezultat de linii din acest cursor conține toate datele tablelor angajaților pentru o unitate cu 10 identificator:
Cursor EMP_CUR Întoarcerea angajaților% RowType este selectată * de la angajați în cazul în care departamentul_id \u003d 10;

Numele cursorului.

Denumirea cursorului explicit trebuie să aibă o lungime de până la 30 de caractere și să corespundă acelorași reguli ca și identificatorii rămași PL / SQL. Numele cursorului nu este o variabilă - acesta este identificatorul indicatorului la cerere. Numele cursorului nu este atribuit valorii, nu poate fi aplicat în expresii. Cursorul este utilizat numai în comenzile deschise, apropiate și de preluare, precum și pentru a clarifica atributul cursor.

Publicitate cursor în pachet

Cursoarele explicite sunt anunțate în anunțurile Block PL / SQL. Cursorul poate fi declarat la nivelul pachetului, dar nu într-o procedură specifică sau o funcție de pachete. Un exemplu de anunțuri de două cursoare în pachet:

Pachetul Book_info este cursorul Titles_Cur este selectat Titlu din cărți; Cursor Books_Cur (titlu_filter_in in Cartes.title% Tip) Return Books% RowType este selectat * din cărți unde titlul ca Title_filter_in; Sfârșit;

Primul cursor Titls_Cur returnează doar titlurile de carte. Cel de-al doilea, cărți_cur, returnează toate liniile tabelului de cărți, în care numele cărților corespund șablonului specificat ca parametru cursor (de exemplu, "toate cărțile care conțin șirul PL / SQL"). Vă rugăm să rețineți: În cel de-al doilea cursor, se utilizează secțiunea de returnare, care declară structura de date returnată de comanda Fetch.

În secțiunea de returnare, oricare dintre următoarele structuri de date poate fi indicată:

  • Înregistrarea definită pe baza șirului de tabel de date utilizând atributul% Rowtype.
  • O intrare definită pe baza unui alt cursor anunțat anterior utilizează, de asemenea, atributul% Rowtype.
  • O înregistrare definită de programator.

Numărul de expresii din lista de eșantionare a cursorului trebuie să corespundă numărului de coloane de înregistrare NAME_TABLE% ROWTYPE, KYPCOP% ROWTYPE sau TIP DE ÎNREGISTRARE. Tipurile de elemente de date ar trebui, de asemenea, să fie compatibile. De exemplu, dacă al doilea element al listei de eșantionare are un tip de număr, atunci cea de-a doua coloană de înregistrare din secțiunea de retur nu poate fi tip varchar2 sau boolean.

Înainte de a trece la o analiză detaliată a secțiunii de returnare și a avantajelor sale, să ne dăm seama mai întâi, de ce aveți nevoie de cursoare de anunțuri în pachet? De ce să nu declarați un cursor explicit în programul în care este utilizat - în procedură, funcție sau un bloc anonim?

Răspunsul este simplu și convingător. Prin definirea cursorului în pachet, puteți repeta solicitarea specificată în acesta, fără a repeta același cod în diferite locuri ale aplicației. Punerea în aplicare a cererii într-un singur loc simplifică rafinamentul său și sprijinul codului. Unele economii de timp se realizează prin reducerea numărului de procese de recuperare.

De asemenea, merită să luați în considerare capacitatea de a crea o funcție care returnează variabila cursorului bazată pe Cursor Ref. Programul de apelare efectuează o probă de șiruri prin variabila cursorului. Pentru mai multe informații, consultați secțiunea "Variabilele cursorului și Ref Cursor".

Anunță cursorii în pachete pentru reutilizare, ar trebui luată în considerare o circumstanță importantă. Toate structurile de date, inclusiv cursorurile declarate la "nivelul pachetului" (nu într-o anumită funcție sau procedură), să-și păstreze valorile pe tot parcursul sesiunii. Aceasta înseamnă că cursorul lot va rămâne deschis până când îl închideți în mod clar sau până când sesiunea este finalizată. Cursorii declarați în blocurile locale sunt închise automat când aceste blocuri sunt finalizate.

Și acum să ne ocupăm de secțiunea de întoarcere. Anunțurile cursorului din pachet există o caracteristică interesantă: poziția cursorului poate fi separată de corpul său. Un astfel de antet, mai asemănător cu un antet de funcții, conține informații necesare pentru un programator de lucru: numele cursorului, parametrii acestuia și tipul de date de returnare. Cursorul este comanda Selectare. Această recepție este demonstrată în noua versiune a cursorului cărți_cur din pachetul de carte_info:

Pachet Book_info este Cursor Book_Cur (titlu_filter_in în cărți. Tipul de tip) Returnați cărțile% Rowtype; Sfârșit; Pachetul Body Book_info este Cursor Book_Cur (titlu_filter_in în cărți. Tipul de tip) Returnare Cărți% Rowtype este selectat * din cărți unde titlul ca Title_filter_in; Sfârșit;

Toate caracterele înainte de cuvântul cheie este formularul de cuvânt al specificației și după ce urmează corpul cursorului. Separarea anunțurilor cursorului poate servi două goluri.

  • Ascunderea informațiilor. Cursorul din pachet este o "cutie neagră". Este convenabil pentru programatori, deoarece nu au nevoie să scrie sau chiar să vadă comanda SELECT. Este suficient să știți care înregistrări returnează acest cursor, în ce ordine și ce coloane conțin. Un programator care lucrează cu pachetul utilizează cursorul ca orice alt element finalizat.
  • Recompilare minimă. Dacă ascundeți definiția unei interogări în corpul pachetului, atunci modificările la comanda SELECT pot fi efectuate fără a modifica antetul cursorului în specificația pachetului. Acest lucru vă permite să vă îmbunătățiți, să corectați și să re-compilați codul fără a recompila specificația pachetului, datorită cărora programele în funcție de acest pachet nu vor fi marcate ca nevalide și nu vor fi necesare pentru a recompila.

Deschiderea cursorului explicit

Utilizarea cursorului începe cu definiția sa în secțiunea Anunțuri. Apoi, cursorul anunțat trebuie deschis. Sintaxa operatorului deschis este foarte simplă:

Deschide_name_name [(argument [, argument ...])];

Aici numele gazdei este numele cursorului anunțat anterior, iar argumentul este valoarea transmisă de cursor dacă este declarată cu lista parametrilor.

Oracle acceptă, de asemenea, pentru sintaxă atunci când deschideți un cursor, care este utilizat atât pentru variabilele cursorului (vezi secțiunea "Variabilele cursorului și Cursor") și pentru SQL dinamic încorporat.

Deschiderea cursorului, PL / SQL execută interogarea conținută în el. În plus, identifică un set activ de date - liniile tuturor participanților la interogarea tabelelor corespunzătoare în cazul în care criteriul și starea asociației. Open Comanda nu extrage date - aceasta este sarcina de comandă a preluării.

Indiferent de momentul primului eșantion de date, implementat în Oracle, modelul de integritate a datelor asigură că toate operațiunile de eșantionare vor returna datele din stat în momentul deschiderii cursorului. Cu alte cuvinte, de la deschidere și înainte de a închide cursorul, atunci când selectați datele din acesta, inserțiile, actualizările și ștergerile efectuate în acest timp sunt complet ignorate.

Mai mult, dacă comanda SELECT conține secțiunea Actualizare, toate cursorul identifică șirul este blocat când este deschis.

Când încercați să deschideți un cursor deschis PL / SQL va da următorul mesaj de eroare:

ORA-06511: PL / SQL: Cursor deja deschis

Prin urmare, înainte de a deschide cursorul, verificați starea acestuia prin valoarea atributului. % Este deschis:

Dacă nu sunt companiile_cur% izopen, atunci deschide company_cur; Terminați dacă;

Atributele cursorilor explicite sunt descrise mai jos, în secțiunea dedicată acestora.

Dacă programul este executat în ciclul utilizând cursorul, acest cursor nu are nevoie de o deschidere explicită (eșantion de date, închidere). Kernelul PL / SQL o face automat.

Selectarea datelor din cursorul explicit

Comanda SELECT creează o table virtuală - un set de șiruri de caractere definite de situația în care cu coloanele definite de lista Selectare coloane. Astfel, cursorul prezintă acest tabel în programul PL / SQL. Scopul principal al cursorului în programele PL / SQL este un eșantion de rânduri pentru procesare. Eșantionul șirului cursorului este executat de comanda Fetch:

Fetch in_name_name_name__named_named;

Aici numele cursorului este numele cursorului, din care este selectată înregistrarea și înregistrarea sau lista variabilelor - structurile de date PL / SQL în care este copiată următoarea linie a setului de înregistrări active. Datele pot fi plasate în intrarea PL / SQL (declarată cu atributul sau tipul% rând) sau la variabile (variabile PL / SQL sau variabilele de legare - ca, de exemplu, în elemente de forme Oracle).

Exemple de cursoare explicite

Următoarele exemple demonstrează modalități diferite de selectare a datelor.

  • Selectarea datelor din Cursor la înregistrarea PL / SQL:
Declarați Cursor Company_cur este selectat ...; Company_rec Company_Cur% RowType; Începe compania deschisă_cur; Fetch Company_Cur în companie_rec;
  • Selectarea datelor de la cursor la variabila:
Fetch New_balance_Cur în New_balance_dollars;
  • Selectarea datelor din cursor la șirul tabelului PL / SQL, Formele Oracle de legare variabilă și variabilă:
Fetch Emp_name_Cur în EMP_NAME (1), HIDIDATE: Dept.min_Salary;

Datele selectate din cursor trebuie plasate întotdeauna într-o înregistrare declarată bazată pe același cursor cu atributul% Rowtype; Evitați eșantionarea în listele variabile. Selectarea din înregistrare face ca codul să fie mai compact și mai flexibil, vă permite să modificați lista de eșantioane fără a schimba comanda Fetch.

Eșantionarea după prelucrarea ultimei linii

Deschiderea cursorului, selectați șirul de la acesta până când acestea sunt expuse. Cu toate acestea, și apoi puteți executa comanda Fetch.

Destul de ciudat, în acest caz PL / SQL nu inițiază o excepție. Nu face nimic. Deoarece nu aveți nimic mai mult de ales, valorile variabilelor din secțiunile de comandă Fetch nu se schimbă. Cu alte cuvinte, comanda Fetch nu stabilește valorile acestor variabile egale cu NULL.

Pseudonimele coloanelor unui cursor explicit

Comanda selectată în declarația cursorului determină lista coloanelor returnate. Împreună cu numele coloanelor meselor, această listă poate conține expresii numite coloanele calculate sau virtuale.

Coloana Alias \u200b\u200beste un nume alternativ specificat în comanda SELECT pentru o coloană sau o expresie. Prin specificarea pseudonimelor adecvate în SQL * Plus, puteți afișa rezultatele unei interogări arbitrare într-un formular ușor de citit. În astfel de situații, pseudonimele nu sunt obligatorii. Pe de altă parte, atunci când se utilizează cursoare pseudonim evidente, coloanele calculate sunt necesare în următoarele cazuri:

  • când selectați datele din cursor la intrarea anunțată cu atributul% Rowtype bazat pe același cursor;
  • când programul conține o legătură cu coloana calculată.

Luați în considerare următoarea solicitare. Comanda SELECT selectează numele tuturor companiilor care au comandat bunuri pe parcursul anului 2001, precum și cantitatea totală de comenzi (se presupune că, pentru instanța de date implicită curentă utilizează o mască de formatare DD-Mon-Yyyy):

Selectați compania_name, suma (INV_AMT) de la compania C, factura I unde c.com și i.invoice_date între "01-ianuarie 2001" și "31-Dec-2001";

La executarea acestei comenzi în SQL * Plus, se va obține următorul rezultat:

Numele companiei. Sumă (inv_amt)
Acme Turbo Inc. 1000
Washington Hair Co. 25.20

După cum puteți vedea, antetul de coloană sum este slab potrivit pentru raport, dar este destul de potrivit pentru vizualizarea simplă a datelor. Acum executați aceeași solicitare în programul PL / SQL utilizând un cursor explicit și adăugați un alias coloană:

Declara Cursor Comp_cur este selectați C.Name, suma (INV_AMT) total_sales de la compania C, factura I unde c.com și i.invoice_date între "01-ianuarie 2001 și" 31-Dec-2001 "; Comp_rec comp_cur% rowtype; Începe deschis comp_cur; Fetch comp_cur în comp_rec; Sfârșit;

Fără un pseudonim, nu mă pot referi la coloana din structura înregistrării COMP_REC. Dacă există un pseudonim cu o coloană calculată, puteți lucra în același mod ca și în cazul oricărei alte coloane de interogare:

Dacă comp_rec.total_sales\u003e 5000 decât dbms_output.putd_line ("ați depășit limita de credit de 5000 USD de către" || to_char (comp_rec.total_sales - 5000, "9999 $")); Terminați dacă;

La însămânțarea unui șir la o înregistrare declarată cu un atribut% ROWTYPE, accesul la coloana calculată poate fi obținut numai după nume - la urma urmei, structura de înregistrare este determinată de structura cursorului.

Închiderea unui cursor explicit

Odată ajuns în copilărie, ne-am învățat pentru ei înșiși, iar acest obicei a fost lăsat cu noi (deși nu toți) pentru viață. Se pare că această regulă joacă un rol extrem de important în programare și mai ales atunci când vine vorba de gestionarea cursorilor. Nu uitați niciodată să închideți cursorul dacă nu mai este nevoie!

Comanda sintaxă închide:

Close_name_name;

Mai jos este mai multe sfaturi importante și considerente legate de închiderea cursorilor explicite.

  • Dacă cursorul este declarat și deschis în procedură, nu uitați să o închideți după terminarea acestuia; În caz contrar, scurgerile de memorie vor apărea în codul dvs. Teoretic, cursorul (ca orice structură de date) trebuie să fie închis automat și distrus atunci când părăsiți zona de acțiune. De regulă, atunci când ieșiți din procedură, funcția sau blocul anonim PL / SQL închide cu adevărat toate cursorurile deschise în ea. Dar acest proces este asociat cu anumite costuri de resurse, prin urmare, din motive de eficacitate PL / SQL, uneori amână identificarea și închiderea cursorilor deschise. Cursoare, cum ar fi Cursorul Ref, prin definiție, nu pot fi închise implicit. Singurul lucru pe care îl puteți fi sigur este că la sfârșitul blocului PL / SQL extern, atunci când controlul va fi returnat la SQL sau alt apelant, PL / SQL va închide implicit cursorurile deschise de această unitate sau blocuri imbricate , Cu excepția Ref Cursor. Articolul "Reutilizarea cursorului în PL / SQL STIC SQL" din rețeaua Oracle Technology oferă o analiză detaliată a modului în care PL / SQL închide cursorurile. Blocurile anonime imbricate - un exemplu de situație în care PL / SQL nu efectuează închiderea implicită a cursorilor. Informații interesante despre acest subiect sunt date în articolul lui Jonathan Ghennik "PL / SQL implicit aproape cursoare?".
  • Dacă cursorul este declarat în pachetul pachet și este deschis într-un anumit bloc sau program, acesta va rămâne deschis până când îl închideți sau înainte de finalizarea sesiunii. Prin urmare, prin completarea muncii cu un cursor la nivel lot, acesta ar trebui să fie imediat aproape de comanda strânsă (și, apropo, același lucru trebuie făcut în secțiunea de excludere):
Începeți deschideți my_package.my_cronsor; ... Lucrăm cu Cursorul Închide My_package.my_CrSor; Excepție atunci când alții, atunci dacă MyPackage.My_CrSor% izopen Apoi închideți my_package.my_cronsor; Terminați dacă; Sfârșit;
  • Cursorul poate fi închis numai dacă a fost deschis mai devreme; În caz contrar, va fi inițiată o excepție invalid_curs0r. Starea cursorului este verificată utilizând atributul% ISOPEN:
Dacă compania_cur% izopen apoi închide compania_cur; Terminați dacă;
  • Dacă există prea multe cursoare deschise în program, numărul acestora poate depăși valoarea parametrului de bază de date Open_Cursori. După primirea unui mesaj de eroare, în primul rând, asigurați-vă că cursorurile declarate în pachete sunt închise după ce trebuie să dispară.

Atribute ale cursorilor explicite

Oracle suportă patru atribute (% găsite,% Nontfound,% izopen,% RowCountm) pentru a obține informații despre starea cursorului explicit. Referința la atribut are următoarea sintaxă: atributul cursor%

Aici Cursorul este numele cursorului anunțat.

Valorile returnate de atributele cursorilor explicite sunt prezentate în tabelul. unu.

Tabelul 1. Atribute ale cursorilor explicite

Valorile atributelor cursorului înainte și după executarea diferitelor operațiuni cu acestea sunt indicate în tabel. 2.

Lucrul cu atributele cursorilor explicite, este necesar să se ia în considerare următoarele:

  • Când încercați să contactați% Găsit,% Notfound sau% Rowcount atribut Înainte de a deschide cursorul sau după ce este închis, Oracle inițiază o excepție de la cursorul nevalid (ORA-01001).
  • Dacă, după prima execuție a comenzii Fetch, setul de rânduri rezultat va fi gol, atributele cursorului returnează următoarele valori:% găsit \u003d False,% Notfound \u003d Adevărat și% Rowcount \u003d 0.
  • Când utilizați cea mai mare parte, atributul% Rowcount returnează numărul de rânduri extrase în colecțiile specificate.

Masa 2. Valorile atributului cursorilor

Operațiune % Găsite. % Nu a fost gasit % Este deschis. % Rowcount.
A deschide O exceptie
ORA-01001.
O exceptie
ORA-01001.
Fals O exceptie
ORA-01001.
După deschidere NUL NUL Adevărat. 0
Înainte de prima preluare a probei NUL NUL Adevărat. 0
După primul eșantion
Fetch.
Adevărat. Fals Adevărat. 1
Înainte de următoarea ulterioară
Fetch.
Adevărat. Fals Adevărat. 1
După preturile ulterioare Adevărat. Fals Adevărat. Depinde de date
Înainte de ultima preluare a probei Adevărat. Fals Adevărat. Depinde de date
După ultima fabrică de preluare Adevărat. Fals Adevărat. Depinde de date
Înainte de închidere Fals Adevărat. Adevărat. Depinde de date
După aproape O exceptie O exceptie Fals O exceptie

Utilizarea tuturor acestor atribute este demonstrată în următorul exemplu:

Anterior în bloguri, exemple de utilizare a parametrilor procedurilor și funcțiilor au fost aduse în mod repetat. Parametrii reprezintă un mijloc de transmitere a informațiilor unui modul software și de la acesta. Cu utilizare corectă, ele fac module mai utile și mai flexibile.

PL / SQL vă permite să transferați parametrii cursorilor. Acestea îndeplinesc aceleași funcții ca parametrii modulelor software, precum și câteva suplimentare.

  • Extinderea utilizării multiple a cursorilor. În loc de codificare rigid în clauza În cazul în care valorile care definesc condițiile de selecție a datelor pot fi utilizate pentru a transfera noi valori acestei oferte cu fiecare deschidere a cursorului.
  • Rezolvarea problemelor legate de domeniul de aplicare al cursorilor. Dacă, în loc de valori codificate rigid, parametrii sunt utilizați în interogare, setul rezultat al rândurilor cursorului nu este legat de o variabilă specifică a programului sau a blocului. Dacă programul a fost imbricat blocuri, cursorul poate fi determinat la nivelul superior și îl utilizează în blocurile imbricate cu variabile declarate în ele.

Numărul parametrilor cursorului nu este limitat. La apelarea deschisă, valorile tuturor parametrilor trebuie specificate pentru cursor (cu excepția parametrilor pentru care sunt definite valorile implicite).

În ce cazuri sunt cursorii necesită parametri? Regula generală este aceeași ca și pentru proceduri și funcții: dacă se presupune că cursorul va fi utilizat în diferite locuri și cu valori diferite în secțiunea În cazul în care parametrul trebuie determinat pentru aceasta. Să comparăm cursorii cu parametrul și fără. Un exemplu de cursor fără parametri:

Cursor joke_cur este selectat nume, categorie, ultimul_uzd_date de la glume;

Setul de cursor rezultat include toate înregistrările tabelului de glumă. Dacă avem nevoie doar de un anumit subset al liniilor, în cazul în care secțiunea este inclusă în interogare:

Cursor Joke_Cur este selectat Nume, Categorie, Last_USED_Date de la glume în care categoria \u003d "soț";

Pentru a îndeplini această sarcină, nu am folosit parametrii, dar nu sunt necesare. În acest caz, cursorul returnează toate rândurile legate de o anumită categorie. Dar cum să fie dacă, cu fiecare apel la acest punct, categoria se schimbă?

Cursorii cu parametri

Desigur, nu vom defini un cursor separat pentru fiecare categorie - acest lucru este complet incompatibil cu principiul dezvoltării aplicațiilor gestionate de date. Avem nevoie de un singur cursor, dar astfel încât ar fi posibil să se schimbe categoria - și ar putea returna informațiile necesare. Și cea mai bună (deși nu singura) soluția la această sarcină este de a defini un cursor parametrizat:

Procedură Explaf_Joke (Main_Category_in în Joke_Category.Category_id%) este / * || Cursor cu o listă de parametri constând || De la singurul parametru de șir. * / Cursor gloke_cur (Category_in in Varchar2) este selectat Nume, Categorie, Last_USED_Date de la glumă unde categoria \u003d superioară (categoria_in); Gloke_rec gloke_cur% rowtype; Începe / acum, când deschideți cursorul, este transmis argumentul * / deschis gloke_cur (Main_Category_in); Fetch gloky_cur în gloke_rec;

Între numele cursorului și cuvântul cheie este acum conține o listă de parametri. Valoarea soțului rigid codificat în clauza în care este înlocuită cu referire la parametrul superior (Category_in). La deschiderea cursorului, puteți seta valoarea soțului, soțului sau soțului - Cursorul va funcționa în continuare. Numele categoriei pentru care cursorul trebuie să returneze rândurile de masă, este setat în instrucțiunea deschisă (în paranteze) ca un literal, constante sau expresii. La momentul deschiderii cursorului, comanda SELECT este parsarea și parametrul este asociat cu valoarea. Apoi setul de rânduri rezultat este determinat - și cursorul este pregătit pentru eșantion.

Deschiderea unui cursor cu parametri

Noul cursor poate fi deschis cu orice categorie:

Open Joke_Cur (glokes_pkg.category); Open Joke_cur ("soț"); Deschideți Joke_cur ("politician"); Deschis glok_cur (gloks_pkg.relation || "-la lege");

Parametrii cursorului sunt cei mai des utilizați în cazul în care este cazul, dar vă puteți referi la acestea în alte locuri Selectați comanda:

Declarați cursorul Joke_cur (Category_in în Archar2) este selectat Nume, Categorie_in, Last_USED_Date de la glumă în cazul în care categoria \u003d superioară (categoria_in);

În loc să citiți o categorie din tabel, pur și simplu înlocuim parametrul Categorie_in din lista de eșantioane. Rezultatul rămâne același, deoarece condiția în care limitează categoria de probă a valorii parametrului.

Zona parametrilor cursorului

Domeniul de aplicare al parametrului cursorului este limitat la acest cursor. Parametrul cursorului nu poate fi referit la comanda SELECT asociată cu cursorul. Fragmentul PL / SQL de mai jos nu este compilat deoarece identificatorul programului_name nu este o variabilă locală în bloc. Acesta este un parametru cursor formal care este definit numai în interiorul cursorului:

Declarați cursorul Scariness_Cur (program_name Varchar2) este suma selectată (scary_level) total_scary_level de la Tales_From_The_Crypt unde prog_name \u003d program_name; Începeți programul_name: \u003d "Mumia de respirație"; / * Link nevalid * / Deschidere Scariness_Cur (program_name); .... Închide Scariness_Cur; Sfârșit;

Modurile parametrilor cursorului

Sintaxa parametrilor cursorului este foarte asemănătoare cu sintaxa procedurilor și funcțiilor - cu excepția faptului că cursorurile pot fi doar parametri în. Pentru cursoare, nu puteți specifica modurile OUT sau IN OUT. Aceste moduri vă permit să transferați și returnați valorile din procedurile pe care nu le are sens pentru cursor. Există o singură modalitate de a obține informații din cursor: o selecție de valori de înregistrare și de copiere din lista de coloane din secțiunea în secțiune

Valorile implicite ale parametrilor

Parametrii cursorului pot fi alocați prin valori implicite. Exemplu de cursor cu valoarea parametrului implicit:

Cursor emp_cur (număr EMP_ID_IN: \u003d 0) este selectat angajat_id, emp_name de la angajat unde angajat_id \u003d emp_id_in;

Deoarece valoarea implicită este definită pentru parametrul EMP_ID_IN, nu vă puteți specifica valoarea acestuia în comanda Fetch. În acest caz, cursorul va returna informații despre angajatul cu codul 0.