Aracılığıyla paylaş


İşlemek için try...Transact-SQL'de catch

Hataları Transact-SQL kod işleme kullanarak bir try…catch yapısı özel durum işleme özelliklerine benzer Microsoft Visual c++ ve Microsoft Visual C# dilleri.BİR TRY…catch yapı iki bölümden oluşur: bir try blok ve bir catch blok.Ne zaman bir hata koşulu algılandı bir Transact-SQL , içinde bir try deyim blok, denetim için bir catch geçirilen blok nerede hata işleme.

catch sonra blok için ilk özel denetim transfer sonra tutamaçları Transact-SQL deyim, izlediği end catch deyim.If the END CATCH statement is the last statement in a stored procedure or trigger, control is returned to the code that invoked the stored procedure or trigger.Transact-SQL statements in the TRY block following the statement that generates an error will not be executed.

try içinde herhangi bir hata varsa blok, Denetim deyiminin hemen sonra ilişkili end catch deyim.Son catch deyim saklı yordam veya tetikleyiciyi son deyim ise, Denetim deyim saklı yordam veya tetikleyiciyi çağrılan geçirilir.

Bir try blok BAŞLAYAN deneyin deyimiyle başlar ve end try deyim ile biter.Bir veya daha fazla Transact-SQL ifadeleri arasında BAŞLAYAN deneyin ve belirtilebilirend TRY'deyimleri.

Bir try blok hemen bir catch tarafından uyulması gereken blok.Bir catch blok BAŞLAYAN catch deyim ile başlar ve end catch deyim ile biter.De Transact-SQL, her try blok tek bir catch ile ilişkili olan blok.

try… ile çalışmaCATCH

try… kullandığınızdacatch yapısı, aşağıdaki yönergeleri ve önerileri göz önünde bulundurun:

  • Her try…catch yapı tek bir toplu iş, saklı yordam veya tetikleyiciyi içinde olması gerekir.Örneğin, konulamıyor bir TRY blok tek bir toplu ve ilişkili CATCH blok başka bir toplu.Aşağıdaki komut dosyası bir hata oluşturur:

    BEGIN TRY
        SELECT *
            FROM sys.messages
            WHERE message_id = 21;
    END TRY
    GO
    -- The previous GO breaks the script into two batches,
    -- generating syntax errors. The script runs if this GO
    -- is removed.
    BEGIN CATCH
        SELECT ERROR_NUMBER() AS ErrorNumber;
    END CATCH;
    GO
    
  • Bir try blok hemen bir catch tarafından uyulması gereken blok.

  • TRY…catch yapıları içiçe.Bunun anlamı try…catch yapıları diğer try ve catch bloğu içinde yerleştirilebilir.İç içe geçmiş bir try içinde bir hata ortaya çıktığında blok, programın denetim için catch transfer blok yuvalanmış try ile ilişkili blok.

  • İçinde belirli bir catch oluşan bir hatayı işlemek için blok, bir try… yaz...catch blok içinde belirtilen catch blok.

  • O neden 20 veya daha yüksek bir önem sahip hataları Veritabanı Altyapısı Bağlantıyı kapatmak için değil işleneceğini tarafından try…catch blok.Ancak, try…Bağlantı kapalı sürece 20 veya daha yüksek bir önem sahip hataları catch işleyecektir.

  • 10 Veya daha düşük bir önem sahip hataları uyarıların veya bilgi iletilerinin kabul edilir ve try… tarafından işlenircatch bloklarını kullanın.

  • Attentions toplu iş iş bir try… kapsam içinde olsa bile, bir toplu iş iş işlemi sona erecekcatch yapı.Buna dahildir tarafından gönderilen bir dikkat Microsoft Distributed Transaction Coordinator (ms dtc) bir dağıtılmış işlem başarısız olur.ms dtc dağıtılmış hareketleri yönetir.

    Not

    Yoksa bir dağıtılmış işlem yürütür kapsam içinde bir try bloğu ve bir hata oluşur, yürütme ilişkili catch bloğu için transfer.dağıtılmış işlem Bir yürütülemeyen durumuna girer.catch içerisindeki blok tarafından kesintiye uğrayabilir Microsoft Distributed Transaction Coordinator, yöneten dağıtılmış hareketleri.Hata oluştuğunda, ms dtc zaman uyumsuz olarak, katılan tüm sunucular bildirir dağıtılmış işlem, katılan tüm görevleri sona erer ve dağıtılmış işlem.Bu bildirim bir try… tarafından işlenen bir dikkat edilmesi şeklinde gönderilircatch yapı ve toplu iş iş iş sona erdi.Bir toplu iş çalýþmayý bitirince Veritabanı Altyapısı geri alır herhangi etkin yürütülemeyen hareketleri.toplu iş iş iş tamamlandığında, hareket bir yürütülemeyen durumuna girildiğinde hata ileti gönderilmedi, bir hata iletisi gösterir bir yürütülemeyen hareket algıladı ve dağıtılmış hareketleri hakkında daha fazla bilgi için geri istemci uygulamasına gönderilir, see Dağıtılmış hareketleri (veritabanı altyapısı).

