Hafta_7_1

Transkript

Hafta_7_1
Cursor
VTYS'deki 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.
SQL sorgularının sonucunda elde edilen kayıtlar, bir iş katmanı içerisinde, DataSet, recordset
veya DataReader gibi nesneler aracılığıyla yönetilir. Ancak bir sorgunun sonucu, daha VTYS
katmanını çıkmadan ele alınıp satırlarına teker teker erişilmesi bazen bir gereksinim olabilir.
İşte bu türden işlemler için bir sorgu sonucunda oluşturulan veri kümesine resultset denir.
Bazen resultset'ler üstünde gezinmemiz gerekebilir. Bu tür durumlarda, Cursor'leri kullanırız.
SQL Server farklı Cursor seçenelerine destek sağlar. Ancak biz burada, en genel manada
bilinen cursor'ler olan Transact-SQL Sunucu Cursor'leri ele alacağız.
Bir Transact-SQL Sunucu Cursor programlamak, ilk bakışta karmaşık gibi görünebilir. Ancak
bu işlemi adımlar halinde ele aldığımızda, aslında bir DataReader ya da TableSet ile veri
yönetmekten pek bir farkı yoktur. Çünkü temellerinde aynı işlevler yatar.
Bir veri tipi olarak da ele alınabilen Transact-SQL Sunucu Cursor şu aşamalardan geçirilerek
kullanılır.
1. Cursor bir SELECT ifadesi için tanımlanır.
2. Select ifadesi hangi veri tiplerinde ne kadar sütun döndürecekse eşdeğeri değişkenler
tanımlanır.
3. Cursor, resultset üstünde gezinilmek üzere OPEN deyimi ile açılır.
4. Resultset'in sonuna gelinceye kadar her seferinde bir kayıt olmak üzere FETCH
NEXT komutu ile kayıtlar üstünde ilerlenir. Burada dikkat edilmesi gereken nokta, bir
kere veri erişim işlemi yapıldıktan sonra, döngüye girilmesidir. Bunun nedenini,
birazdan kendiniz algılayacağınız için şimdilik devam edelim.
5. Resultset ile ilgili işlemler sona erdiğinde cursor CLOSE ile kapatılır. Ancak kapatılan
cursor henüz hafızada yer kaplamaya devam eder. Gerek duyulursa, yeniden açılabilir.
Ama bu cursor, kapalı bile olsa bir sonraki adıma geçilmeden aynı adda bir cursor
tanımlanamaz.
6. Cursor ile ilgili işlerimiz bittiği anda hafızadan da silmek için cursor DEALLOCATE
ile hafızadan boşaltılır.
Örnek: Şu şekilde bir kitap tablomuz olsun:
CREATE TABLE kitap
(
kitapNo
INT IDENTITY(1, 1) NOT NULL PRIMARY KEY,
kitapAdi VARCHAR(55) NOT NULL,
geldiMi BIT
)
Kitaplar listesini ekrana yazdıracak(resultset olarak değil de teker teker) bir kod parçası
yazalım:
1.Cursor tanımlanır:
DECLARE cursor_adi CURSOR FOR
SELECT İFADESİ
Şeklinde tanımlanır.
DECLARE cr_ogrenciAdlari CURSOR FOR
SELECT o.ad, o.soyad FROM dbo.tbl_ogrenci o
Ve bu sorgu tarafından döndürülen iki satıra karşılık, NVARCHAR(55) tipinde iki değişken
tanımlanır.
DECLARE @ad NVARCHAR(50),@soyad NVARCHAR(50)
2.Cursor açılır:
OPEN cursor_adi
OPEN cr_ ogrenciAdlari
3.Cursor üstünde dolaşmak için FETCH komutundan faydalanılır:
FETCH NEXT FROM cursor_adi [INTO icine_doldurulacak_degisken1 [, ....] ]
FETCH NEXT FROM cr_KitaplarListesi INTO @kitapNo, @kitapAdi
-- ilk satirin üstüne geldik ve ilk kayitta yer alan iki değeri yazdirdk.
print @kitapNo
print @kitapAdi
FETCH komutu ile ikinci kaydı yazdırmayı deneyin.
Cursor'ün sona gelip gelmediğini anlamak için @@FETCH_STATUS global
fonksiyonlarından faydalanacağız:
@@FETCH_STATUS fonksiyonu, en son çalıştırılan FETCH komutunun sonucu hakkında
bize bilgi verir. Bu fonksiyon, şu üç değerden birini verecektir:
0 : Bir önceki FETCH komutu başarı ile gerçekleştirlidi.
-1 : Bir önceki FETCH komutunda bir hata ile karşılaşıldı.
-2 : Resultset'teki tüm kayıtlar bittiği için en sona gelindi, daha fazla kayıt yer almıyor. (end
of resultset)
Şimdi artık, kitaplar listesini sonuna kadar yazdırabiliriz. Bu iş için WHILE yapısını
kullanacağız:
DECLARE cr_KitaplarListesi CURSOR FOR
SELECT kitapNo,KitapAdi FROM Kitap
OPEN cr_kitaplarListesi
DECLARE @kitapNo INTEGER,@kitapAdi VARCHAR(55)
FETCH NEXT FROM cr_KitaplarListesi INTO @kitapNo, @kitapAdi
WHILE (@@FETCH_STATUS = 0)
BEGIN
PRINT @kitapNo
PRINT @kitapAdi
--bir önceki FETCH ile aldığımız kaydı yazdırdık. Bir sonraki
kayda geçelim:
FETCH NEXT FROM cr_kitaplarListesi INTO @kitapNo, @kitapAdi
--kayıtlarımızı doldurduk. Başa döndüğünde yazılacak.
END
Kitaplar listesini yazdıran cursor ile bizim işimiz bitti ancak yapmamız gereken işlemler
bitmedi.
4.Cursor'ı kapatmamız gerekiyor:
CLOSE cursor_adi
CLOSE cr_kitaplarListesi
CLOSE komutu ile sadece bir cursor'ün içerdiği resultset boşaltılır. Ancak Cursor için
hafızada açılan yer halen kullanımdadır ve bir cursor hafızadan tam olarak silinmediği sürece
aynı adda başka bir cursor daha oluşturulamaz.
5. Cursor şu şekilde hafızadan silinir:
DEALLOCATE cursor_adi
DEALLOCATE cr_kitaplarListesi
DECLARE cr_ogrenciAdlari CURSOR FOR
SELECT o.ad, o.soyad FROM dbo.tbl_ogrenci o
DECLARE @ad NVARCHAR(50),@soyad NVARCHAR(50)
OPEN cr_ogrenciAdlari
FETCH NEXT FROM cr_ogrenciAdlari INTO @ad,@soyad
WHILE @@FETCH_STATUS =0
BEGIN
PRINT UPPER(@ad + ' '+@soyad)
FETCH NEXT FROM cr_ogrenciAdlari INTO @ad,@soyad
END
CLOSE cr_ogrenciAdlari
DEALLOCATE cr_ogrenciAdlari
Örnek:
Kitap adlarını ve dışarıda ise dışarıda, içeride ise içeride yazdıran bir Cursor yazınız:
DECLARE cnot CURSOR FOR
SELECT o.ogr_id, o.ad, o.soyad FROM dbo.tbl_ogrenci o
DECLARE @ogr_id INT,@ad NVARCHAR(50),@soyad NVARCHAR(50),@ogrOrt
DECIMAL(5,2)
OPEN cnot
FETCH NEXT FROM cnot INTO @ogr_id,@ad,@soyad
WHILE @@FETCH_STATUS = 0
BEGIN
SELECT @ogrOrt=AVG(notu) FROM tbl_ogrenciNot
WHERE ogr_id=@ogr_id
PRINT @ad+' '+@soyad + ' ort: ' + CASE WHEN @ogrOrt IS NULL THEN ''
ELSE cast(@ogrOrt AS NVARCHAR(10)) END
FETCH NEXT FROM cnot INTO @ogr_id,@ad,@soyad
END
CLOSE cnot
DEALLOCATE cnot
---------------------------------------------------
declare cnt cursor for
select ogr_id,ad,soyad from tbl_ogrenci
open cnt
declare
@ogr_id int,@ad nvarchar(50),@soyad nvarchar(50),@ort decimal(5,3)
fetch next from cnt into @ogr_id,@ad,@soyad
while @@fetch_status=0
begin
select @ort= avg(notu) from tbl_ogrenciNot where ogr_id=@ogr_id
--set @ort = (select avg(notu) from tbl_ogrenciNot where
ogr_id=@ogr_id)
--print @ad+' '+ @soyad
print @ad+' '+ @soyad +' ort:'+ case when @ort is null then '0' else
cast(@ort as nvarchar(10)) end
fetch next from cnt into @ogr_id,@ad,@soyad
end
close cnt
deallocate cnt
Örnek: Sehir tablosundaki sehilerin bölgelerini bularak ekrana yazdıran
cursor ifadesini yazalım.
DECLARE cr_sehir CURSOR FOR
SELECT sehir,bolge_id FROM tbl_sehir
DECLARE @sehir NVARCHAR(65),@bolge_id INT, @bolgeAdi NVARCHAR(40)
OPEN cr_sehir
FETCH NEXT FROM cr_sehir INTO @sehir,@bolge_id
WHILE @@FETCH_STATUS=0
BEGIN
SET @bolgeAdi = (SELECT bolgeAd FROM tbl_bolge WHERE bolge_id=@bolge_id)
PRINT @sehir + ' '+@bolgeAdi
FETCH NEXT FROM cr_sehir INTO @sehir,@bolge_id
END
CLOSE cr_sehir
DEALLOCATE cr_sehir

Benzer belgeler

Cursor VTYS`deki cursor`ler, metin editörlerindeki cursorler ile aynı

Cursor VTYS`deki cursor`ler, metin editörlerindeki cursorler ile aynı 2. Select ifadesi hangi veri tiplerinde ne kadar sütun döndürecekse eşdeğeri değişkenler tanımlanır. 3. Cursor, resultset üstünde gezinilmek üzere OPEN deyimi ile açılır. 4. Resultset'in sonuna gel...

Detaylı

Cursor (İmleç)

Cursor (İmleç) DECLARE [SCROLL] CURSOR FOR