T-SQL’de hataların nasıl işlendiğini anlamak önemlidir. T-SQL dilinde çeşitli hata işleme mekanizmaları vardır. Bu bölümde temel SQL hataların kasıtlı olarak nasıl oluşturulacağını ve tetiklenecek uyarıları oluşturmayı ele alacağız. Sonraki bölümde ise yapılandırılmış hata işleme olarak bilinen daha gelişmiş bir metodu göreceğiz.

Hatalar ve Hata Mesajları

Hata, bir veritabanı işlemi sırasında ortaya çıkan bir problemi veya önemli bir sorunu gösterir. Her hata aşağıdaki elemanlardan oluşur:

  • Hata numarası: Hatayı tanımlayan benzersiz sayı.
  • Hata mesajı: Hatayı açıklayan metin.
  • Önemi: 1’den 25’e kadar sayısal önem göstergesi.
  • Durumu: Veri tabanı motoru durumu için dahili durum kodu.
  • Procedure:  Hatanın oluştuğu sp veya trigger adı.
  • Satır numarası: Batch veya sp’deki hangi ifadenin hatayı oluşturduğu.

Hatalar sistem düzeyinde SQL Server Database Engine tarafından bir olay veya problem sonucunda üretilebilmektedir. Hataları kendi T-SQL kodunuzda da oluşturabilirsiniz.

Sistem Hataları

Sistem hataları önceden tanımlanmış hatalardır. Sistem hataları sys.messages yardımıyla görüntülenebilir. Bir sistem hatası oluştuğunda hatanın önem derecesine bağlı olarak SQL Server tarafından otomatik düzeltme eylemi gerçekleştirilebilir. Örneğin yüksek önem derecesine sahip bir hata oluştuğunda, veri tabanı SQL Server tarafından çevrimdışı duruma getirebilir hatta database engine service bile durdurulabilir.

Özel Hatalar

Uygulamanıza özgü koşullara yanıt vermek veya hataya yanıt olarak client uygulamalara gönderilen mesajları özelleştirmek için T-SQL kodunuzda kendiniz de hatalar oluşturabilirsiniz. Bu hataları inline olarak tanımlayabilir veya bunları önceden sistem tarafından sağlanan hataların yanında yani sys.messages tablosunda tanımlayabilirsiniz. Özel tanımlanan hatalar için kullanılan hata numarası 50001 veya üstü olmalıdır.

sys.messages’a özel bir hata mesajı eklemek için sp_addmessage sp’sin kullanılır. Bu işlem için sysadmin veya serveradmin rollerine sahip olmak gerekir.

sp_addmessage syntax’ı:
sp_addmessage [ @msgnum= ] msg_id , [ @severity= ] severity , [ @msgtext= ] 'msg'
 [ , [ @lang= ] 'language' ]
 [ , [ @with_log= ] { 'TRUE' | 'FALSE' } ]
 [ , [ @replace= ] 'replace' ] 

Örnek özel hata mesajı:

sp_addmessage 50001, 10, N’Unexpected value entered’; 

Ayrıca sysadmin rolündeki kullanıcıar da @with_log ek parametresini kullanabilir. Parametre TRUE olarak ayarlandığında, hata Windows Application log’a da kaydedilir. Windows Application log’a yazılan tüm iletiler de SQL Server error log’una yazılır. Ağ ve sistem yöneticileri sistem günlüklerinde çok fazla gözüken uygulamaları beğenmeme gibi bir eğilim gösterdiğinden @with_log kullanırken dikkatli olunması gerekmektedir. Ancak hatanın bir alert ile yakalanması gerekiyorsa, hata önce Windows Application log’a yazılmalıdır.

Kod içerisinde sistem hatalarının fırlatılması desteklenmemektedir.

Hata mesajlarını silmeden @replace = ‘replace’ ile değiştirebilirsiniz.

Ek olarak, language_id değerine bağlı olarak aynı anda birçok dil için aynı hata numarasıyla farklı mesajlar tanımlanabilir. (Not: İngilizce mesajlar için language_id 1033’tür.)

RAISERROR ile Hata Basmak

Bilgi ve uyarı mesajı döndürmek için hem PRINT hem de RAISERROR kullanılabilmektedir. RAISERROR ile ek olarak uygulama içerisinde catchable hata oluşturulabilir.

T-SQL’de hatalar herhangi bir sistem hatası gibi gönderildiği için bu durum hata işlemeyi kolaylaştırmaktadır. RAISERROR aşağıdakiler için kullanılır:

  • T-SQL kodunda hataları saptarken
  • Veri değerlerini kontrol ederken
  • Sürekli değişen metin değerleri içeren iletiler döndürürken

PRINT ifadesi ile hata basmak aslında RAISERROR ile önem derecesi 10 olan hata basmak gibidir.

THROW Kullanarak Hata Basmak