Hata işlevler

TRY…catch hata bilgileri yakalamak için aşağıdaki hata işlevleri kullanır:

  • error_number() hata sayısını verir.

  • error_message(), hata iletisinin tam metni verir.Metin sağlanan uzunlukları, nesne adlarını veya süreleri gibi değiştirilebilir parametreler için değerler içerir.

  • ERROR_SEVERITY() hata önem verir.

  • error_state() hata durumu numarası verir.

  • ERROR_LINE(), hataya neden olan yordamı içinde satır sayısını verir.

  • error_procedure() hatanın oluştuğu saklı yordam veya tetikleyiciyi adını döndürür.

Hata bilgileri bu işlevleri kullanarak yerden alınır, kapsam , bir try… catch bloğucatch yapı.Hata işlevleri null olarak adlandırılan bir catch kapsam dışında döndüreceği blok.Hata İşlevler, saklı yordam içinde başvurulan ve catch saklı yordam çalıştırıldığında hata bilgilerini almak için kullanılan blok.Bunu yaparak, hata işleme kodunu her catch içinde yinelemek zorunda değil blok.Aşağıdaki kod örneği, SELECT deyim içinde TRY Blok generate bir sıfıra bölme hatası.Hata tarafından ele CATCH blok, kullanan bir saklı yordam için dönüş hata bilgileri.

USE AdventureWorks2008R2;
GO

-- Verify that the stored procedure does not exist.
IF OBJECT_ID ('usp_GetErrorInfo', 'P') IS NOT NULL
    DROP PROCEDURE usp_GetErrorInfo;
GO

-- Create a procedure to retrieve error information.
CREATE PROCEDURE usp_GetErrorInfo
AS
    SELECT 
        ERROR_NUMBER() AS ErrorNumber,
        ERROR_SEVERITY() AS ErrorSeverity,
        ERROR_STATE() as ErrorState,
        ERROR_PROCEDURE() as ErrorProcedure,
        ERROR_LINE() as ErrorLine,
        ERROR_MESSAGE() as ErrorMessage;
GO

BEGIN TRY
    -- Generate divide-by-zero error.
    SELECT 1/0;
END TRY
BEGIN CATCH
    -- Execute the error retrieval routine.
    EXECUTE usp_GetErrorInfo;
END CATCH;
GO

Derleme ve deyimi düzey hataları yeniden derleyin.

try… tarafından işleneceğini hataları iki türü vardır.Aynı yürütme içinde hata oluşursa catch düzey olarak try…catch yapı:

  • Bir toplu iş yürütülmesini engellemek sözdizimi hataları gibi hataları derleyin.

  • Derleme ertelenmiş ad çözümlemesi yüzünden sonra gerçekleşen nesne adı çözünürlüğü hataları gibi deyim düzey yeniden derlemesinde sırasında oluşan hataları.

Zaman toplu saklı yordam, veya try… içeren tetikleyiciBiri bu hataların try… catch yapı oluştururcatch yapı bu hataları ele alıyor.Bu hatalar için uygulama veya hata üretme yordam olarak adlandırılan toplu iş iş döndürecektir.Örneğin, aşağıdaki örnekte gösterildiği kod bir SELECT deyim neden olan bir sözdizimi hatası.Bu kod içinde yürütülürse SQL Server Management Studio Query Editor yürütme başlatılmayacağını çünkü toplu iş iş başarısız derleme.Hata sorgu Düzenleyici'ye döndü ve tarafından yakalanan değil TRY…CATCH.

