Partager via


TRY...CATCH (Transact-SQL)

S’applique à : SQL Server Azure SQL Database Azure SQL Managed Instance Azure Synapse Analytics Analytics Platform System (PDW) SQL analytics endpoint in Microsoft Fabric Warehouse in Microsoft Fabric

Implémente la gestion des erreurs pour Transact-SQL similaire à la gestion des exceptions dans les langages C# et Visual C++. Un groupe d’instructions Transact-SQL peut être placé dans un TRY bloc. Si une erreur se produit dans le TRY bloc, le contrôle est généralement passé à un autre groupe d’instructions placés dans un CATCH bloc.

Conventions de la syntaxe Transact-SQL

Syntaxe

BEGIN TRY
    { sql_statement | statement_block }
END TRY
BEGIN CATCH
    [ { sql_statement | statement_block } ]
END CATCH
[ ; ]

Arguments

sql_statement

Toute instruction Transact-SQL.

statement_block

Tout groupe d’instructions Transact-SQL dans un lot ou placé dans un BEGIN...END bloc.

Notes

Une TRY...CATCH construction intercepte toutes les erreurs d’exécution dont la gravité est supérieure à 10 et qui ne ferment pas la connexion de base de données.

Un TRY bloc doit être immédiatement suivi d’un bloc associé CATCH . L’inclusion d’autres instructions entre les END TRY instructions génère BEGIN CATCH une erreur de syntaxe.

Une TRY...CATCH construction ne peut pas s’étendre sur plusieurs lots. Une TRY...CATCH construction ne peut pas s’étendre sur plusieurs blocs d’instructions Transact-SQL. Par exemple, une TRY...CATCH construction ne peut pas s’étendre sur deux BEGIN...END blocs d’instructions Transact-SQL et ne peut pas s’étendre sur une IF...ELSE construction.

S’il n’y a aucune erreur dans le code placé dans un TRY bloc, lorsque la dernière instruction du TRY bloc se termine, le contrôle passe à l’instruction immédiatement après l’instruction associée END CATCH .

S’il existe une erreur dans le code placé entre un TRY bloc, le contrôle passe à la première instruction du bloc associé CATCH . Une fois le code du CATCH bloc terminé, le contrôle passe à l’instruction immédiatement après l’instruction END CATCH .

Remarque

Si l’instruction est la dernière instruction d’une procédure stockée ou d’un déclencheur, le END CATCH contrôle est repassé à l’instruction qui a appelé la procédure stockée ou déclenché le déclencheur.

Les erreurs interceptées par un CATCH bloc ne sont pas retournées à l’application appelante. Si une partie des informations d’erreur doit être retournée à l’application, le code du CATCH bloc doit le faire à l’aide de mécanismes tels que SELECT les jeux de résultats ou les RAISERROR instructions PRINT .

TRY...CATCH les constructions peuvent être imbriquées. Un TRY bloc ou un CATCH bloc peut contenir des constructions imbriquées TRY...CATCH . Par exemple, un CATCH bloc peut contenir une construction incorporée TRY...CATCH pour gérer les erreurs rencontrées par le CATCH code.

Les erreurs rencontrées dans un CATCH bloc sont traitées comme des erreurs générées ailleurs. Si le CATCH bloc contient une construction imbriquée TRY...CATCH , toute erreur dans le bloc imbriqué TRY passe le contrôle au bloc imbriqué CATCH . S’il n’existe aucune construction imbriquée TRY...CATCH , l’erreur est renvoyée à l’appelant.

TRY...CATCH crée des erreurs non gérées à partir de procédures stockées ou de déclencheurs exécutés par le code dans le TRY bloc. Les procédures stockées ou les déclencheurs peuvent également contenir leurs propres TRY...CATCH constructions pour gérer les erreurs générées par leur code. Par exemple, lorsqu’un TRY bloc exécute une procédure stockée et qu’une erreur se produit dans la procédure stockée, l’erreur peut être gérée de la manière suivante :

  • Si la procédure stockée ne contient pas sa propre TRY...CATCH construction, l’erreur retourne le contrôle au CATCH bloc associé au TRY bloc qui contient l’instruction EXECUTE .

  • Si la procédure stockée contient une TRY...CATCH construction, l’erreur transfère le CATCH contrôle au bloc dans la procédure stockée. Une fois le code de bloc terminé, le CATCH contrôle est repassé à l’instruction immédiatement après l’instruction EXECUTE qui a appelé la procédure stockée.