THROW ile hata basmak aslında daha basittir. Bu yolla basılan hataların hata numarası da en az 50000 olmalıdır.

THROW birkaç yönüyle RAISERROR’dan farklıdır:

  • THROW tarafından oluşturulan hataların önem seviyesi 16’dır.
  • THROW ile döndürülen hata mesajlarının sys.sysmessages’daki input’larla alakası yoktur.
  • THROW tarafından oluşturulan hatalar yalnızca SET XACT_ABORT ON ile birlikte kullanıldığında veya session sonlandırıldığında transaction’ın sona erdirilmesine neden olur.

@@Error Kullanımı

SQL Server’da hata işleme kodlarının çoğu @@ERROR kullanılarak oluşturulmuştur. SQL Server 2005’te yapılandırılmış hata işlemenin tanıtılmasıyla @@ERROR’e güçlü bir alternatif doğmuş oldu.

SQL Server’daki hata işleme kodlarının büyük kısmında @@ERROR kullanılmıştır, bu nedenle nasıl çalışıldığını anlamak önemlidir.

@@ERROR değişkeni, meydana gelen son hatanın hata numarasını tutan bir sistem değişkenidir. @@ERROR kullanmanın dezavantajı, herhangi bir ifade yürütülmeye başlandığında tuttuğu değerin hemen sıfırlanmasıdır.

Örneğin aşağıdaki koda bir göz atalım:

RAISERROR(N'Message', 16, 1);
IF @@ERROR <> 0
PRINT 'Error=' + CAST(@@ERROR AS VARCHAR(8));
GO

Kod yürütüldüğünde, yazdırılan mesajda hata numarasını görmeyi bekleriz, ancak çıktı aşağıdaki gibi döndü:

Msg 50000, Level 16, State 1, Line 1
Message
Error=0

Hata oluştu ancak hata mesajı “Error= 0” şeklinde. Çıktının ilk satırında, RAISERROR ile iletilen bir mesajla birlikte hatanın aslında beklendiği gibi 50000 olduğunu görebilirsiniz. Bunun sebebi RAISERROR ifadesinden sonra IF deyiminin çalıştırılması ve bunun da @@ERROR değerinin sıfırlanmasına neden olmasıdır.

Bu nedenle, @@ERROR kullanırken hata numarasını yakalayıp bir değişkene atamak ve sonra işleme bu değişkenle devam etmek önemlidir.

Bu durumun örneği aşağıda verilmiştir:

DECLARE @ErrorValue int;
RAISERROR(N'Message', 16, 1);
SET @ErrorValue = @@ERROR;
IF @ErrorValue <> 0
PRINT 'Error=' + CAST(@ErrorValue AS VARCHAR(8)); 

Bu kod yürütüldüğünde aşağıdaki output dönecektir:

Msg 50000, Level 16, State 1, Line 2
Message
Error=50000 

Hata numarası şimdi doğru bir şekilde basılmış oldu.

Hata İşlemenin Merkezileştirilmesi

Hata işlerken @@ERROR kullanımıyla ilgili bir diğer önemli sorun, T-SQL kodunda merkezileştirmenin zor olmasıdır. Hata işleme, kod içerisinde dağınıklaşma eğilimindedir. @@ERROR kullanırken label ve GOTO ifadesi kullanarak bir dereceye kadar merkezileştirmek mümkündür. Ayrıca günümüzde bu durum, çoğu geliştirici tarafından zayıf bir kodlama pratiği olarak nitelendirilmektedir.

Hata Oluştuğunda Alert Basmak

Yöneticiler SQL Server’da belirli hata kategorileri için alert oluşturabilir, çünkü hatalar oluştuğunda anında haberdar olmak isterler. Bu durum kullanıcı tanımlı hata mesajları için de geçerli olabilir. Örneğin, transaction log dolduğunda uyarı gelmesini isteyebilirsiniz. Uyarılar genellikle yöneticilerin önüne yüksek önem arz eden hataların (önem seviyesi 19 veya üzeri) sunulması için kullanılır.

Özel hata mesajları için alert oluşturulabilir. Alert servisi kendisini olay günlüğünde callback servisi şeklinde kaydederek çalışır. Buradan uyarıların yalnızca günlüğe kaydedilen hatalarda çalıştığı anlamı çıkmaktadır.

Bir hata oluştuğunda alert oluşturabilmenin iki yolu bulunur; hata basarken WITH LOG seçeneği kullanabilir veya sp_altermessage ile günlükteki mesajı değiştirebilirsiniz. WITH LOG sadece geçerli ifadeye etki edecektir. sp_altermessage ile hata davranışı değiştirilir. Sistem hatalarının sp_altermessage ile değiştirilmesi sadece SQL Server 2005 SP3 veya SQL Server 2008 SP1 sürümünden itibaren mümkündür.

Kaynak:
PRINT (Transact-SQL)
THROW
RAISERROR
@@ERROR (Transact-SQL)