USE AdventureWorks2008R2;
GO

BEGIN TRY
    -- This PRINT statement will not run because the batch
    -- does not begin execution.
    PRINT N'Starting execution';

    -- This SELECT statement contains a syntax error that
    -- stops the batch from compiling successfully.
    SELECT ** FROM HumanResources.Employee;
END TRY
BEGIN CATCH
    SELECT 
        ERROR_NUMBER() AS ErrorNumber,
        ERROR_MESSAGE() AS ErrorMessage;
END CATCH;
GO

Sözdizimi hatası önceki örnekte, aksine deyim düzey yeniden derlemesinde sırasında oluşan hata toplu iş iş derleme dan engel olmayacak, ancak yeniden derlemesinde deyim için başarısız gibi toplu iş iş sona erecek.Örneğin, bir toplu iş iş işlemi iki deyim ve ikinci deyim, var olmayan bir tablo başvuruları, ertelenmiş ad çözümlemesi başarıyla derlemek ve yürütme o ifadeyi çekirdekler kadar eksik tablo sorgu planı bağlama olmadan başlatmak toplu iş iş olur.toplu iş iş durur eksik başvurular deyimsine aldığında çalışan tablo ve bir hata döndürür.Bu tür bir hata bir try… tarafından elecatch yapı aynı düzey hatanın oluştuğu yürütme.Bu davranış aşağıdaki örnekte gösterilmiştir.

USE AdventureWorks2008R2;
GO

BEGIN TRY
    -- This PRINT statement will run because the error
    -- occurs at the SELECT statement.
    PRINT N'Starting execution';

    -- This SELECT statement will generate an object name
    -- resolution error because the table does not exist.
    SELECT * FROM NonExistentTable;
END TRY
BEGIN CATCH
    SELECT 
        ERROR_NUMBER() AS ErrorNumber,
        ERROR_MESSAGE() AS ErrorMessage;
END CATCH;
GO

try… kullanabilirsiniztry içinde ayrı toplu iş iş hata üretme kod yürütmek yoluyla derlenmesi veya deyim düzey yeniden derlemesinde sırasında oluşan hataları işlemek için catch blok.Örneğin, bir saklı yordam kod yerleştirerek ya da dinamik yürütme bunu Transact-SQL deyim kullanarak sp_executesql.Böylece try…Yüksek bir hata yakalamak için catch düzey yürütme hatası oluşumu daha.Örneğin, aşağıdaki kod bir nesne adı çözümlemesi hata üretir bir saklı yordam gösterir.İçeren toplu iş TRY…CATCH yapýsýnýn bir yüksek yürütme düzey saklı yordam; dan ve ortaya çıkan düşük hata düzey, yakalandı.

USE AdventureWorks2008R2;
GO

-- Verify that the stored procedure does not already exist.
IF OBJECT_ID ('usp_MyError', 'P') IS NOT NULL
    DROP PROCEDURE usp_MyError;
GO

CREATE PROCEDURE usp_MyError
AS
    -- This SELECT statement will generate
    -- an object name resolution error.
    SELECT * FROM NonExistentTable;
GO

BEGIN TRY
    -- Run the stored procedure.
    EXECUTE usp_MyError;
END TRY
BEGIN CATCH
    SELECT 
        ERROR_NUMBER() AS ErrorNumber,
        ERROR_MESSAGE() AS ErrorMessage;
END CATCH;
GO

Sonuç kümesi buradadır.

ErrorNumber ErrorMessage
----------- ---------------------------------------
208         Invalid object name 'NonExistentTable'.

Daha fazla bilgi için bkz: Ertelenmiş ad çözümlemesi ve derleme ve "derlenmesine yürütme planları" Bölüm'de Yeniden yürütme planı önbellekleme ve.

Uncommittable hareketleri

