Kursor u SQL Serveru je d atabase objekt koji nam omogućuje da dohvatimo svaki red po red i manipuliramo njegovim podacima . Kursor nije ništa više od pokazivača na red. Uvijek se koristi zajedno s naredbom SELECT. Obično je to zbirka SQL logika koja prolazi kroz unaprijed određeni broj redaka jedan po jedan. Jednostavna ilustracija pokazivača je kada imamo opsežnu bazu podataka o radnicima i želimo izračunati plaću svakog radnika nakon odbitka poreza i dopusta.
SQL poslužitelj svrha pokazivača je ažurirati podatke red po red, promijeniti ih ili izvršiti izračune koji nisu mogući kada dohvaćamo sve zapise odjednom . Također je koristan za obavljanje administrativnih zadataka kao što su sigurnosne kopije baze podataka SQL Servera u sekvencijalnom redoslijedu. Kursori se uglavnom koriste u razvojnim, DBA i ETL procesima.
Ovaj članak objašnjava sve o kursoru SQL Servera, kao što je životni ciklus kursora, zašto i kada se kursor koristi, kako implementirati kursore, njihova ograničenja i kako možemo zamijeniti kursor.
Životni ciklus kursora
Možemo opisati životni ciklus kursora u pet različitih odjeljaka kako slijedi:
1: Deklarirajte kursor
Prvi korak je deklarirati kursor koristeći donju SQL naredbu:
stringbuilder
DECLARE cursor_name CURSOR FOR select_statement;
Kursor možemo deklarirati navodeći njegovo ime s tipom podataka CURSOR nakon ključne riječi DECLARE. Zatim ćemo napisati naredbu SELECT koja definira izlaz za kursor.
2: Otvaranje kursora
To je drugi korak u kojem otvaramo kursor za pohranjivanje podataka dohvaćenih iz skupa rezultata. To možemo učiniti pomoću donje SQL naredbe:
OPEN cursor_name;
3: Dohvaćanje kursora
To je treći korak u kojem se retci mogu dohvaćati jedan po jedan ili u bloku radi manipulacije podacima poput operacija umetanja, ažuriranja i brisanja na trenutno aktivnom retku u pokazivaču. To možemo učiniti pomoću donje SQL naredbe:
FETCH NEXT FROM cursor INTO variable_list;
Također možemo koristiti @@FETCHSTATUS funkcija u SQL Serveru da biste dobili status posljednjeg kursora FETCH naredbe koji je izvršen na kursoru. The DOHVATI naredba je bila uspješna kada @@FETCHSTATUS daje nulti izlaz. The DOK naredba se može koristiti za dohvaćanje svih zapisa iz kursora. Sljedeći kod to jasnije objašnjava:
WHILE @@FETCH_STATUS = 0 BEGIN FETCH NEXT FROM cursor_name; END;
4: Zatvori kursor
To je četvrti korak u kojem kursor treba zatvoriti nakon što završimo rad s kursorom. To možemo učiniti pomoću donje SQL naredbe:
CLOSE cursor_name;
5: Poništite kursor
To je peti i posljednji korak u kojem ćemo izbrisati definiciju kursora i osloboditi sve sistemske resurse povezane s kursorom. To možemo učiniti pomoću donje SQL naredbe:
DEALLOCATE cursor_name;
Upotreba kursora SQL Servera
Znamo da su sustavi za upravljanje relacijskim bazama podataka, uključujući SQL Server, izvrsni u rukovanju podacima o skupu redaka koji se nazivaju skupovi rezultata. Na primjer , imamo stol tablica_proizvoda koji sadrži opis proizvoda. Ako želimo ažurirati cijena proizvoda, zatim u nastavku ' AŽURIRAJ' upit će ažurirati sve zapise koji odgovaraju uvjetu u ' GDJE' klauzula:
UPDATE product_table SET unit_price = 100 WHERE product_id = 105;
Ponekad aplikacija mora obraditi retke na pojedinačni način, tj. red po red, a ne cijeli skup rezultata odjednom. Ovaj proces možemo izvesti pomoću kursora u SQL Serveru. Prije korištenja pokazivača, moramo znati da pokazivači imaju vrlo loše performanse, tako da ih uvijek treba koristiti samo kada nema druge opcije osim kursora.
Kursor koristi istu tehniku kao što mi koristimo petlje poput FOREACH, FOR, WHILE, DO WHILE za ponavljanje jednog po jednog objekta u svim programskim jezicima. Stoga se može odabrati jer primjenjuje istu logiku kao i proces petlje u programskom jeziku.
Vrste kursora u SQL Serveru
Sljedeće su različite vrste kursora u SQL Serveru navedene u nastavku:
- Statički kursori
- Dinamički kursori
- Pokazivači samo prema naprijed
- Kursori skupa tipki
Statički kursori
Skup rezultata prikazan statičkim kursorom uvijek je isti kao kada je kursor prvi put otvoren. Budući da će statički kursor pohraniti rezultat u tempdb , uvijek su samo za čitanje . Možemo koristiti statički pokazivač za pomicanje naprijed i natrag. Za razliku od drugih kursora, sporiji je i zauzima više memorije. Kao rezultat toga, možemo ga koristiti samo kada je potrebno pomicanje, a drugi pokazivači nisu prikladni.
Ovaj pokazivač prikazuje retke koji su uklonjeni iz baze podataka nakon što je otvorena. Statički kursor ne predstavlja nikakve operacije INSERT, UPDATE ili DELETE (osim ako je kursor zatvoren i ponovno otvoren).
Dinamički kursori
Dinamički kursori suprotni su statičkim kursorima koji nam omogućuju izvršavanje operacija ažuriranja, brisanja i umetanja podataka dok je kursor otvoren. to je prema zadanim postavkama moguće je pomicati . Može detektirati sve promjene napravljene na redovima, redoslijedu i vrijednostima u skupu rezultata, bilo da se promjene događaju unutar pokazivača ili izvan njega. Izvan pokazivača ne možemo vidjeti ažuriranja dok se ne predaju.
Kursori samo prema naprijed
To je zadana i najbrža vrsta kursora među svim kursorima. Naziva se kursorom samo za naprijed jer kreće se samo naprijed kroz skup rezultata . Ovaj kursor ne podržava pomicanje. Može dohvatiti samo retke od početka do kraja skupa rezultata. Omogućuje nam izvođenje operacija umetanja, ažuriranja i brisanja. Ovdje su vidljivi učinci operacija umetanja, ažuriranja i brisanja koje je izvršio korisnik, a koje utječu na retke u skupu rezultata dok se redovi dohvaćaju s kursora. Kada je red dohvaćen, ne možemo vidjeti promjene napravljene na redovima kroz kursor.
Kursori samo naprijed su tri kategorizirani u tri vrste:
harald baldr
- Forward_Only Keyset
- Forward_Only Static
- Fast_Forward
Pokazivači vođeni skupom tipki
Ova funkcija kursora nalazi se između statičkog i dinamičkog kursora u pogledu njegove sposobnosti otkrivanja promjena. Ne može uvijek otkriti promjene u članstvu skupa rezultata i redoslijedu kao statički kursor. Može otkriti promjene u vrijednostima redaka skupa rezultata poput dinamičkog kursora. Može samo pomaknite se od prvog do zadnjeg i posljednjeg do prvog reda . Redoslijed i članstvo su fiksirani kad god se ovaj pokazivač otvori.
Njime upravlja skup jedinstvenih identifikatora koji su isti kao ključevi u skupu ključeva. Skup ključeva je određen svim redovima koji su kvalificirali naredbu SELECT kada je kursor prvi put otvoren. Također može otkriti sve promjene u izvoru podataka, što podržava operacije ažuriranja i brisanja. Prema zadanim postavkama može se pomicati.
Implementacija primjera
Implementirajmo primjer kursora na SQL poslužitelju. To možemo učiniti tako da prvo stvorimo tablicu pod nazivom ' kupac ' pomoću donje izjave:
CREATE TABLE customer ( id int PRIMARY KEY, c_name nvarchar(45) NOT NULL, email nvarchar(45) NOT NULL, city nvarchar(25) NOT NULL );
Zatim ćemo unijeti vrijednosti u tablicu. Možemo izvršiti naredbu u nastavku za dodavanje podataka u tablicu:
INSERT INTO customer (id, c_name, email, city) VALUES (1,'Steffen', '[email protected]', 'Texas'), (2, 'Joseph', '[email protected]', 'Alaska'), (3, 'Peter', '[email protected]', 'California'), (4,'Donald', '[email protected]', 'New York'), (5, 'Kevin', '[email protected]', 'Florida'), (6, 'Marielia', '[email protected]', 'Arizona'), (7,'Antonio', '[email protected]', 'New York'), (8, 'Diego', '[email protected]', 'California');
Podatke možemo provjeriti izvršavanjem IZABERI izjava:
SELECT * FROM customer;
Nakon izvršenja upita, možemo vidjeti donji izlaz gdje ga imamo osam redova u tablicu:
Sada ćemo kreirati kursor za prikaz zapisa kupaca. Sljedeći isječci koda objašnjavaju sve korake deklaracije ili stvaranja kursora stavljanjem svega zajedno:
interni rad hashmapa
--Declare the variables for holding data. DECLARE @id INT, @c_name NVARCHAR(50), @city NVARCHAR(50) --Declare and set counter. DECLARE @Counter INT SET @Counter = 1 --Declare a cursor DECLARE PrintCustomers CURSOR FOR SELECT id, c_name, city FROM customer --Open cursor OPEN PrintCustomers --Fetch the record into the variables. FETCH NEXT FROM PrintCustomers INTO @id, @c_name, @city --LOOP UNTIL RECORDS ARE AVAILABLE. WHILE @@FETCH_STATUS = 0 BEGIN IF @Counter = 1 BEGIN PRINT 'id' + CHAR(9) + 'c_name' + CHAR(9) + CHAR(9) + 'city' PRINT '--------------------------' END --Print the current record PRINT CAST(@id AS NVARCHAR(10)) + CHAR(9) + @c_name + CHAR(9) + CHAR(9) + @city --Increment the counter variable SET @Counter = @Counter + 1 --Fetch the next record into the variables. FETCH NEXT FROM PrintCustomers INTO @id, @c_name, @city END --Close the cursor CLOSE PrintCustomers --Deallocate the cursor DEALLOCATE PrintCustomers
Nakon što pokrenemo pokazivač, dobit ćemo sljedeći rezultat:
Ograničenja pokazivača SQL Servera
Pokazivač ima neka ograničenja tako da bi se uvijek trebao koristiti samo kada nema druge mogućnosti osim pokazivača. Ova ograničenja su:
- Pokazivač troši mrežne resurse zahtijevajući mrežno povratno putovanje svaki put kada dohvati zapis.
- Kursor je skup pokazivača koji se nalazi u memoriji, što znači da zauzima nešto memorije koju bi drugi procesi mogli koristiti na našem stroju.
- Zaključava dio tablice ili cijelu tablicu prilikom obrade podataka.
- Performanse i brzina pokazivača su sporiji jer ažuriraju zapise tablice red po red.
- Kursori su brži od while petlji, ali imaju više dodatnih troškova.
- Broj redaka i stupaca unesenih u pokazivač još je jedan aspekt koji utječe na brzinu pokazivača. Odnosi se na to koliko je vremena potrebno za otvaranje pokazivača i izvršavanje naredbe za dohvaćanje.
Kako možemo izbjeći pokazivače?
Glavni zadatak pokazivača je da prelaze red po red tablice. Najlakši način za izbjegavanje kursora je dat u nastavku:
Korištenje SQL while petlje
Najlakši način da izbjegnete korištenje pokazivača je korištenjem while petlje koja omogućuje umetanje skupa rezultata u privremenu tablicu.
Korisnički definirane funkcije
Ponekad se kursori koriste za izračunavanje rezultirajućeg skupa redaka. To možemo postići korištenjem korisnički definirane funkcije koja zadovoljava zahtjeve.
Korištenje spojeva
Join obrađuje samo one stupce koji ispunjavaju navedeni uvjet i time smanjuje redove koda koji daju bržu izvedbu od pokazivača u slučaju da je potrebno obraditi ogromne zapise.