GOTOles instructions ne peuvent pas être utilisées pour entrer un ou CATCH un TRY bloc. GOTOles instructions peuvent être utilisées pour accéder à une étiquette à l’intérieur du même ou du même TRY bloc ou CATCH pour quitter un ou CATCH un TRY bloc.

La TRY...CATCH construction ne peut pas être utilisée dans une fonction définie par l’utilisateur.

Récupérer les informations d’erreur

Dans l’étendue d’un CATCH bloc, les fonctions système suivantes peuvent être utilisées pour obtenir des informations sur l’erreur qui a provoqué l’exécution du CATCH bloc :

Fonction Description
ERROR_NUMBER Retourne le nombre de l’erreur.
ERROR_SEVERITY Retourne la gravité.
ERROR_STATE Retourne le numéro d’état d’erreur.
ERROR_PROCEDURE Retourne le nom de la procédure stockée ou du déclencheur où l’erreur s’est produite.
ERROR_LINE Retourne le numéro de ligne à l’intérieur de la routine qui a provoqué l’erreur.
ERROR_MESSAGE Retourne le texte complet du message d’erreur. Le texte comprend les valeurs fournies pour tous les paramètres remplaçables, tels que les longueurs, les noms d'objet ou les heures.

Ces fonctions retournent NULL si elles sont appelées en dehors de l’étendue du CATCH bloc. Les informations d’erreur peuvent être récupérées à l’aide de ces fonctions n’importe où dans l’étendue du CATCH bloc. Par exemple, le script suivant montre une procédure stockée contenant des fonctions de gestion des erreurs : dans le bloc CATCH d'une construction TRY...CATCH, la procédure stockée est appelée et les informations sur l'erreur sont retournées.

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

-- Create 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 error retrieval routine.
    EXECUTE usp_GetErrorInfo;
END CATCH;

Les ERROR_* fonctions fonctionnent également dans un CATCH bloc à l’intérieur d’une procédure stockée compilée en mode natif.

Erreurs non affectées par un TRY... Construction CATCH

TRY...CATCH les constructions ne interceptent pas les conditions suivantes :

  • Les avertissements ou messages d'information dont la gravité est inférieure ou égale à 10.

  • Les erreurs dont le niveau de gravité est supérieur ou égal à 20 interrompent le traitement des tâches du Moteur de base de données SQL Server pour la session. Si une erreur se produit qui a une gravité de 20 ou supérieure et que la connexion de base de données n’est pas interrompue, TRY...CATCH gère l’erreur.

  • Un événement d'avertissement, tel qu'une requête d'interruption par le client ou une rupture de connexion avec le client, se produit.

  • Lorsqu’un administrateur système utilise l’instruction KILL pour mettre fin à la session.

Les types d’erreurs suivants ne sont pas gérés par un CATCH bloc lorsqu’ils se produisent au même niveau d’exécution que la TRY...CATCH construction :

  • Les erreurs de compilation, telles que les erreurs de syntaxe, qui empêchent un traitement de s'exécuter.

  • Les erreurs qui se produisent pendant une recompilation de niveau instruction, telles que les erreurs de résolution de nom d’objet qui surviennent après la compilation en raison d’une résolution de nom différée.

  • Erreurs de résolution de noms d’objets

Ces erreurs sont renvoyées au niveau qui a exécuté le traitement, la procédure stockée ou le déclencheur.

Si une erreur se produit pendant la recompilation au niveau de la compilation ou de l’instruction à un niveau d’exécution inférieur (par exemple, lors de l’exécution sp_executesql ou d’une procédure stockée définie par l’utilisateur) à l’intérieur du TRY bloc, l’erreur se produit à un niveau inférieur à la TRY...CATCH construction et sera gérée par le bloc associé CATCH .

L’exemple suivant montre comment une erreur de résolution de noms d’objet générée par une SELECT instruction n’est pas interceptée par la TRY...CATCH construction, mais interceptée par le CATCH bloc lorsque la même SELECT instruction est exécutée à l’intérieur d’une procédure stockée.

BEGIN TRY
    -- Table does not exist; object name resolution
    -- error not caught.
    SELECT *
    FROM NonexistentTable;
END TRY

BEGIN CATCH
    SELECT ERROR_NUMBER() AS ErrorNumber,
        ERROR_MESSAGE() AS ErrorMessage;
END CATCH