İçinde bir try…catch yapı hareketleri hareket kalır açık fakat kaydedilemeyen bir durum girebilirsiniz.İşlem verileri değiştirme veya geri çalışıyor gibi hareket günlüğüne yazma oluşturmak herhangi bir işlem yapamazsınız bir kayıt noktası.Ancak, bu durumda, hareket tarafından alınan kilitleri tutulur ve bağlantı da açık tutulur.Hareketin etkileri geri alma deyim verilene kadar veya toplu iş iş kadar ters çevrilir sona erer ve hareket otomatik olarak toplu iş iş geri Veritabanı Altyapısı.Toplu iş tamamlandığında, işlemin bir yürütülemeyen durumuna girildiğinde hata ileti gönderilmedi, istemci uygulamasına bir yürütülemeyen hareket algıladı ve geri bildiren bir hata iletisi gönderilir.

Bir hareket içinde bir try bir yürütülemeyen durumuna girer blok bir hata oluştuğunda, aksi halde sona hareket.Örneğin, çoğu hatalardan veri tanımılama dili (ddl) deyim (örneğin, create table) veya küme xact_abort on olarak ayarlandığında çoğu hataları try bloğunun dışına işlemi sona erdirir ancak bir hareket yürütülemeyen try bloðunun olun.

Bir catch bloğu içinde kod xact_state kullanarak bir hareket durumu için sınamalısınız işlev.Oturum yürütülemeyen bir hareket varsa xact_state -1 döndürür.catch blok xact_state -1 verir, günlüğe yazmaya oluşturmak eylemleri gerçekleştirmeniz gerekir.Aşağıdaki kod örneği, bir ddl deyim bir hata üretir ve kullanan XACT_STATE bir hareket için ele durumunu sınamak içinen uygun eylem.

USE AdventureWorks2008R2;
GO

-- Verify that the table does not exist.
IF OBJECT_ID (N'my_books', N'U') IS NOT NULL
    DROP TABLE my_books;
GO

-- Create table my_books.
CREATE TABLE my_books
    (
    Isbn        int PRIMARY KEY,
    Title       NVARCHAR(100)
    );
GO

BEGIN TRY
    BEGIN TRANSACTION;
        -- This statement will generate an error because the 
        -- column author does not exist in the table.
        ALTER TABLE my_books
            DROP COLUMN author;
    -- If the DDL statement succeeds, commit the transaction.
    COMMIT TRANSACTION;
END TRY
BEGIN CATCH
    SELECT
        ERROR_NUMBER() as ErrorNumber,
        ERROR_MESSAGE() as ErrorMessage;

    -- Test XACT_STATE for 1 or -1.
    -- XACT_STATE = 0 means there is no transaction and
    -- a commit or rollback operation would generate an error.

    -- Test whether the transaction is uncommittable.
    IF (XACT_STATE()) = -1
    BEGIN
        PRINT
            N'The transaction is in an uncommittable state. ' +
            'Rolling back transaction.'
        ROLLBACK TRANSACTION;
    END;

    -- Test whether the transaction is active and valid.
    IF (XACT_STATE()) = 1
    BEGIN
        PRINT
            N'The transaction is committable. ' +
            'Committing transaction.'
        COMMIT TRANSACTION;   
    END;
END CATCH;
GO

Kilitlenmeleri işleme

TRY…catch kilitlenmeleri işlemek için kullanılabilir.1205 çıkmaz kurban hata yakalandı catch bloğu tarafından ve işlem iş parçacıklarının geri duruma kadar alınabilmesi.Deadlocking hakkında daha fazla bilgi için bkz: Deadlocking.

Aşağıdaki örnekte gösterildiği nasıl try…catch kilitlenmeleri işlemek için kullanılabilir.Bu ilk bölüm ve hata bilgileri yazdırmak için kullanılan bir saklı yordam bir çıkmaz durumu göstermek için kullanılan bir tablo oluşturur.

USE AdventureWorks2008R2;
GO

-- Verify that the table does not exist.
IF OBJECT_ID (N'my_sales',N'U') IS NOT NULL
    DROP TABLE my_sales;
GO

-- Create and populate the table for deadlock simulation.
CREATE TABLE my_sales 
    (
    Itemid       INT PRIMARY KEY,
    Sales        INT not null
    );
GO

INSERT my_sales (itemid, sales) VALUES (1, 1);
INSERT my_sales (itemid, sales) VALUES (2, 1);
GO
  
