Ana içeriğe geç
Kesit SQL
Orta · T-SQL (SQL Server)

Hata yönetimi ileri: yeniden fırlatma, XACT_STATE, XACT_ABORT, yeniden deneme

CATCH bloğunda hatayı yutmamak, işlemin hâlâ geçerli olup olmadığını bilmek.

Uygulamada aç, 7 alıştırmayı çözÜcretsiz, hesap gerekmez, kurulum yok.

Bu sayfa dersin okuma sürümüdür. Metin bir kutuyu çalıştırmanı ya da adıma geçmeni söylüyorsa dersi uygulamada aç.

Hatayı yutma, yeniden fırlat

TRY/CATCH temeli için Hata yönetimi dersine bak. CATCH içinde parametresiz THROW; yakalanan hatayı aynı numarayla çağırana iletir. THROW öncesindeki satır noktalı virgülle bitmelidir.

BEGIN TRY
  BEGIN TRY
    SELECT 1 / 0;
  END TRY
  BEGIN CATCH
    PRINT N'Kayda yazıldı: ' + ERROR_MESSAGE();
    THROW;
  END CATCH;
END TRY
BEGIN CATCH
  SELECT ERROR_NUMBER() AS dista_yakalanan;
END CATCH;

XACT_STATE

DeğerAnlamYapılabilecek
1Açık, işlenebilir işlemCOMMIT ya da ROLLBACK
0Açık işlem yokGeri alınacak bir şey yok
-1Açık ama işlenemez işlemOkuma ve tam ROLLBACK; yazma ve COMMIT yok

@@TRANCOUNT işlem var mı der ama işlenebilir mi demez. XACT_STATE ise iç içe sayısını söylemez.

SET XACT_ABORT ON

Çalışma zamanı hatasında işlemi geri alır; TRY içindeyse işlem işlenemez duruma geçer ve CATCH'te XACT_STATE() = -1 görülür. Uygulama zaman aşımında bile kilit bırakmak için yordamların başına konması önerilir.

SET XACT_ABORT ON;
BEGIN TRY
  BEGIN TRANSACTION;
  DELETE FROM departments WHERE dept_id = 7;
  SELECT 1 / 0;
  COMMIT TRANSACTION;
END TRY
BEGIN CATCH
  SELECT XACT_STATE() AS durum;
  IF XACT_STATE() <> 0 ROLLBACK TRANSACTION;
END CATCH;
SELECT COUNT(*) AS hukuk_duruyor_mu FROM departments WHERE dept_id = 7;
Bu motordaXACT_STATE -1'i yalnız XACT_ABORT ON iken üretir ve o durumda COMMIT ya da yazma Msg 3930 verir. Gerçek sunucuda bazı hatalar XACT_ABORT kapalıyken de işlemi işlenemez yapabilir. Motor ayrıca hatada bütün çalıştırmayı durdurur; gerçek sunucuda birçok hata yalnız o ifadeyi durdurur, XACT_ABORT OFF ise sonraki satır çalışmaya devam eder.

Yeniden deneme kalıbı

Deadlock kurbanı 1205 alır ve işlem geri alınmıştır; yeniden denemek güvenlidir. Learn kısa, rastgele bir bekleme öneriyor. Burada 1205 üretemeyiz (tek bağlantı), bu yüzden hatayı THROW ile taklit ediyoruz.

DECLARE @deneme INT = 0, @bitti INT = 0;
WHILE @bitti = 0 AND @deneme < 3
BEGIN
  SET @deneme = @deneme + 1;
  BEGIN TRY
    IF @deneme < 3 THROW 51205, N'Taklit: kurban seçildi', 1;
    SET @bitti = 1;
  END TRY
  BEGIN CATCH
    PRINT N'Deneme ' + CAST(@deneme AS NVARCHAR(5)) + N' başarısız';
    IF ERROR_NUMBER() <> 51205 THROW;
  END CATCH;
END;
SELECT @deneme AS deneme, @bitti AS bitti;
Alıştırmalara geç (7)