TRY/CATCH en SQL 2005

viernes, 9 de marzo de 2007

Microsoft SQL Server 2005 trae incorporada una nueva forma de manejo de errores. Las versiones anteriores solo permitían el detectar errores con la función @@Error, que permite hacer un reporte del error pero no hacer un manejo, solamente muestra la información y la excepción se manda al que llamó al Stored Procedure y es él quien decide qué hacer.
Otra desventaja del @@Error es que el empleo apropiado de esta función requiere hacer una comprobación después de cada declaración, de otra manera el valor de la variable se resetea.
Por ejemplo:

SELECT 1/0
IF @@ERROR <> 0
BEGIN
SELECT @@ERROR
END
-----------
Msg 8134, Level 16, State 1, Line 1Divide by
zero error encountered.
-----------
0
(1 row(s) affected)

La función @@Error devuelve 0 en el select, y no el número de error, porque el IF no dio un error.

En SQL Server 2005 las excepciones se pueden manejar desde el SP con la nueva función TRY/CATCH, que emula el manejo de errores derivado del lenguaje C. Se escribe el código dentro del bloque TRY y si lanza una excepción la recibe el bloque CATCH, de esta forma el error puede manejarse dentro del SP sin necesidad de mandar una excepción al que lo llama.
Esta función también ayuda a mejorar el código de las transacciones ya que no hay que escribir la validación del @@Error después de cada declaración sino que desde el momento en que empieza la transacción se hace un TRY y en el CATCH se hace el rollback.

Microsoft SQL 2005 también tiene otras funciones que facilitan el reporte de errores que son ERROR_MESSAGE(), ERROR_NUMBER(), ERROR_LINE(), ERROR_SEVERITY(), ERROR_STATE() y ERROR_PROCEDURE(). Estas funciones a diferencia del @@Error no se resetean.

Un ejemplo simple del uso del TRY/CATCH con las funciones de ERROR sería crear un Store Procedure con el siguiente código:
CREATE Procedure PruebaTryCatch
(
@Dividendo int,
@Divisor int
)
as
BEGIN TRY
SELECT @Dividendo/@Divisor
END TRY
BEGIN CATCH
SELECT
ERROR_MESSAGE() as Mensaje,
ERROR_NUMBER() as Numero,
ERROR_LINE() as Linea,
ERROR_SEVERITY() as Severidad,,
ERROR_STATE() as Estado,
ERROR_PROCEDURE() as Proceso
END CATCH
Si lo ejecuta con el número 1 como dividendo y el 0 como divisor:
EXECUTE PruebaTryCatch 1, 0
El resultado será:

Mensaje                          Numero Linea
-------------------------------------------------------
Divide by zero error encountered. 8134 11

Severidad Estado Proceso
------------------------
16 1 PruebaTryCatch