TRY...CATCH (Transact-SQL)

S’applique à :SQL ServerAzure SQL DatabaseAzure SQL Managed InstanceAzure Synapse AnalyticsAnalytics Platform System (PDW)Point de terminaison analytique SQL dans Microsoft FabricEntrepôt dans Microsoft Fabric

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

Conventions de la syntaxe Transact-SQL

Syntaxe

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

Remarque

Pour afficher la syntaxe Transact-SQL pour SQL Server 2014 (12.x) et versions antérieures, consultez Versions antérieures de la documentation.

Arguments

sql_statement
Peut correspondre à n’importe quelle instruction Transact-SQL.

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

Notes

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

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

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

Si le code inclus dans un bloc TRY ne contient aucune erreur, lorsque l'exécution de la dernière instruction du bloc TRY est terminée, le contrôle est passé à l'instruction qui se trouve immédiatement après l'instruction END CATCH associée.

S'il existe une erreur dans le code inclus dans le bloc TRY, le contrôle est passé à la première instruction du bloc CATCH associé. Lorsque le code du bloc CATCH est terminé, le contrôle est passé à l'instruction qui se trouve immédiatement après l'instruction END CATCH.

Notes

Si l'instruction END CATCH se trouve dans la dernière instruction d'une procédure stockée ou d'un déclencheur, le contrôle revient à l'instruction qui a appelé la procédure stockée ou activé le déclencheur.

Les erreurs interceptées par un bloc CATCH ne sont pas renvoyées à l'application appelante. Si une partie des informations sur les erreurs doivent être renvoyées à l'application, le code dans le bloc CATCH doit pour ce faire utiliser des mécanismes tels que les jeux de résultats SELECT ou les instructions RAISERROR et PRINT.

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

Les erreurs rencontrées dans un bloc CATCH sont traitées comme les erreurs générées à n'importe quel autre emplacement. Quand un bloc CATCH contient une construction TRY...CATCH imbriquée, toute erreur dans le bloc imbriqué TRY passe le contrôle au bloc CATCH imbriqué. S’il n’existe pas de construction TRY...CATCH imbriquée, l’erreur est renvoyée à l’appelant.

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

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

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

Les instructions GOTO ne peuvent pas être utilisées pour entrer un bloc TRY ou CATCH. Les instructions GOTO peuvent être utilisées pour accéder directement à une étiquette dans le même bloc TRY ou CATCH ou pour quitter un bloc TRY ou CATCH.

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

Extraction des informations sur les erreurs

Dans la portée d'un bloc CATCH, les fonctions système suivantes peuvent être utilisées pour obtenir des informations sur l'erreur qui a entraîné l'exécution du bloc CATCH :

  • ERROR_NUMBER() renvoie le numéro de l’erreur.

  • ERROR_SEVERITY() renvoie la gravité de l’erreur.

  • ERROR_STATE() renvoie le numéro d’état de l’erreur.

  • ERROR_PROCEDURE() renvoie le nom de la procédure stockée ou du déclencheur où s’est produite l’erreur.

  • ERROR_LINE() renvoie le numéro de ligne au sein de la routine qui a entraîné l’erreur.

  • ERROR_MESSAGE() renvoie 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 renvoient la valeur NULL si elles sont appelées en dehors de l'étendue du bloc CATCH. Les informations sur les erreurs peuvent être récupérées à l'aide de ces fonctions à partir de n'importe quel emplacement dans l'étendue du bloc CATCH. 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 fonctions ERROR_* fonctionnent également dans un bloc CATCH à l’intérieur d’une procédure stockée compilée en mode natif.

Erreurs non affectées par une construction TRY...CATCH

Les constructions TRY...CATCH n’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 dont le niveau de gravité est supérieur ou égal à 20 survient et que la connexion à la 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.

  • Cela survient lorsque la session est terminée par un administrateur système utilisant l'instruction KILL.

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

  • 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 survient pendant la compilation ou la recompilation au niveau de l’instruction à un niveau d’exécution inférieur (par exemple lors de l’exécution de sp_executesql ou d’une procédure stockée définie par l’utilisateur) à l’intérieur du bloc TRY, l’erreur survient à un niveau inférieur à la construction TRY...CATCH et est gérée par le bloc CATCH associé.

L'exemple suivant montre comment une erreur de résolution de noms d'objets générée par une instruction SELECT n'est pas interceptée par la construction TRY...CATCH, mais par le bloc CATCH lorsque la même instruction SELECT est exécutée au sein 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 est passé de la construction TRY...CATCH au niveau supérieur suivant.

L'exécution de l'instruction SELECT au sein d'une procédure stockée entraîne l'occurrence de l'erreur à un niveau inférieur à celui du bloc TRY. L'erreur sera gérée par la construction TRY...CATCH.

-- 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 validables et XACT_STATE

Si une erreur générée dans un bloc TRY entraîne l'invalidation de la transaction actuelle, elle est classifiée comme transaction non validable. Une erreur qui termine normalement une transaction en dehors d'un bloc TRY fait entrer la transaction dans un état non validable lorsqu'elle survient au sein d'un bloc TRY. Une transaction non validable ne peut effectuer que des opérations de lecture ou ROLLBACK TRANSACTION. La transaction ne peut exécuter aucune instruction Transact-SQL qui générerait une opération d’écriture ou un COMMIT TRANSACTION. La fonction XACT_STATE renvoie une valeur de -1 si une transaction a été classifiée comme non validable. 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 est passée dans un état non validable, une erreur est envoyée à l'application cliente lorsque le traitement se termine. Cela indique qu'une transaction non validable a été détectée et annulée.

Pour plus d’informations sur les transactions non validables et la fonction XACT_STATE, consultez XACT_STATE (Transact-SQL).

Exemples

R. Utilisation de TRY...CATCH

L'exemple suivant illustre 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. Utilisation de 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. Utilisation de 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  

Voir aussi

THROW (Transact-SQL)
Niveaux de gravité des erreurs du moteur de base de données
ERROR_LINE (Transact-SQL)
ERROR_MESSAGE (Transact-SQL)
ERROR_NUMBER (Transact-SQL)
ERROR_PROCEDURE (Transact-SQL)
ERROR_SEVERITY (Transact-SQL)
ERROR_STATE (Transact-SQL)
RAISERROR (Transact-SQL)
@@ERROR (Transact-SQL)
GOTO (Transact-SQL)
BEGIN...END (Transact-SQL)
XACT_STATE (Transact-SQL)
SET XACT_ABORT (Transact-SQL)