-- Verify that the stored procedure for error printing
-- does not exist.
IF OBJECT_ID (N'usp_MyErrorLog',N'P') IS NOT NULL
    DROP PROCEDURE usp_MyErrorLog;
GO

-- Create a stored procedure for printing error information.
CREATE PROCEDURE usp_MyErrorLog
AS
    PRINT 
        'Error ' + CONVERT(VARCHAR(50), ERROR_NUMBER()) +
        ', Severity ' + CONVERT(VARCHAR(5), ERROR_SEVERITY()) +
        ', State ' + CONVERT(VARCHAR(5), ERROR_STATE()) + 
        ', Line ' + CONVERT(VARCHAR(5), ERROR_LINE());
    PRINT 
        ERROR_MESSAGE();
GO

Aynı anda iki ayrı Çalıştır komut dosyalarını oturum 1 ve 2 oturum için aşağıdaki kod SQL Server Management Studio bağlantıları.Her iki oturumları aynı satırları güncelleştirmek deneyin tablo.Oturumlardan birini ilk girişimi sırasında güncelleştirme işlemi başarılı olur ve başka oturum çıkmaz seçilmiş olması kurban.çıkmaz kurban hata catch bloğu atlamak yürütülmesine neden olur ve hareket bir yürütülemeyen durumuna girer.çıkmaz catch bloğu içinde kurban hareketi geri almak almak ve güncelleştirme başarılı veya yeniden deneme sınırına ulaşıldığında, hangisi ilk kez olmuyor kadar tablosunu güncelleştirme yeniden deneyin.

Oturum 1

Oturum 2

USE AdventureWorks2008R2;
GO
-- Declare and set variable
-- to track number of retries
-- to try before exiting.
DECLARE @retry INT;
SET @retry = 5;
-- Keep trying to update 
-- table if this task is 
-- selected as the deadlock 
-- victim.
WHILE (@retry > 0)
BEGIN
    BEGIN TRY
        BEGIN TRANSACTION;
    
        UPDATE my_sales
        SET sales = sales + 1
        WHERE itemid = 1;
        WAITFOR DELAY '00:00:13';
    
        UPDATE my_sales
        SET sales = sales + 1
        WHERE itemid = 2;
        SET @retry = 0;
        COMMIT TRANSACTION;
    END TRY
    BEGIN CATCH 
        -- Check error number.
        -- If deadlock victim error,
        -- then reduce retry count
        -- for next update retry. 
        -- If some other error
        -- occurred, then exit
        -- retry WHILE loop.
        IF (ERROR_NUMBER() = 1205)
            SET @retry = @retry - 1;
        ELSE
            SET @retry = -1;
        -- Print error information.
        EXECUTE usp_MyErrorLog;
  
        IF XACT_STATE() <> 0
            ROLLBACK TRANSACTION;
    END CATCH;
END; -- End WHILE loop.
GO
USE AdventureWorks2008R2;
GO
-- Declare and set variable
-- to track number of retries
-- to try before exiting.
DECLARE @retry INT;
SET @retry = 5;
--Keep trying to update 
-- table if this task is 
-- selected as the deadlock 
-- victim.
WHILE (@retry > 0)
BEGIN
    BEGIN TRY
       BEGIN TRANSACTION;
    
        UPDATE my_sales
        SET sales = sales + 1
        WHERE itemid = 2;
        WAITFOR DELAY '00:00:07';
    
        UPDATE my_sales
        SET sales = sales + 1
        WHERE itemid = 1;
        SET @retry = 0;
        COMMIT TRANSACTION;
    END TRY
    BEGIN CATCH 
        -- Check error number.
        -- If deadlock victim error,
        -- then reduce retry count
        -- for next update retry. 
        -- If some other error
        -- occurred, then exit
        -- retry WHILE loop.
        IF (ERROR_NUMBER() = 1205)
            SET @retry = @retry - 1;
        ELSE
            SET @retry = -1;
        -- Print error information.
        EXECUTE usp_MyErrorLog;
  
        IF XACT_STATE() <> 0
            ROLLBACK TRANSACTION;
    END CATCH;
END; -- End WHILE loop.
GO

TRY…RAISERROR catch

RAISERROR kullanılabilir try veya catch blok , bir try…Hata işleme davranışını etkilemek için yapı catch.

