|
Cursor (T-SQL) ile Kayıtlara Satır Satır Erişmek |
|
Gönderiliyor lütfen bekleyin... |
|
|
Veritabanı
Yönetim Sistemindeki cursor’ler, metin editörlerindeki cursorler ile
aynı işi yapar. Metin editörlerinde O an için cursor nerede
ise, oradaki verileri baz alan işlemler yapabilirsiniz. Veritabanı
sistemlerinde ise, cursor’ün bulunduğu yerdeki verileri yazdırma,
ele alma gibi işlemleri yerine getirebiliriz. Bu makalede, özet olarak
sorgu sonuçlarına, VTYS ortamında satır satır erişme
işlevini sağlayan Sunucu Taraf Cursor’lar ele alınmaktadır.
SQL sorgularinin
sonucunda elde edilen kayitlar, bir is katmani içerisinde, DataSet, recordset
veya DataReader gibi nesneler araciligiyla yönetilir. Ancak bir sorgunun sonucu,
daha VTYS katmanini çikmadan ele alinip satirlarina teker teker erisilmesi bazen
bir gereksinim olabilir. Iste bu türden islemler için bir sorgu sonucunda olusturulan
veri kümesine resultset denir. Bazen resultset’ler üstünde gezinmemiz gerekebilir.
Bu tür durumlarda, Cursor’leri kullaniriz.
SQL Server farkli
Cursor seçenelerine destek saglar. Ancak biz burada, en genel manada bilinen
cursor’ler olan Transact-SQL Sunucu Cursor’leri ele alacagiz.
Bir Transact-SQL
Sunucu Cursor programlamak, ilk bakista karmasik gibi görünebilir. Ancak bu
islemi adimlar halinde ele aldigimizda, aslinda bir DataReader ya da TableSet
ile veri yönetmekten pek bir farki yoktur. Çünkü temellerinde ayni islevler
yatar.
Bir veri tipi olarak
da ele alinabilen Transact-SQL Sunucu Cursor su asamalardan geçirilerek kullanilir.
- Cursor bir SELECT
ifadesi için tanimlanir.
- Select ifadesi
hangi veri tiplerinde ne kadar sütun döndürecekse esdegeri degiskenler tanimlanir.
- Cursor, resultset
üstünde gezinilmek üzere OPEN deyimi ile açilir.
- Resultset’in
sonuna gelinceye kadar her seferinde bir kayit olmak üzere FETCH NEXT komutu
ile kayitlar üstünde ilerlenir. Burada dikkat edilmesi gereken nokta, bir
kere veri erisim islemi yapildiktan sonra, döngüye girilmesidir. Bunun nedenini,
birazdan kendiniz algilayacaginiz için simdilik devam edelim.
- Resultset ile
ilgili islemler sona erdiginde cursor CLOSE ile kapatilir. Ancak kapatilan
cursor henüz hafizada yer kaplamaya devam eder. Gerek duyulursa, yeniden açilabilir.
Ama bu cursor, kapali bile olsa bir sonraki adima geçilmeden ayni adda bir
cursor tanimlanamaz.
- 5. Cursor ile
ilgili islerimiz bittigi anda hafizadan da silmek için cursor DEALLOCATE ile
hafizadan bosaltilir.
Örnek:
Su sekilde bir
kitap tablomuz olsun:
CREATE TABLE kitap(
kitapNo INT IDENTITY(1,1) NOT NULL PRIMARY KEY,
kitapAdi VARCHAR(55) NOT NULL
.......
)
|
Kitaplar listesini
ekrana yazdiracak(resultset olarak degil de teker teker) bir kod parçasi yazalim:
1.Cursor tanimlanir:
DECLARE cursor_adi CURSOR FOR
SELECT IFADESI
|
Seklinde tanimlanir.
DECLARE cr_kitaplarListesi CURSOR FOR
SELECT kitapNo, kitapAdi
FROM Kitap
|
Ve bu sorgu tarafindan
döndürülen iki satira karsilik, bir INT ve bir de VARCHAR(55) tipinde iki degisken
tanimlanir.
DECLARE @kitapNo INTEGER,@kitapAdi VARCHAR(55)
|
2.Cursor açilir:
OPEN cursor_adi
OPEN cr_kitaplarListesi
|
3.Cursor üstünde
dolasmak için FETCH komutundan faydalanilir:
FETCH NEXT FROM cursor_adi [INTO icine_doldurulacak_degisken1 [, ....] ]
FETCH cr_KitaplarListesi INTO @kitapNo, @kitapAdi
|
-- ilk satirin
üstüne geldik ve ilk kayitta yer alan iki degeri yazdirdik.
print @kitapNo
print @kitapAdi
|
FETCH komutu ile
ikinci kaydi yazdirmayi deneyin.
Cursor’ün sona
gelip gelmedigini anlamak için @@FETCH_STATUS ve @@rowcount global fonksiyonalrindan
faydalanacagiz:
@@FETCH_STATUS
fonksiyonu, en son çalistirilan FETCH komutunun sonucu hakkinda bize bilgi verir.
Bu fonksiyon, su üç degerden birini verecektir:
0 : Bir önceki
FETCH komutu basari ile gerçeklestirlidi.
-1 : Bir önceki FETCH komutunda bir hata ile karsilasildi.
-2 : Resultset’teki tüm kayitlar bittigi için en sona gelindi, daha fazla kayit
yer almiyor. (end of resultset)
@@rowcount, bir
önceki FETCH komutu icra edildikten sonra resultset’te toplam kaç kayit kaldigini
tutar. Hiç FETCH komutu kullanilmadi ise Cursor’un isaretledigi resultset’te
toplam kaç kayit yer aldigini gösterir.
Simdi artik, kitaplar
listesini sonuna kadar yazdirabiliriz. Bu is için WHILE yapisini kullanacagiz:
DECLARE cr_KitaplarListesi CURSOR AS
SELECT kitapNo,KitapAdi
FROM Kitap
DECLARE @kitapNo INTEGER,@kitapAdi VARCHAR(55)
FETCH cr_KitaplarListesi INTO @kitapNo, @kitapAdi
WHILE (@@FETCH_STATUS = 0)
BEGIN
PRINT @kitapNo
PRINT @kitapAdi
--bir önceki FETCH ile aldigimiz kaydi yazdirdik. Bir sonraki kayda geçelim:
FETCH cr_kitaplarListesi INTO @kitapNo, @kitapAdi
--kayitlarimizi doldurduk. Basa döndügünde yazilacak.
END
|
Kitaplar listesini
yazdiran cursor ile bizim isimiz bitti ancak yapmamiz gereken islemler bitmedi.
4.Cursor’i kapatmamiz
gerekiyor:
CLOSE cursor_adi
CLOSE cr_kitaplarListesi
|
CLOSE komutu ile
sadece bir cursor’ün içerdigi resultset bosaltilir. Ancak Cursor için hafizada
açilan yer halen kullanimdadir ve bir cursor hafizadan tam olarak silinmedigi
sürece ayni adda baska bir cursor daha olusturulamaz.
5. Cursor su sekilde
hafizadan silinir:
DEALLOCATE cursor_adi
DEALLOCATE cr_kitaplarListesi
|
Örnek:
Kitap adlarini
ve disarida ise disarida, içeride ise içeride yazdiran bir Cursor yaziniz:
DECLARE cr_kitapDurumu CURSOR FOR
SELECT kitaplar.kitapAdi,odunc.GeldiMi
FROM Kitap LEFT JOIN odunc ON odunc.KitapNo=Kitaplar.KitapNo
DECLARE @kitapAdi VARCHAR(25), @Durumu BIT
OPEN cr_kitapDurumu
FETCH NEXT FROM cr_kitapDurumu INTO @kitapAdi, @Durumu
WHILE @@FETCH_STATUS =0
BEGIN
print @kitapAdi
IF @Durumu = 0
print ’disarida’
ELSE
Print ’içeride’
FETCH NEXT FROM cr_kitapDurumu INTO @kitapAdi, @Durumu
END
CLOSE cr_kitapDurumu
DEALLOCATE cr_kitapDurumu
|
Örnek:
Kitaplar tablosunda
ayni kitap numarasindan iki tane olan varsa sildirecek bir cursor yazalim
SET ROWCOUNT 0
DECLARE @kitapNo INTEGER, @kitapAdi VARCHAR(45), @sayac BIT
DECLARE crKitaplar CURSOR FOR
SELECT kitapNo,KitapAdi
FROM Kitap
ORDER BY kitapNo
OPEN crKitaplar
FETCH NEXT FROM crKitaplar INTO @KitapNo, @kitapAdi
print @kitapNo
SET @sayac = 0
WHILE @@FETCH_STATUS=0
BEGIN
IF @sayac=1
BEGIN
SET @sayac = 0
SET ROWCOUNT 1
DELETE FROM Kitap WHERE kitapNo = @kitapNo
SET ROWCOUNT 0
END
ELSE
SET @sayac = 1
FETCH NEXT FROM crKitaplar INTO @KitapNo,@kitapadi
print @kitapAdi
END
CLOSE crKitaplar
DEALLOCATE crKitaplar
|
IPUCU:
ROWCOUNT parametresine atanan deger, bir islemden en fazla kaç satirin etkilenecegini
gösterir. Normalde, ROWCOUNT 0 degerindedir. Sayet kriteri saglayan kayitlarin
tamami için geçerli bir islem yapacaksak SET ROWCOUNT 0 ile normal haline döndürebiliriz.
ROWCOUNT’a bir deger atandiginda, oturum kapanincaya ya da yeni bir deger atanincaya
kadar o deger geçerli olur.
DIKKAT:
@@rowcount ile
ROWCOUNT parametresi farkli islevlere sahiptir.
IPUCU:
Bir sorgunun sonucunda
sadece en yüksek n kaydi görmek için TOP n deyimini Microsoft temelli VTYS’lerde
kullanilabilir. Bu özellik MS Access ve SQL Server 2000 de sadece SELECT sorgulari
ile kullanilabilirken, SQL Server 2005 sürümünde UPDATE ve DELETE gibi ifadelerle
de kullanilabilir hale getirilmesi planlanmaktadir. ANSI-92’nin bir parçasi
degildir..
Örnek:
SELECT TOP 5 *
FROM kitapORDER BY sayfaSayisi DESC
|
Makale:
Cursor (T-SQL) ile Kayıtlara Satır Satır Erişmek ADO.NET ve SQL Yaşar Gözüdeli
|
|
|
-
-
Eklenen Son 10
-
Bu Konuda Geçmiş 10
Bu Konuda Yazılmış Yazılmış 10 Makale Yükleniyor
Son Eklenen 10 Makale Yükleniyor
Bu Konuda Yazılmış Geçmiş Makaleler Yükleniyor
|
|