Récupération d'informations d'erreur dans Transact-SQL

Deux méthodes permettent d'obtenir des informations d'erreur dans Transact-SQL :

  • Dans l'étendue du bloc CATCH d'une construction TRY…CATCH, vous pouvez utiliser les fonctions système suivantes :

    • ERROR_LINE() retourne le numéro de la ligne dans laquelle l'erreur s'est produite.

    • ERROR_MESSAGE() retourne le texte du message à communiquer à l'application. Le texte comprend les valeurs fournies pour tous les paramètres substituables, tels que les longueurs, les noms d'objets ou les heures.

    • ERROR_NUMBER() retourne le numéro de l'erreur.

    • ERROR_PROCEDURE() retourne le nom de la procédure stockée ou du déclencheur dans lequel l'erreur s'est produite. Cette fonction retourne la valeur NULL si l'erreur ne s'est pas produite dans une procédure stockée ou dans un déclencheur.

    • ERROR_SEVERITY() retourne le niveau de gravité.

    • ERROR_STATE() retourne l'état.

  • Dès que vous avez exécuté une instruction Transact-SQL, vous pouvez tester une erreur et récupérer son numéro à l'aide de la fonction @@ERROR.

Utilisation des fonctions ERROR_LINE, ERROR_MESSAGE, ERROR_NUMBER, ERROR_PROCEDURE, ERROR_SEVERITY et ERROR_STATE

Les fonctions ERROR_LINE, ERROR_MESSAGE, ERROR_NUMBER, ERROR_PROCEDURE, ERROR_SEVERITY et ERROR_STATE ne retournent des informations d'erreur que lorsqu'elles sont utilisées dans l'étendue du bloc CATCH d'une construction TRY…CATCH. En dehors de l'étendue d'un bloc CATCH, elles retournent la valeur NULL. Ces fonctions retournent des informations sur l'erreur qui a provoqué l'appel du bloc CATCH. Elles retournent les mêmes informations d'erreur, quel que soit l'endroit où elles sont exécutées dans l'étendue d'un bloc CATCH, même si elles sont référencées plusieurs fois. Les fonctions fournissent aux instructions Transact-SQL les mêmes données que celles retournées à l'application.

Dans les blocs CATCH imbriqués, les fonctions ERROR_LINE, ERROR_MESSAGE, ERROR_NUMBER, ERROR_PROCEDURE, ERROR_SEVERITY et ERROR_STATE retournent des informations d'erreur spécifiques au bloc CATCH dans lequel elles sont référencées. Par exemple, le bloc CATCH d'une construction TRY...CATCH externe peut posséder une construction TRY...CATCH imbriquée. Dans le bloc CATCH imbriqué, ces fonctions retournent des informations sur l'erreur qui a appelé le bloc CATCH interne. Les mêmes fonctions dans le bloc CATCH externe retourneraient des informations sur l'erreur qui a appelé ce bloc CATCH.

À titre d'illustration, l'exemple ci-dessous montre que lorsque la fonction ERROR_MESSAGE est référencée dans le bloc CATCH externe, elle retourne le texte de message généré par le bloc TRY externe. Lorsqu'elle est référencée dans le bloc CATCH interne, la fonction ERROR_MESSAGE retourne le texte généré dans le bloc TRY interne. L'exemple montre également que, dans le bloc CATCH externe, la fonction ERROR_MESSAGE retourne toujours le message généré dans le bloc TRY externe, même après l'exécution de la construction TRY...CATCH interne.

IF EXISTS (SELECT message_id FROM sys.messages
    WHERE message_id = 50010)
        EXECUTE sp_dropmessage 50010;
GO
EXECUTE sp_addmessage @msgnum = 50010,
    @severity = 16, 
    @msgtext = N'Message text is from the %s TRY block.';
GO
BEGIN TRY -- Outer TRY block.
    -- Raise an error in the outer TRY block.
    RAISERROR (50010, -- Message id.
        16, -- Severity,
        1, -- State,
        N'outer'); -- Indicate TRY block.
END TRY -- Outer TRY block.
BEGIN CATCH -- Outer CATCH block.
    -- Print the error message recieved for this
    -- CATCH block.
    PRINT N'OUTER CATCH1: ' + ERROR_MESSAGE();
    BEGIN TRY -- Inner TRY block.
        -- Start a nested TRY...CATCH and generate
        -- a new error.
        RAISERROR (50010, -- Message id.
            16, -- Severity,
            2, -- State,
            N'inner'); -- Indicate TRY block.
    END TRY -- Inner TRY block.
    BEGIN CATCH -- Inner CATCH block.
        -- Print the error message recieved for this
        -- CATCH block.
        PRINT N'INNER CATCH: ' + ERROR_MESSAGE();
    END CATCH; -- Inner CATCH block.
    -- Show that ERROR_MESSAGE in the outer CATCH
    -- block still returns the message from the
    -- error generated in the outer TRY block.
    PRINT N'OUTER CATCH2: ' + ERROR_MESSAGE();
END CATCH; -- Outer CATCH block.
GO

Récupération d'informations à l'aide de la fonction @@ERROR

La fonction @@ERROR permet de capturer le numéro d'une erreur générée par l'instruction Transact-SQL précédente. Elle retourne les informations d'erreur juste après l'exécution de l'instruction Transact-SQL qui génère l'erreur.

  • Si l'instruction qui génère l'erreur se trouve dans un bloc TRY, la valeur @@ERROR doit être testée et récupérée dans la première instruction du bloc CATCH associé.

  • Si l'instruction qui génère l'erreur ne se trouve pas dans un bloc TRY, la valeur @@ERROR doit être testée et récupérée dans l'instruction qui suit cette instruction.

En dehors de l'étendue d'un bloc CATCH, le numéro d'erreur contenu dans @@ERROR est la seule information disponible sur une erreur dans le code Transact-SQL. Si l'erreur utilise un message d'erreur défini dans la table sys.messages, vous pouvez récupérer dans celle-ci le niveau de gravité spécifié et le texte du message d'erreur, comme l'illustre l'exemple ci-dessous.

IF EXISTS (SELECT message_id FROM sys.messages
    WHERE message_id = 50010)
        EXECUTE sp_dropmessage 50010;
GO
-- Define a message with text that accepts
-- a substitution string.
EXECUTE sp_addmessage @msgnum = 50010,
    @severity = 16, 
    @msgtext = N'Substitution string = %s.';
GO
DECLARE @ErrorVariable INT;
-- RAISERROR uses a different severity and
-- supplies a substitution argument.
RAISERROR (50010, -- Message id.
    15, -- Severity,
    1, -- State,
    N'ABC'); -- Substitution Value.
-- Save @@ERROR.
SET @ErrorVariable = @@ERROR;
-- The results of this select illustrate that
-- outside a CATCH block only the original
-- information from sys.messages is available to
-- Transact-SQL statements. The actual message
-- string returned to the application is not
-- available to Transact-SQL statements outside
-- of a CATCH block.
SELECT @ErrorVariable AS ErrorID,
    text
FROM sys.messages
WHERE message_id = @ErrorVariable;
GO