11 19 Bir try içinde yürütülen için önemi olan RAISERROR blok için ilişkili catch aktarmak denetim neden olan blok.RAISERROR 11 19 bir catch içinde yürütülen için önemi olan blok çağıran uygulama veya toplu iş iş bir hata döndürür.Bu yolla, RAISERROR arayan catch nedeniyle oluşan hata hakkında bilgi döndürmek için kullanılır blok yürütmek için.try… tarafından sağlanan hata bilgileriİşlevleri özgün hata numarası da dahil olmak üzere RAISERROR iletide, yakalanabilir bir hata YAKALAMAK; RAISERROR hata numarası olması gerekir ancak, >= 50000.

10 Veya daha düşük bir önem sahip RAISERROR bir bilgilendirme iletisi döndürüyor arama toplu iş iş veya uygulama bir catch çağırmadan blok.

20 Veya daha yüksek bir önem sahip RAISERROR catch çağırmadan veritabanı bağlantısını kapatır blok.

Aşağıdaki kod örneği gösterir nasıl RAISERROR içinde kullanılan bir CATCH Blok çağıran uygulama veya özgün hata bilgilerini dönmek içintoplu iş iş. Saklı yordam usp_GenerateError yürüten bir DELETE deyim içinde bir TRY blok, oluşturan bir kısıtlama ihlali hatası.İlişkili aktarmak yürütme hatası olur CATCH blok içinde usp_GenerateError nerede saklı yordam usp_RethrowError yürütüleceği raise kısıtlama ihlali hata bilgileri kullanarak RAISERROR.Tarafından üretilen bu hata RAISERROR çağıran toplu iş için döndürülen nerede usp_GenerateError yürütülen ve aktarmak için ilişkili yürütme neden olan CATCH blok çağıran bir toplu iş.

Not

RAISERROR 1 ile 127 arasında yalnızca durumu ile hatalara neden olabilir.Çünkü Veritabanı Altyapısı hatalara neden olabilir durumu 0 değeri olarak RAISERROR durum parametresi geçirmeden önce error_state tarafından döndürülen hata durumunu denetlemenizi öneririz

USE AdventureWorks2008R2;
GO

-- Verify that stored procedure does not exist.
IF OBJECT_ID (N'usp_RethrowError',N'P') IS NOT NULL
    DROP PROCEDURE usp_RethrowError;
GO

-- Create the stored procedure to generate an error using 
-- RAISERROR. The original error information is used to
-- construct the msg_str for RAISERROR.
CREATE PROCEDURE usp_RethrowError AS
    -- Return if there is no error information to retrieve.
    IF ERROR_NUMBER() IS NULL
        RETURN;

    DECLARE 
        @ErrorMessage    NVARCHAR(4000),
        @ErrorNumber     INT,
        @ErrorSeverity   INT,
        @ErrorState      INT,
        @ErrorLine       INT,
        @ErrorProcedure  NVARCHAR(200);

    -- Assign variables to error-handling functions that 
    -- capture information for RAISERROR.
    SELECT 
        @ErrorNumber = ERROR_NUMBER(),
        @ErrorSeverity = ERROR_SEVERITY(),
        @ErrorState = ERROR_STATE(),
        @ErrorLine = ERROR_LINE(),
        @ErrorProcedure = ISNULL(ERROR_PROCEDURE(), '-');

    -- Build the message string that will contain original
    -- error information.
    SELECT @ErrorMessage = 
        N'Error %d, Level %d, State %d, Procedure %s, Line %d, ' + 
            'Message: '+ ERROR_MESSAGE();

    -- Raise an error: msg_str parameter of RAISERROR will contain
    -- the original error information.
    RAISERROR 
        (
        @ErrorMessage, 
        @ErrorSeverity, 
        1,               
        @ErrorNumber,    -- parameter: original error number.
        @ErrorSeverity,  -- parameter: original error severity.
        @ErrorState,     -- parameter: original error state.
        @ErrorProcedure, -- parameter: original error procedure name.
        @ErrorLine       -- parameter: original error line number.
        );
GO

-- Verify that stored procedure does not exist.
IF OBJECT_ID (N'usp_GenerateError',N'P') IS NOT NULL
    DROP PROCEDURE usp_GenerateError;
GO

