Gestión de errores en Transact SQL

La gestión de errores, es un aspecto fundamental en el manejo de código Transact SQL, que nos permite controlar nuestro flujo de código y detectar problemas y errores que nos facilitan su resolución o información.

A través del manejo de excepciones, podemos tener un control total sobre nuestra aplicación y detectar las casuísticas que provocan interrupciones en nuestro código.

Existen estructuras de control de flujo especialmente diseñadas para la gestión de errores. En esta sección nos centraremos en el TRY...CATCH y el THROW.

TRY…CATCH

TRY…CATCH es una estructura de control de flujo que nos permite detectar y atrapar errores. El funcionamiento esencial es simple:

  • TRY: Encierra una serie de instrucciones Transact SQL que intentarán ejecutarse.

  • CATCH: Recoge cualquier error que se produzca en el TRY, ejecutándose las sentencias propias de este bloque CATCH, que generalmente estarán destinadas a proporcionar información acerca del error producido.

En definitiva, si todo va bien, el código perteneciente a la cláusula CATCH no se ejecuta. Sin embargo, si durante la ejecución del TRY se produce algún error, el código saltará al CATCH para atraparlo y tratarlo.

En cuanto a la sintaxis, es la siguiente:

BEGIN TRY
     [codigo]
END TRY
BEGIN CATCH
    [codigo]
END CATCH

Existen algunas consideraciones ha tener en cuenta acerca del TRY...CATCH:

  • Puede utilizarse dentro de procedimientos almacenados.

  • Las sentencias TRY...CATCH pueden anidarse.

  • TRY debe ir siempre acompañado inmediatamente después de su bloque CATCH correspondiente. Cualquier instrucción entre END TRY y BEGIN CATCH, causará un error sintáctico.

  • No permite englobar varios lotes. Por ejemplo, no podrá contener más de un bloque BEGIN...END ni construcciones IF...ELSE.

Funciones ERROR

Existen una serie de funciones encargadas de devolver información acerca de los errores producidos, muy utilizadas a menudo dentro del bloque CATCH.

  • ERROR_NUMBER(): devuelve el número del error.

  • ERROR_SEVERITY(): devuelve la gravedad del error.

  • ERROR_STATE(): devuelve el número de estado de error.

  • ERROR_PROCEDURE(): devuelve el nombre del procedimiento almacenado o disparador donde ocurrió el error.

  • ERROR_LINE(): devuelve el número de línea dentro de la rutina que provocó el error.

  • ERROR_MESSAGE(): devuelve el texto completo del mensaje de error.

Ejemplo

Para ejemplificar el funcionamiento de TRY...CATCH de manera sencilla, procedemos a intentar dividir un número entre cero dentro de un bloque TRY...CATCH para capturar y devolver información del error:

BEGIN TRY
    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
ErrorNumber ErrorSeverity ErrorState ErrorProcedure ErrorLine ErrorMessage
8134 16 1 NULL 2 Error de división entre cero.

THROW

THROW nos permite generar nuestras propias excepciones y devolverlas en el bloque CATCH de una construcción TRY...CATCH. De esta manera, podremos manejar una gestión de errores personalizada.

La sintaxis es la siguiente:

THROW  (error_number | variable,
        message | variable ,
        state | variable )

Argumentos THROW

Como vemos en su sintaxis, la instrucción THROW utiliza tres argumentos importantes en su declaración:

  1. error_number: Indica el número del error. Será de tipo de dato INT y su valor deberá estar comprendido entre 50000 y 2147483647 (ambos incluidos)

  2. message: devuelve el texto completo del mensaje de error que especifiquemos

  3. state: devuelve el número de estado de error. Será de tipo TINYINT con un valor comprendido entre 0 y 255 (ambos incluidos)

Ejemplo

Para ejemplificar el funcionamiento de THROW de manera sencilla, procedemos a intentar dividir un número entre cero dentro de un bloque TRY...CATCH para capturar y devolver la información personalizada del error generado:

BEGIN TRY
    SELECT 1/0;
END TRY
BEGIN CATCH
    THROW 50100, 'La operación matemática es errónea.',1;
END CATCH;
GO

Msg 50100, Level 16, State 1, Line 5 La operación matemática es errónea.