Share via


Kullanarak TRY... CATCH Transact-SQL'DE

Hataları Transact-SQL kod bir özel durum işleme özellikleri için benzer TRY…CATCH yapısı'nı kullanarak işlenebilecek Microsoft Visual C++ ve Microsoft Visual C# dilleri. Bir TRY…CATCH yapýsý iki kısımdan oluşur: TRY blok ve bir CATCH blok. Içinde bir hata koşulu algılandığında bir Transact-SQL TRY blok içinde olan bir deyim hata işlenebilecek bir CATCH blok için Denetim geçirilir.

CATCH blok özel durum işleme sonra denetim için ilk sonra aktarılır Transact-SQL END CATCH deyim aşağıdaki 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 blok içinde herhangi bir hata varsa, Denetim deyim hemen ilişkili END CATCH deyiminden sonraki deyime geçirir.END CATCH deyim bir saklı yordam veya tetikleyiciyi son ise, Denetim deyim saklı yordam veya tetiği başlatılır geçirilir.

TRY blok BEGIN TRY ile başlayan deyim ve END TRY ile biten deyim.Bir veya daha çok Transact-SQL arasında BEGIN TRY ve END TRY deyimlerini, ifadeleri belirtilebilir.

TRY blok hemen bir CATCH blok gelmelidir.Bir CATCH blok BEGIN CATCH ile başlayan deyim ve END CATCH ile biten deyim.Içinde Transact-SQL, her bir TRY bloğuna yalnızca bir CATCH blok ile ilişkilidir.

TRY…CATCH ile çalışma

TRY…CATCH yapısı'nı kullandığınızda, aşağıdaki yönergeleri ve önerileri göz önünde bulundurun:

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

    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
    
  • TRY blok hemen bir CATCH blok gelmelidir.

  • TRY…CATCH yapıları iç içe kullanılabilir.Bu, diğer bir TRY ve CATCH bloğu içinde TRY…CATCH yapıları yerleştirilebilir anlamına gelir.Program denetimi içinde iç içe geçmiş bir TRY bloğuna bir hata ortaya çıktığında, iç içe geçmiş TRY blok ile ilgili CATCH blok transfer edilir.

  • Belirli bir CATCH blok içinde oluşan bir hatayı işlemek için , belirtilen CATCH blok içinde TRY…... CATCH blok yazın.

  • 20 Veya daha yüksek önem derecesi, neden olan hatalar Database Engine bağlantıyı kapatmak için TRY…CATCH blok tarafından işleneceğini değil. Ancak, Bağlantı kapatılmadı sürece TRY…CATCH 20 veya daha büyük bir önem hatayla işleyecektir.

  • 10 Veya daha düşük bir önem olan hatalar, uyarıların veya bilgi iletilerinin günlüğünün olduğu düşünülür ve TRY…CATCH engeller tarafından işlenmez.

  • Toplu iş içinde bile attentions toplu sonlandırılacak kapsam, bir TRY…CATCH yapýsý.Bu, gönderilen bir dikkat içerir Microsoft Dağıtılmış işlem Eşgüdümcüsü (MS dağıtılmış işlem başarısız olduğunda DTC). MS DTC dağıtılmış hareketleri yönetir.

    Not

    Içinde bir dağıtılmış işlem yürütür, kapsam bir TRY bloğuna ve bir hata oluşur, yürütme için ilgili CATCH blok transfer edilir.Dağıtılmış işlem yürütülemeyen bir duruma girer.Yürütme CATCH blok içinde tarafından kesintiye uğratılmasına Microsoft Hangi dağıtılmış işlemleri yönetir ve dağıtılmış işlem düzenleyicisi. Hata oluştuğunda, MS DTC zaman uyumsuz olarak dağıtılmış işleme katılan tüm sunucuları bildirir ve dağıtılmış işleme katılan tüm görevleri sona erdirir.Bu bildirim olmayan bir dikkat biçiminde gönderilen bir TRY…CATCH yapısı tarafından işlenen ve toplu iş iş iş sonlandırıldı.Çalışan, toplu iş iş iş sona erdiğinde Database Engine tüm etkin yürütülemeyen işlemleri'ne geri alır. Hata iletisi gönderirse bir hata iletisi yürütülemeyen bir hareketi algılandı gösteren istemci uygulamaya gönderilir ve geri dağıtılmış hareketleri hakkında daha fazla bilgi için bkz: toplu iş iş iş tamamlandığında, hareket yürütülemeyen durumu, girilen Dağıtılmış işlemler (Veritabanı Altyapısı).