-- Create a stored procedure that generates a constraint violation
-- error. The error is caught by the CATCH block where it is 
-- raised again by executing usp_RethrowError.
CREATE PROCEDURE usp_GenerateError 
AS 
    BEGIN TRY
        -- A FOREIGN KEY constraint exists on the table. This 
        -- statement will generate a constraint violation error.
        DELETE FROM Production.Product
            WHERE ProductID = 980;
    END TRY
    BEGIN CATCH
        -- Call the procedure to raise the original error.
        EXEC usp_RethrowError;
    END CATCH;
GO

-- In the following batch, an error occurs inside 
-- usp_GenerateError that invokes the CATCH block in
-- usp_GenerateError. RAISERROR inside this CATCH block
-- generates an error that invokes the outer CATCH
-- block in the calling batch.
BEGIN TRY  -- outer TRY
    -- Call the procedure to generate an error.
    EXECUTE usp_GenerateError;
END TRY
BEGIN CATCH  -- Outer CATCH
    SELECT
        ERROR_NUMBER() as ErrorNumber,
        ERROR_MESSAGE() as ErrorMessage;
END CATCH;
GO

Akışını değiştirme

Akışını değiştirmek için Git bir try içinde kullanılabilir blok veya bir catch blok.goto da kullanılabilir bir try çıkmak için blok veya bir catch blok; Ancak, Git bir try girmek için kullanılamaz blok veya bir catch blok.

AdventureWorks2008R2 örnek veritabanı hata işleme çözümü

The AdventureWorks2008R2 sample database includes an error-handling solution designed to log information about errors that are caught by the CATCH block of a TRY…CATCH construct that can later be queried or analyzed.

dbo.ErrorLog tablo

The ErrorLog table records information about an error number, error severity, error state, name of the stored procedure or trigger where the error occurred, line number at which the error occurred, and the complete text of the error message.Tarih ve saat hata oluştuğu ile hata oluşturma yordamını kullanıcı adını kaydeder.Bu tablo doldurulduğunu, saklı yordam uspLogError içinde yürütüldüğünde kapsam bir try… catch bloğu,catch yapısı.

dbo.uspLogError

Saklı yordam uspLogError hata bilgilerini her oturum açtığında ErrorLog Tablo için catch aktarmak yürütülmesine neden olan bir hata hakkında blok , bir try…catch yapısı.İçin uspLogError hata bilgilerini eklemek için ErrorLog tablo, aşağıdaki koşullar gerekir:

  • uspLogError içinde yürütülen kapsam bir catch bloğu.

  • Geçerli hareket bir yürütülemeyen durumda ise, işlem yeniden yürütmeden önce alınır uspLogError.

Çıkış parametresi @ErrorLogID , uspLogError verir ErrorLogID tarafından eklenen satır uspLogError içine ErrorLog tablo.Varsayılan değer olan @ErrorLogID 0.Aşağıdaki örnek kodu gösterilir uspLogError.

CREATE PROCEDURE [dbo].[uspLogError] 
    @ErrorLogID [int] = 0 OUTPUT  -- Contains the ErrorLogID of the row inserted
                                  -- by uspLogError in the ErrorLog table.

AS
BEGIN
    SET NOCOUNT ON;

    -- Output parameter value of 0 indicates that error 
    -- information was not logged.
    SET @ErrorLogID = 0;

    BEGIN TRY
        -- Return if there is no error information to log.
        IF ERROR_NUMBER() IS NULL
            RETURN;

        -- Return if inside an uncommittable transaction.
        -- Data insertion/modification is not allowed when 
        -- a transaction is in an uncommittable state.
        IF XACT_STATE() = -1
        BEGIN
            PRINT 'Cannot log error since the current transaction is in an uncommittable state. ' 
                + 'Rollback the transaction before executing uspLogError in order to successfully log error information.';
            RETURN;
        END;

        INSERT [dbo].[ErrorLog] 
            (
            [UserName], 
            [ErrorNumber], 
            [ErrorSeverity], 
            [ErrorState], 
            [ErrorProcedure], 
            [ErrorLine], 
            [ErrorMessage]
            ) 
        VALUES 
            (
            CONVERT(sysname, CURRENT_USER), 
            ERROR_NUMBER(),
            ERROR_SEVERITY(),
            ERROR_STATE(),
            ERROR_PROCEDURE(),
            ERROR_LINE(),
            ERROR_MESSAGE()
            );

        -- Pass back the ErrorLogID of the row inserted
        SELECT @ErrorLogID = @@IDENTITY;
    END TRY
    BEGIN CATCH
        PRINT 'An error occurred in stored procedure uspLogError: ';
        EXECUTE [dbo].[uspPrintError];
        RETURN -1;
    END CATCH