L’erreur n’est pas interceptée et le contrôle passe de la TRY...CATCH construction au niveau supérieur suivant.

L’exécution de l’instruction à l’intérieur SELECT d’une procédure stockée provoque l’erreur à un niveau inférieur au TRY bloc. L’erreur est gérée par la TRY...CATCH construction.

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

-- Create a stored procedure that will cause an
-- object resolution error.
CREATE PROCEDURE usp_ExampleProc
AS
SELECT *
FROM NonexistentTable;
GO

BEGIN TRY
    EXECUTE usp_ExampleProc;
END TRY

BEGIN CATCH
    SELECT ERROR_NUMBER() AS ErrorNumber,
        ERROR_MESSAGE() AS ErrorMessage;
END CATCH;

Transactions non modifiables et XACT_STATE

Si une erreur générée dans un TRY bloc entraîne l’invalidation de l’état de la transaction actuelle, la transaction est classifiée comme une transaction noncommittable. Une erreur qui met généralement fin à une transaction en dehors d’un TRY bloc entraîne l’entrée d’une transaction dans un état noncommittable lorsque l’erreur se produit à l’intérieur d’un TRY bloc. Une transaction noncommittable ne peut effectuer que des opérations de lecture ou un ROLLBACK TRANSACTION. La transaction ne peut pas exécuter d’instructions Transact-SQL qui généreraient une opération d’écriture ou un COMMIT TRANSACTION. La XACT_STATE fonction retourne une valeur de -1 si une transaction a été classifiée comme une transaction noncommittable. Lorsqu'un traitement est terminé, le Moteur de base de données restaure automatiquement toutes les transactions non validables actives. Si aucun message d’erreur n’a été envoyé lorsque la transaction a entré un état noncommittable, une fois le lot terminé, un message d’erreur est envoyé à l’application cliente. Cela indique qu'une transaction non validable a été détectée et annulée.

Pour plus d’informations sur les transactions non modifiables et la XACT_STATE fonction, consultez XACT_STATE.

Exemples

R. Utiliser TRY... CATCH

L’exemple suivant montre une instruction SELECT qui génère une erreur de division par zéro. L'erreur entraîne le saut de l'exécution vers le bloc CATCH associé.

BEGIN TRY
    -- Generate a divide-by-zero error.
    SELECT 1 / 0;
END TRY

BEGIN CATCH
    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;
END CATCH;
GO

B. Utiliser TRY... CATCH dans une transaction

L'exemple suivant montre comment un bloc TRY...CATCH fonctionne dans une transaction. L'instruction dans le bloc TRY génère une erreur de violation de contrainte.

BEGIN TRANSACTION;

BEGIN TRY
    -- Generate a constraint violation error.
    DELETE
    FROM Production.Product
    WHERE ProductID = 980;
END TRY

BEGIN CATCH
    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;

    IF @@TRANCOUNT > 0
        ROLLBACK TRANSACTION;
END CATCH;

IF @@TRANCOUNT > 0
    COMMIT TRANSACTION;
GO

C. Utiliser TRY... CATCH avec XACT_STATE

L'exemple suivant montre comment utiliser la construction TRY...CATCH pour gérer les erreurs qui surviennent dans une transaction. La fonction XACT_STATE détermine si la transaction doit être validée ou annulée. Dans cet exemple, SET XACT_ABORT est ON. Cela rend la transaction non validable lorsque l'erreur de violation de contrainte se produit.

-- Check to see whether this stored procedure exists.
IF OBJECT_ID(N'usp_GetErrorInfo', N'P') IS NOT NULL
    DROP PROCEDURE usp_GetErrorInfo;
GO

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

-- SET XACT_ABORT ON will cause the transaction to be uncommittable
-- when the constraint violation occurs.
SET XACT_ABORT ON;

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 statement succeeds, commit the transaction.
    COMMIT TRANSACTION;
END TRY

BEGIN CATCH
    -- Execute error retrieval routine.
    EXECUTE usp_GetErrorInfo;

    -- Test XACT_STATE:
    -- If 1, the transaction is committable.
    -- If -1, the transaction is uncommittable and should
    --     be rolled back.
    -- XACT_STATE = 0 means that 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 committable.
    -- You may want to commit a transaction in a catch block if you want to commit changes to statements that ran prior to the error.
    IF (XACT_STATE()) = 1
    BEGIN
        PRINT N'The transaction is committable. Committing transaction.'

        COMMIT TRANSACTION;
    END;
END CATCH;
GO