MsSql Server – Cursor Kullanımı 2

Merhaba,

Database Yöneticileri tarafından sıkılıkla karşılaşılan bir problemden bahsetmek istiyorum bugün sizlere. Yazılım/Veritabanı geliştiricilerinin çoğunlukla başvurduğu metotlardan biridir Bulk Insert/Update/Delete işlemleri. Tabi ki bu işlemi yaparken, “yaptığım işlem bir başkasını etkiler mi?” düşüncesi genelde bulunmaz. Onlar için önemli olan yaptıkları işin bir an önce bitmesi ve sonuca ulaşmalarıdır.

Production ortamlarında, çok büyük sayıda kayıtların bir tabloya eklenmesi, silinmesi veya update edilmesi sırasında o tablonun işlemi yapan kişi tarafından locklanmış olması dolayısıyla, o tabloya erişecek olan başka kimselerin (Rapor çeken, yeni kayıt girişleri yapan kullanıcılar vb.) işlerini yapamamaları sonucunda ilk çalacakları kapı DBA’lerin kapısıdır. DBA’lerin de yapacakları ilk iş bulk işlemi yapan kişinin session’ını kill etmek veya bu kişiyi hızlıca uyarmaktır işlemi kesmesi için.

Biz bu gibi durumlarda yazılımcılara genellikle Cursor kullanmalarını veya while kullarak işlemlerini parça parça yapmalarını şiddetle tavsiye ediyoruz/zorluyoruz. Çok basit gibi gözüken bu işlem sayesinde sistemin aksamadan yürümesi, herkesin istediği sonucu elde etmesi biraz daha kolaylaşmakta. Bu yüzden de her ne kadar bulk işlemlere göre biraz daha yavaş olmasına rağmen ilk önerdiğimiz kullanımlar içerisinde yer almakta Cursor vb.

Bugünde size Sql Server’da Cursor işlemini bir örnek ile açıklamaya çalışacağım.

Cursor İşlermi .Net’te kullanılan for döngüsünün bir benzeri olarak Sql Server’da kullanılmaktadır.

Senaryomuz şu şekilde olsun: 2014 yılından önceki ürünler bir tabloya yedeklendi ve bu yedekleme işleminden sonra Product tablosundan 2014 yılından önceki ürünler silinmesi gerekiyor. Silinecek kayıtların çokluğu dolayısıyla kayıtları tek hamlede silmek yerine Cursor içerisinde yazarak teker teker silinmesini sağlayacağız.

Aşağıdaki resimde görüldüğü gibi tarih bazında kaç kayıt olduğu belirtilmiş. Bu sorgumuz sonucunda 26241 kaydın silinmesi gerekiyor.

ProductCount

DECLARE @ID int
DECLARE @sayi int = 0

DECLARE Cursor_Product CURSOR FOR
SELECT ID
FROM dbo.Product WITH (NOLOCK)
WHERE StartDate < '20140111'

OPEN Cursor_Product
FETCH NEXT FROM Cursor_Product INTO @ID
WHILE @@FETCH_STATUS = 0
BEGIN
DELETE FROM dbo.Product WHERE ID = @ID
PRINT @sayi

FETCH NEXT FROM Cursor_Product INTO @ID
END
CLOSE Cursor_Product
DEALLOCATE Cursor_Product

Cursor Çalıştıktan sonraki durum

Result

CURSOR ADIMLARI

  • DECLARE -> Kod içerisinde kullanılan değişkenler tanımlanır.
  • DECLARE CURSOR -> Cursor’ımızı tanımlayıp içerisinde işlem yapacağımız data SELECT ile çekilir.
  • OPEN -> Datayı işlemek için Cursor açılır.
  • FETCH NEXT FROM -> Tabloya ait kayıtlar arasında ilerlemek için kullanılır. Bu ilerleme sırasında değişkene/değişkenlere değerler atanır.
  • WHILE @@FETCH_STATUS -> While komutuyla kayıtları dolaşmamız sağlanır. Eğer FETCH_STATUS 0 ise kayıt başarılı, -1 ise kayıt başarısız, -2 ise kayıt bulunamadığını belirtir.
  • BEGIN…END -> Bu kısımda data işlenmeye başlar. Bizim örneğimizde ID leri eşleşen kayıtlar silinecektir.
  • CLOSE -> İşlem yapılan datayı serbest bırakır. Tablo üstündeki lock işlemini kaldırır ve Cursor’ı tekrar açılması için sonraki adıma geçer.
  • DEALLOCATE -> Cursor’ı tamamen yok eder.

Sizlerin de bu gibi durumlar için kullandığınız metotları da duymak isterim.

Faydalı Olması dileğiyle.

2 thoughts on “MsSql Server – Cursor Kullanımı

  1. Reply ömer Kas 9,2015 07:43

    http://www.sonercelix.com/MakaleDetay/6079/SQL-Server-Cursor-Kullanimi

    Bu siteden çözüme ulaşabilirsiniz. Konuda resimli açıklama mevcut olup bilgisayar üzerine çokça paylaşım yapan bir sitedir.
    Uzun zamandır takip ediyorum, tavsiye ederim.

  2. Reply hasantatarli Şub 4,2016 06:37

    @Ömer Verdiğin link maalesef çalışmıyor. Çalışan bir link paylaşırsan daha faydalı olur.

Leave a Reply