SQL Server’da Raiserror ve Throw Arasındaki Farklar
Herkese merhaba,
Bu başlık altında SQL Server’da Raiserror ve Throw arasındaki farkları inceleyeceğiz.
Raiserror ve Throw ifadeleri SQL Server’da hata fırlatmak için kullanılırlar.
Raiserror ifadesi SQL Server 7.0 ile ortaya çıkmış bir ifade iken Throw ifadesi SQL Server 2012 ile çıkmış bir ifadedir.
Microsoft Raiserror ifadesi yerine Throw ifadesi kullanmayı öneriyor.
RAISERROR
Hangi SQL Server Sürümünde Sunuldu?
SQL Server 7.0 ile hayatımıza girdi. Raiserror ifadesi SQL Server 2014’de Natively compiled Stored Procedure’lerde kullanılamaz. Microsoft artık Raiserror ifadesi kullanmayı önermiyor.
Sözdizimi
RAISERROR ( { error_number | message | @local_variable } { ,severity ,state } [ ,argument [ ,...n ] ] ) [ WITH option [ ,...n ] ]
Catch bloklarında orjinal hatayı tekrar çağırabilir miyiz?
Hayır. Her zaman yeni istisna üretilir ve orijinal hata ayrıntılarının kaybedilmesine sebep olur. Aşağıdaki örnekte, bunu görmektesiniz.
BEGIN TRY
DECLARE @result INT
--Sıfıra bölme hatası oluşur.
SET @result = 55/0
END TRY
BEGIN CATCH
--Hatanın ayrıntıları Catch bloğu ifadesi içinde çağrıldı. Kısacası hata burada yakalandı.
DECLARE
@ErMessageNVARCHAR(2048),
@ErSeverity INT,
@ErState INT
SELECT
@ErMessage = ERROR_MESSAGE()
,@ErSeverity = error_severity()
,@ErState = ERROR_STATE()
RAISERROR (@ErMessage,
@ErSeverity,
@ErState)
END CATCH
Sonuç :
Msg 50000, Level 16, State 1, Line 19
Divide by zero error encountered.
NOT : Sıfıra bölünmesi sonucu üretilen hata kodunun gerçek satır sayısı normalde 4’tür ancak Raiserror tarafından döndürülen özel durum iletisi bize 19 olarak gösterilir. Ayrıca sıfıra bölme işlemine karşılık gelen hata numarası SYS.Messages tablosunda 8134’tür. Raiserror tarafından dönen numara 50000’dir.
Deyimsel ifadelerin sonlandırılmasına neden oluyor mu?
Örnek 1 : Aşağıdaki örnekte Raiserror ifadesinden sonra Print ifadesi yürütüldü.
BEGIN
PRINT 'RAISERROR ÖNCESİ'
RAISERROR ('RAISERRORTEST', 16, 1)
PRINT 'RAISERROR SONRASI'
END
Sonuç :
RAISERROR ÖNCESİ
Msg 50000, Level 16, State 1, Line 3
RAISERROR TEST
RAISERROR SONRASI
Örnek 2 : Aşağıdaki örnekte tüm ifade Raiserror deyiminden sonra yürütülür.
BEGIN TRY
DECLARE @RESULT INT = 55/0
END TRY
BEGIN CATCH
PRINT 'RAISERROR ÖNCESİ';
--Hatanın ayrıntıları Catch bloğu ifadesi içinde çağrıldı. Kısacası hata burada yakalandı.
DECLARE
@ErMessageNVARCHAR(2048),
@ErSeverity INT,
@ErState INT
SELECT
@ErMessage = ERROR_MESSAGE()
,@ErSeverity = error_severity()
,@ErState = ERROR_STATE()
RAISERROR (@ErMessage,
@ErSeverity,
@ErState)
PRINT 'RAISERROR SONRASI'
END CATCH
PRINT 'YAKALANDIKTAN SONRA'
RESULT:
RAISERROR ÖNCESİ
Msg 50000, Level 16, State 1, Line 19
Divide by zero error encountered.
RAISERROR SONRASI
YAKALANDIKTAN SONRA
Önem düzeyi derecesi atama işlemi yapılabilir mi?
EVET. Önem düzeyi parametresi, oluşan hatanın önem derecesini belirten bir ifadedir.
Önceki deyimin noktalı virgül (;) sonlandırıcısıyla sonlandırılmasını gerektiriyor mu?
HAYIR.
System hata mesajları sayısı yükseltilebilir mi?
SYS.MESSAGES tablosu hem sistem tanımlı hem de kullanıcı tanımlı mesajlara sahiptir. 50000’den küçük mesajlar sistem mesajlarıdır.
EVET. Raiserror ile sistem istisnasını yükseltebiliriz.
Örnek :
RAISERROR (40655,16,1)Sonuç :
Msg 40655, Level 16, State 1, Line 1
Database ‘master’ cannot be restored.
SYS.MESSAGES tablosunda tanımlanmamış 50000’den büyük message_id ile kullanıcı tanımlı mesajı yazılabilir mi?
HAYIR. Raiserror’da bir msg_id almak için, sys.messages içinde öncelikle tanımlanma işlemi yapılmalıdır.
Örnek :
RAISERROR (60000, 16, 1)
Sonuç :
Msg 18054, Level 16, State 1, Line 1
Error 60000, severity 16, state 1 was raised, but no message with that error number was found insys.messages. If error is larger than 50000, make sure the user-defined message is added using sp_addmessage.
Şimdi mesajı aşağıdaki deyimi kullanarak SYS.MESSAGES tablosuna ekleyelim:
EXEC sys.sp_addmessage 60000, 16, ‘Test Mesaj’
Now try to Raise the Error:
RAISERROR (60000, 16, 1)
Sonuç :
Msg 60000, Level 16, State 1, Line 1
Test Mesaj
Mesaj parametrelerine değer atama işlemi gerçekleştirebilir miyiz?
Aşağıdaki deyimi kullanarak SYS.Messages tablosuna parametreleri de kullanarak örnek bir metin mesajı ekleyelim.
EXEC sp_addmessage 80000,16,’Mesaj parametresi : %d ve parametre 2 :%s’
EVET. Msg_str parametresi printf biçimlendirme stilleri içerebilir.
Örnek 1 :
RAISERROR (80000, 16, 1, 505,’Yavuz’ )
Sonuç :
Msg 80000, Level 16, State 1, Line 1
Message with Parameter 1: 505 and Parameter 2:Yavuz
THROW
Hangi SQL Server Sürümünde Sunuldu?
SQL Server 2012 ile hayatımıza girdi. Kullanımı Raiserror ifadesine göre daha kolaydır. SQL Server 2014’de Natively Compiled Stored Procedure’lerde kullanılabilir.
Sözdizimi
THROW [ { error_number | @local_variable }, { message | @local_variable }, { state | @local_variable } ] [ ; ]
Catch bloklarında orjinal hatayı tekrar çağırabilir miyiz?
Evet. Try Bloğu’nda yakalanan orijinal hatayı yeniden gözden geçirmek için, Throw deyimini ile herhangi bir parametre olmadan Catch bloğunda belirtebiliriz. Aşağıdaki örnekte bunu görmektesiniz.
BEGIN TRY
DECLARE @result INT --Generate divide-by-zero error
SET @result = 55 / 0
END TRY
BEGIN CATCH
THROW
END CATCH
Sonuç :
Msg 8134, Level 16, State 1, Line 4
Divide by zero error encountered.
Yukarıdaki ifadede Throw ifadesi bize hatayı doğru satır sayısı ve doğru satır numarası ile döndürür.
Deyimsel ifadelerin sonlandırılmasına neden oluyor mu?
Örnek 1 : Aşağıdaki örnekte Throw deyiminden sonraki Print deyimi yürütülemez.
BEGIN
PRINT 'THROW ÖNCESİ';
THROW 50000, 'THROWTEST', 1
PRINT 'THROW SONRASI'
END
Sonuç :
THROW ÖNCESİ
Msg 50000, Level 16, State 1, Line 3
THROW TEST
Örnek 2 : Aşağıdaki örnekte Throw deyiminden sonra print ifadesi yürütülmez.
BEGIN TRY
DECLARE @RESULT INT = 55 / 0
END TRY
BEGIN CATCH
PRINT 'THROW ÖNCESİ';
THROW;
PRINT 'THROW SONRASI'
END CATCH
PRINT 'YAKALANDIKTAN SONRA'
Sonuç:
THROW ÖNCESİ
Msg 8134, Level 16, State 1, Line 2
Divide by zero error encountered.
Önem düzeyi derecesi atama işlemi yapılabilir mi?
HAYIR. Hiçbir önem derecesi parametresi yoktur. İstisna önem derecesi her zaman 16 olarak ayarlanır (Bir Catch bloğuna yeniden girmediği sürece)
Önceki deyimin noktalı virgül (;) sonlandırıcısıyla sonlandırılmasını gerektiriyor mu?
EVET. Throw deyiminden önceki deyimde, noktalı virgül (;) deyimi ile sonlandırılması gerekmektedir.
System hata mesajları sayısı yükseltilebilir mi?
SYS.MESSAGES tablosu hem sistem tanımlı hem de kullanıcı tanımlı mesajlara sahiptir. 50000’den küçük mesajlar sistem mesajlarıdır.
HAYIR. Throw ile Sistem İstisnasını yükseltemiyoruz. Ancak, Catch bloğunda kullanıldığında, sistem özel durumunu tekrar gözden geçirebilir.
Örnek :
Sistem istisnasını yükseltmeye çalışmak (Örnek : ErrorNumber 50000’den küçük istisna).
THROW 40655, ‘Database master cannot be restored.’, 1
Sonuç :
Msg 35100, Level 16, State 10, Line 1
Error number 40655 in the THROWstatement is outside the valid range. Specify an error number in the valid range of 50000 to 2147483647
SYS.MESSAGES tablosunda tanımlanmamış 50000’den büyük message_id ile kullanıcı tanımlı mesajı yazılabilir mi?
EVET. The error_number parameter does not have to be defined insys.messages.
Örnek :
THROW 60000, ‘Test Mesaj’, 1
Sonuç :
Msg 60000, Level 16, State 1, Line 1
Test Mesaj
Mesaj parametrelerine değer atama işlemi gerçekleştirebilir miyiz?
Aşağıdaki deyimi kullanarak SYS.Messages tablosuna parametreleri de kullanarak örnek bir metin mesajı ekleyelim.
EXEC sp_addmessage 80000,16,’Mesaj parametresi : %d ve parametre 2 :%s’
HAYIR. Mesaj parametresi printf stili biçimlendirmesini kabul etmiyor.
Örnek 1 :
THROW 80000, ‘Message with Parameter 1: %d and Parameter 2:%s’, 1, 505,’Yavuz’
Sonuç :
Msg 102, Level 15, State 1, Line 1
Incorrect syntax near ‘,’.
Alternatif olarak bunu yapmanın yolu şu şekildedir.
DECLARE @ErrorMsg NVARCHAR(2048) = FORMATMESSAGE(70000, 505, ‘Örnek mesaj’ );
THROW 80000, @ErrorMsg, 1
Msg 80000, Level 16, State 1, Line 2
Mesaj parametresi : 505 and Parameter 2:Örnek mesaj
Örnek 2 : Mesajları değiştirmeye Throwdeyimine izin verilmez.
Aşağıdaki deyim başarısız olacak.
THROW 58000,’Metin1 ‘ + ‘ Metin2’,1
Sonuç :
Msg 102, Level 15, State 1, Line 1
Incorrect syntax near ‘+’.
Bu gibi sorunları rahatıkla çözebiliriz, mesajı Throw deyiminden önce hazırlayabilir ve daha sonra ifadeyi bir değişken şeklinde iletebiliriz. Aşağıdaki örnek bunu göstermektedir.
DECLARE @message NVARCHAR(2048)
SET @message = ‘metin1’ + ‘ metin2’;
THROW 58000, @message, 1
Sonuç :
Msg 58000, Level 16, State 1, Line 3
metin1 metin2
Herkese çalışma hayatında ve yaşamında başarılar kolaylıklar.