Recuperar información de errores en Transact-SQL

Hay dos formas de obtener información de errores en Transact-SQL:

  • En el ámbito del bloque CATCH de una construcción TRY…CATCH se pueden utilizar las siguientes funciones del sistema:

    • ERROR_LINE() devuelve el número de línea en que se produjo el error.

    • ERROR_MESSAGE() devuelve el texto del mensaje que se devolvería a la aplicación. Este texto incluye los valores suministrados para los parámetros reemplazables, como longitudes, nombres de objetos u horas.

    • ERROR_NUMBER() devuelve el número de error.

    • ERROR_PROCEDURE() devuelve el nombre del procedimiento almacenado o desencadenador en que se produjo el error. Esta función devuelve NULL si el error no se ha producido en un procedimiento almacenado o un desencadenador.

    • ERROR_SEVERITY() devuelve la gravedad.

    • ERROR_STATE() devuelve el estado.

  • Inmediatamente después de ejecutar una instrucción de Transact-SQL, puede hacer una prueba para detectar errores y recuperar el número de error mediante la función @@ERROR.

Usar ERROR_LINE, ERROR_MESSAGE, ERROR_NUMBER, ERROR_PROCEDURE, ERROR_SEVERITY y ERROR_STATE

Las funciones ERROR_LINE, ERROR_MESSAGE, ERROR_NUMBER, ERROR_PROCEDURE, ERROR_SEVERITY y ERROR_STATE sólo devuelven información de errores cuando se utilizan en el ámbito del bloque CATCH de una construcción TRY…CATCH. Fuera del ámbito de un bloque CATCH devuelven NULL. Estas funciones devuelven información acerca del error que provocó la invocación del bloque CATCH. Las funciones devuelven la misma información de error en cualquier parte en que se ejecuten dentro del ámbito de un bloque CATCH, aunque se haga referencia a ellas varias veces. Estas funciones proporcionan a las instrucciones de Transact-SQL los mismos datos que se devuelven a la aplicación.

En bloques CATCH anidados, las funciones ERROR_LINE, ERROR_MESSAGE, ERROR_NUMBER, ERROR_PROCEDURE, ERROR_SEVERITY y ERROR_STATE devuelven la información de error específica para el bloque CATCH en el que se haga referencia a ellas. Por ejemplo, el bloque CATCH de una construcción TRY...CATCH externa podría tener una construcción TRY...CATCH anidada. Dentro del bloque CATCH anidado, estas funciones devuelven información acerca del error que invocó el bloque CATCH interno. Las mismas funciones en el bloque CATCH externo devolverían información acerca del error que invocó dicho bloque CATCH.

En el ejemplo siguiente se ilustra esto mostrando que cuando se hace referencia a ERROR_MESSAGE en el bloque CATCH externo, la función devuelve el texto del mensaje generado en el bloque TRY externo. Cuando se hace referencia en el bloque CATCH interno, ERROR_MESSAGE devuelve el texto de mensaje generado en el bloque TRY interno. Este ejemplo también muestra que en el bloque CATCH externo, ERROR_MESSAGE siempre devuelve el mensaje generado en el bloque TRY externo, incluso después de ejecutar la construcción TRY...CATCH interna.

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

Recuperar información mediante @@ERROR

La función @@ERROR se puede utilizar para capturar el número de un error generado con la instrucción anterior de Transact-SQL. @@ERROR sólo devuelve información de error inmediatamente después de la instrucción de Transact-SQL que genera el error.

  • Si la instrucción que genera el error se encuentra en un bloque TRY, el valor de @@ERROR debe probarse y recuperarse en la primera instrucción del bloque CATCH asociado.

  • Si la instrucción que genera el error no se encuentra en un bloque TRY, el valor de @@ERROR debe probarse y recuperarse en la instrucción inmediatamente después de aquélla que genera el error.

Fuera del ámbito de un bloque CATCH, el número de error de @@ERROR es la única información disponible acerca de un error dentro del código de Transact-SQL. Si el error utilizó un mensaje de error definido en sys.messages, se puede recuperar la gravedad definida y el texto del mensaje de error de sys.messages, tal como se muestra en este ejemplo.

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