Hata işlevler

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

  • ERROR_NUMBER() hata verir.

  • ERROR_MESSAGE(), hata iletisinin tam metni verir.Metni uzunlukları, nesne adları veya zamanları gibi değiştirilebilir parametreleri için sağlanan değerler içerir.

  • ERROR_SEVERITY() hata önem verir.

  • ERROR_STATE() hata durumu döndürür.

  • ERROR_LINE() hataya neden olan bir yordam içinde satır numarasını verir.

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

Hata bilgisi yerden bu işlevleri kullanarak alınan bir TRY…CATCH yapýsý CATCH blok kapsamında.Hata işlevleri, NULL kapsam dışında bir CATCH blok) adı verilen, döndürecektir.Hata işlevleri, bir saklı yordamın içinde başvurulan ve CATCH blok içinde saklı yordam çalıştırıldığında hata bilgilerini almak için kullanılabilir.Bunu yaptığınızda, her bir CATCH blok kodunda hata yinelemeniz gerekmez.Aşağıdaki kod örneği içinde SELECT Deyimde TRY blok, bir sıfıra bölme hatası üretecektir. Hata tarafından ele CATCH blok, saklı bir yordam hata bilgileri kullanır.

USE AdventureWorks;
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 deyim-recompile hataları düzey

Aynı yürütme, hata ortaya çıkarsa TRY…CATCH tarafından işleneceğini hatalar iki tür düzey TRY…CATCH yapýsý olarak:

  • Bir toplu iş, yürütmesine engel olmak sözdizimi hataları gibi hataları derleyin.

  • Sırasında oluşan hataları deyim-düzey recompilation (derleme ertelenen ad çözümlemesi yüzünden sonra gerçekleşen nesne adı çözümlemesi hataları gibi.

TRY…CATCH yapýsý, toplu iş iş, saklı yordam veya tetikleyiciyi TRY…CATCH yapýsý içeren aşağıdaki hatalardan birine oluşturduğunda, bu hatalar işlemez.Bu hatalar belirli bir uygulama veya hata oluşturma yordamını çağıran bir toplu iş döndürecektir.Örneğin, bu aşağıdaki örnekte gösterildiği kod bir SELECT deyim bir sözdizimi hatasına neden oluyor. Bu kod içinde gerçekleştirildiğinde, SQL Server Management Studio toplu iş iş derleme başarısız sorgu Düzenleyicisi'nde, yürütme başlatılmaz. Hata Query düzenleyicisine döndürdü ve tarafından yakalanan. TRY…CATCH.

USE AdventureWorks;
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

Farklı bir sözdizimi hatası önceki örnekte, deyim düzey recompilation sırasında oluşan bir hata, toplu iş derleme gelen engellemez, ancak raporu için recompilation başarısız olarak toplu işlem sonlandırılacak.Örneğin, bir toplu iş iki deyim ve ikinci deyim varolmayan bir tabloya başvuruyor, ertelenen ad çözümlemesi başarıyla derlemek ve yürütme, bu deyim derlenmiş çekirdekler kadar eksik tablo için bir sorgu planını bağlama olmadan başlatmak toplu iş olur.toplu iş iş iş için aldığında çalışan vermiyor deyim eksik tablosu ve hata verir.Bu tür bir hata değil işlenecek tarafından aynı anda bir TRY…CATCH yapýsý düzey hatanın oluştuğu yürütme.Aşağıdaki örnekte, bu davranışı gösterir.

USE AdventureWorks;
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 blok içinde ayrı bir toplu iş oluşturma hatası kod yürütmek yoluyla bir derleme veya deyim düzey recompilation sırasında oluşan hataları işlemek için TRY…CATCH kullanabilirsiniz.Örneğin, saklı yordam kodu girerek veya dinamik yürütülüyor bunu Transact-SQL deyim kullanma Sp_executesql.Bu hatanın yüksek yakalamak üzere TRY…CATCH sağlar düzey yürütülmesinin hata oluşumu farklı.Örneğin, aşağıdaki kod, nesne adı çözümlemesi hata oluşturduğu saklı yordam gösterir.Içeren toplu iş TRY…CATCH saklı yordam; daha yüksek düzeyde yapýsý yürütülüyor ve daha alttaki bir düzeyde oluşan hata oluştu.

USE AdventureWorks;
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

Here is the result set.

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

Daha fazla bilgi için bkz: Ertelenen ad çözümlemesi ve derleme"Yürütme planları Recompiling" bölümünde ve Yürütme planı önbelleğe alma ve yeniden.

yürütülemeyen hareketleri

Bir TRY…CATCH yapısı hareketlerin durumu hareketin açık kalır ancak kaydedilmiş olamaz girebilirsiniz.Işlem, işlem günlüğü, verileri değiştirme veya bir kayıt noktası için geri almak almak çalışılırken yazma oluşturmak herhangi bir eylem gerçekleştiremiyor.Ancak, bu durumda, işlem tarafından alınan kilitleri sürdürülür ve bağlantı da açık tutulur.Hareket etkilerinin bir ROLLBACK deyim verilen kadar veya toplu iş kadar tersine değil sona erer ve hareket otomatik olarak toplu geri Database Engine. toplu iş iş iş tamamlandığında yürütülemeyen durumu, hareket girdiğinizde bir hata iletisi gönderilmişse, bir hata iletisi yürütülemeyen bir hareketi algıladı ve geri gösteren istemci uygulamaya gönderilir.

Bir hareket yürütülemeyen bir duruma girdiği bir TRY içinde bir hata oluştuğunda blok yoksa hareket sonlandırmış.Örneğin, bir veri tanımlama dili (DDL) deyim (örneğin, CREATE tablo) çoğu hatalarını veya küme XACT_ABORT, ON olarak ayarlandığında, çoğu hataları bir TRY bloğunun dışına hareket sona erdirmek, ancak bir hareket içinde bir TRY bloğuna yürütülemeyen olun.

Bir CATCH blok içinde kod XACT_STATE işlevini kullanarak bir hareketin durumunu sınamanız gerekir.Oturum yürütülemeyen bir hareket varsa XACT_STATE bir -1 döndürür.CATCH blok XACT_STATE bir -1 döndürürse günlüğe yazmaya üreten herhangi bir eylem gerçekleştirmeniz gerekir.Aşağıdaki kod örneği, bir DDL ekstresindeki bir hata oluşturur ve kullanır XACT_STATE en uygun eylem için bir hareket durumunu sınamak için .

USE AdventureWorks;
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.Hata 1205 çıkmaz kurban CATCH blok yakalandı ve iş parçacıklarını kilidi haline geri kadar hareket alınması.Deadlocking hakkında daha fazla bilgi için bkz: Deadlocking.

Aşağıdaki örnek, kilitlenmeleri işlemeye TRY…CATCH nasıl kullanılabileceğini gösterir.Bu ilk bölümünde hata bilgileri yazdırmak için kullanılacak bir saklı yordam ve bir çıkmaz durumu göstermek için kullanılan bir tablo oluşturur.

USE AdventureWorks;
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

Oturum 1 ve 2 oturumu için aşağıdaki kod komut dosyaları aynı anda iki ayrı çalıştırın. SQL Server Management Studio olarak işle. Her iki oturumların aynı satırda güncelleştirmeye tablo.Tüm oturumların bir güncelleştirme işlemi sırasında ilk girişimde başarılı olur ve başka oturum, çıkmaz kurban olarak seçilecektir.çıkmaz kurban hata CATCH blok için atlamak yürütme neden olur ve hareket yürütülemeyen bir duruma girer.CATCH blok içinde çıkmaz kurban hareketi geri almak almak ve güncelleştirmenin başarılı ya da hangisi olacağını ilk yeniden deneme sınırına ulaşıldığında kadar tablo güncelleştirme için yeniden deneyin.

Oturum 1

Oturum 2

USE AdventureWorks;
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 AdventureWorks;
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

RAISERROR ile TRY…CATCH

RAISERROR hata işleme davranışını etkileyen bir TRY…CATCH yapýsý TRY veya CATCH blok içinde kullanılabilir.

Bir önem 11 19 TRY blok yürütülmesi için sahip RAISERROR ilgili CATCH blok transfer etmek, Denetim neden olur.Çağıran uygulama veya toplu iş, bir önem 11 19 bir CATCH blok içinde yürütülmesi için sahip RAISERROR hata verir.Bu yolla, RAISERROR arayanın CATCH blok yürütmesine neden hata hakkında bilgileri döndürmek için kullanılır.TRY…CATCH hata işlevleri tarafından sağlanan hata bilgileri RAISERROR iletide, özgün hata numarası dahil olmak üzere yakalanan; ancak, hata numarasını RAISERROR için gerekir >= 50000.

10 Veya daha düşük bir önem olan RAISERROR bir bilgi iletisi çağıran toplu iş iş iş veya uygulama bir CATCH blok yürütmesini olmadan döndürür.

Önem derecesi 20 veya daha yüksek olan RAISERROR CATCH blok yürütmesini olmadan, veritabanı bağlantısını kapatır.

Aşağıdaki örnekte gösterildiği nasıl kod RAISERROR içinde kullanılan bir CATCH çağıran uygulama veya toplu iş, özgün hata bilgilerini geri dönmek için blok'ı tıklatın. Saklı yordam usp_GenerateError yürüten bir DELETE deyim içinde bir TRY blok bir kısıtlama ihlali hatasına neden olur. Hata ilişkili aktarmak yürütme neden olur. CATCH blok içinde usp_GenerateError Burada saklı yordam usp_RethrowError kısıtlama ihlali hatası bilgi using artýrmak için yürütüldü RAISERROR. Bu hata, tarafından oluşturulan RAISERROR arama işlemi için döndürülen yeri usp_GenerateError çalıştırıldı ve yürütme ilişkili aktarmak neden olur. CATCH Arama toplu iş iş işleme engelleyin.

Not

RAISERROR, 1 ile 127 yalnızca durumu ile hatalara neden olabilir.Çünkü Database Engine hataları neden durumu 0 ile bunu bir değeriyle RAISERROR Durum parametresini geçirmeden önce ERROR_STATE tarafından döndürülen hata durumunu denetlemenizi öneririz.

USE AdventureWorks;
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

Yürütme akışının değiştirme

Akış yürütme değiştirmek için , GOTO bir TRY bloğuna ya da bir CATCH blok içinde kullanılabilir.GOTO bir TRY bloğuna veya bir CATCH blok çıkmak için de kullanılabilir; ancak, GOTO blok TRY veya CATCH blok girmek için kullanılamaz.

Hata-işlem Solution AdventureWorks örnek veritabanındaki

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

Tablo dbo.ErrorLog

The ErrorLog tablo records information about an error number, error severity, error state, name of the saklı yordam or trigger where the error occurred, line number at which the error occurred, and the complete text of the error message.Tarih ve saat, hatanın oluştuğu hata oluşturma yordamına yürütülen bir kullanıcı adı kaydeder.Bu tablo doldurulur, saklı yordam uspLogError bir TRY…CATCH yapýsý CATCH blok kapsam içinde yürütülür.Daha fazla bilgi için bkz:ErrorLog tablo (AdventureWorks).

dbo.uspLogError

Saklı yordam uspLogError hata bilgileri günlüğe kaydeder.ErrorLog tablo hakkında bir TRY…CATCH yapýsý CATCH blok aktarmak yürütülmesine neden olan hata.Için uspLogError hata bilgileri eklemek içinErrorLog tablosu, aşağıdaki koşullar bulunmalıdır:

  • uspLogError bir CATCH blok kapsam içinde yürütülür.

  • Cari işlem bir yürütülemeyen durumundaysa, işlem yürütülmeden önce döndürülüyor uspLogError.

Çıkış parametresi @ ErrorLogID of uspLogError verir...ErrorLogID tarafından eklenen bir satırınuspLogError into the ErrorLog tablo.Varsayılan değeri @ ErrorLogID is 0.Aşağıdaki örnek kodu gösterilir. uspLogError. Daha fazla bilgi için bkz:Saklı yordamlar, AdventureWorks.

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.uspPrintError should 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. Daha fazla bilgi için bkz:Saklı yordamlar, AdventureWorks.

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 AdventureWorks hata işleme bir çözümdür. Içinde kod TRY blok kayıtla silmeye çalışır ProductID 980 içinde Production.Product TABLO. yabancı anahtar kısıtlama tablo engeller DELETE izleyen ve bir kısıtlama ihlali hatası ekstresindeki oluşturulur. Bu hata, transfer etmek yürütme neden CATCH blok. Içinde CATCH blok, aşağıdaki eylemler gerçekleşir:

  • uspPrintError hata bilgileri yazdırır.

  • Sonra hareketi, döndürülüyor uspLogError hata bilgileri girer ErrorLog Tablo ve döndürür ErrorLogID eklenen bir satırın @ErrorLogID OUTPUT Parametre.

USE AdventureWorks;
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ç içe geçmiş hata işleme örneği

Aşağıdaki örnek, iç içe geçmiş TRY…CATCH yapıları kullanarak gösterir.

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

Here is the result set.

Inner TRY error number: 241 on line: 3

Outer TRY error number: 245 on line: 9