END; 

dbo.uspPrintError

The stored procedure uspPrintError prints information about the error that caused execution to transfer to the CATCH block of a TRY…CATCH construct.uspPrintErrorshould be executed in the scope of a CATCH block; otherwise, the procedure returns without printing any error information.Aşağıdaki örnek kodu gösterilir uspPrintError.

CREATE PROCEDURE [dbo].[uspPrintError] 
AS
BEGIN
    SET NOCOUNT ON;

    -- Print error information. 
    PRINT 'Error ' + CONVERT(varchar(50), ERROR_NUMBER()) +
          ', Severity ' + CONVERT(varchar(5), ERROR_SEVERITY()) +
          ', State ' + CONVERT(varchar(5), ERROR_STATE()) + 
          ', Procedure ' + ISNULL(ERROR_PROCEDURE(), '-') + 
          ', Line ' + CONVERT(varchar(5), ERROR_LINE());
    PRINT ERROR_MESSAGE();
END;

Hata işleme örneği

Aşağıdaki örnekte gösterilmiştir AdventureWorks2008R2 hata işleme çözümüdür.Kod içinde TRY blok çalışır ile kayıt silmek ProductID 980 , Production.Product tablo.Bir yabancı anahtar kısıtlaması üzerinde tablo önler DELETE deyimini izleyen ve bir kısıtlama ihlali hatası üretilir.Yürütme transfer etmek bu hataya neden CATCH blok.İçinde CATCH blok, aşağıdaki eylemler gerçekleşir:

  • uspPrintErrorhata bilgileri yazdırır.

  • Hareket geri alındıktan sonra uspLogError hata bilgileri girer ErrorLog Tablo ve iade ErrorLogID eklenen satırın @ErrorLogID OUTPUT parametresi.

USE AdventureWorks2008R2;
GO

-- Variable to store ErrorLogID value of the row
-- inserted in the ErrorLog table by uspLogError 
DECLARE @ErrorLogID INT;

BEGIN TRY
    BEGIN TRANSACTION;

    -- A FOREIGN KEY constraint exists on this table. This 
    -- statement will generate a constraint violation error.
    DELETE FROM Production.Product
        WHERE ProductID = 980;

    -- If the delete operation succeeds, commit the transaction.
    COMMIT TRANSACTION;
END TRY
BEGIN CATCH
    -- Call procedure to print error information.
    EXECUTE dbo.uspPrintError;

    -- Roll back any active or uncommittable transactions before
    -- inserting information in the ErrorLog.
    IF XACT_STATE() <> 0
    BEGIN
        ROLLBACK TRANSACTION;
    END

    EXECUTE dbo.uspLogError @ErrorLogID = @ErrorLogID OUTPUT;
END CATCH; 

-- Retrieve logged error information.
SELECT * FROM dbo.ErrorLog WHERE ErrorLogID = @ErrorLogID;
GO

İç içe geçmiş hata işleme örneği

Aşağıdaki örnek, iç içe try… kullanarak gösterir.catch yapıları.

BEGIN TRY
    BEGIN TRY
        SELECT CAST('invalid_date' AS datetime)
    END TRY
    BEGIN CATCH 
        PRINT 'Inner TRY error number: ' +    
            CONVERT(varchar,ERROR_NUMBER()) + ' on line: ' +
            CONVERT(varchar, ERROR_LINE())
    END CATCH
    SELECT CAST('invalid_int' AS int)
END TRY
BEGIN CATCH
    PRINT 'Outer TRY error mumber: ' + CONVERT(varchar,ERROR_NUMBER())+ 
            ' on line: ' + CONVERT(varchar, ERROR_LINE())
END CATCH

Sonuç kümesi buradadır.

Inner TRY error number: 241 on line: 3

Outer TRY error number: 245 on line: 9