Anda di halaman 1dari 4

CONTROL DE ERRORES EN SQL SERVER SQL Server incorpora diferentes alternativas de Control de Errores para el desarrollo y programacin en Transact-SQL

Utilizar SET XACT_ABORT para programar Transacciones Resulta muy cmodo utilizar la opcin XACT_ABORT para la programacin de transacciones. Al activar esta opcin (SET XACT_ABORT ON), si se produce un error en tiempo de ejecucin, SQL Server deshar completamente todas las transacciones abiertas. Esto simplifica enormemente la programacin de transacciones, y adems, est disponible desde SQL Server 2000 (toma ya ;-), y as evitamos tener que hacer la tediosa tarea de comprobar el valor de @@ERROR despus de cada sentencia para poder deshacer la transaccin correctamente, y que en caso de errores no se confirmen resultados parciales. Sin activar XACT_ABORT, que es el comportamiento por defecto de SQL Server (SET XACT_ABORT OFF), sera necesario comprobar @@ERROR sucesivas veces (ojo, que estoy descartando el uso de TRY/CATCH para ahora, y que veremos despus), como en el siguiente ejemplo: BEGIN TRAN INSERT INTO tbl VALUES (1) IF @@ERROR<>0 GOTO TrataError INSERT INTO tbl VALUES (1) -- Violacin de Clave IF @@ERROR<>0 GOTO TrataError INSERT INTO tbl VALUES (3) IF @@ERROR<>0 GOTO TrataError COMMIT TRAN RETURN TrataError: ROLLBACK TRAN RETURN; Sin embargo, utilizando XACT_ABORT activado resulta mucho ms sencillo, teniendo la garanta de que se confirmar o deshar la transaccin por completo sin necesidad de programar las comprobaciones de la funcin del sistema @@ERROR: SET XACT_ABORT ON BEGIN TRAN INSERT INTO tbl VALUES (1) INSERT INTO tbl VALUES (1) -- Violacin de Clave INSERT INTO tbl VALUES (3) COMMIT TRAN RETURN El principal caso de uso de XACT_ABORT es el ejemplo anterior, para el manejo de transacciones, eso s, cuando NO es necesario realizar una gestin ms completa de los errores,

ya que si se desea programar un Control de Errores ms complejo (ej: registrar el error producido, imprimir - print - mensajes personalizados para cada error, etc.), al menos hasta SQL Server 2000 es necesario sufrir del uso de la funcin de sistema @@ERROR (claro, que desde SQL Server 2005, podemos utilizar TRY/CATCH). Utilizar TRY/CATCH para programar el Control de Errores La gestin de errores a travs de bloques TRY/CATCH est disponible desde SQL Server 2005, simplificndose enormemente la gestin de errores en cdigo Transact-SQL (como en el caso de la programacin de procedimientos almacenados). Cualquier error que se produzca dentro del bloque TRY provocar que se salte a la ejecucin del bloque CATCH sin enviar ningn error al cliente, mientras, que cualquier error que se produzca dentro del bloque CATCH SI se enviar al cliente (excepto que anidemos estructuras TRY/CATCH). As, la ejecucin de sentencias RAISERROR dentro de bloques TRY fuerza que se salte la ejecucin al correspondiente bloque CATCH. BEGIN TRY BEGIN TRAN INSERT INTO tbl VALUES (1) INSERT INTO tbl VALUES (1) -- Violacin de Clave INSERT INTO tbl VALUES (3) COMMIT TRAN END TRY BEGIN CATCH ROLLBACK TRAN RAISERROR('Se ha producido un error.', 16, 1); END CATCH De ste modo, dentro del bloque CATCH podemos hacer uso de nuevas funciones del sistema para registrar el error producido o lanzar el error (RAISERROR) a la aplicacin cliente. En particular, podemos utilizar las siguientes funciones: ERROR_NUMBER(). ERROR_MESSAGE(). ERROR_SEVERITY(). ERROR_STATE(). ERROR_PROCEDURE(). ERROR_LINE()

Un problema de la utilizacin de RAISERROR, es que no es posible lanzar (o re-lanzar) un error del sistema desde el bloque CATCH. Esto es, si se produce un error dentro de nuestro bloque TRY, la ejecucin se pasar al bloque CATCH, sin embargo, NO es posible desde el bloque CATCH re-lanzar el error original (ya que este intento, provocar un nuevo error ;-), por lo cual, como mucho podremos lanzar un error personalizado, he incluir en el texto del error la informacin que deseemos (es una apa, pero puede servir, no?). La parte negativa (perdn... menos positiva) de la utilizacin de bloques TRY/CATH en cdigo Transact-SQL de SQL Server 2005, es que no ofrece toda la potencia que sus equivalentes de lenguajes de programacin como C#, como por ejemplo: slo es posible especificar un nico bloque CATCH, no existe el bloque FINALLY, y no es posible relanzar el error original desde el

bloque CATCH. Tambin es importante recordar que si est activa la opcin XACT_ABORT (es decir, SET XACT_ABORT ON) no ser posible confirmar una transaccin desde el bloque CATCH, evidentemente. Ante la duda, es posible consultar el valor actual de la funcin XACT_STATE(), y en funcin del mismo, poder tomar una u otra medida. Errores definidos por el usuario (sp_addmessage) Es posible definir errores de usuario con el fin de poder reutilizarlos, y as ofrecer un comportamiento homogneo. Esto puede realizarse a travs del procedimiento almacenado del sistema sp_addmessage (especificando cdigo de error, severidad, texto del error, e idioma), y pueden consultarse los errores existentes en sys.messages (los errores de usuario se almacenan en MSDB). Los errores de usuario deben tener un cdigo de error superior al 50000. Una ventaja de la utilizacin de errores de usuario, es que es posible utilizar parmetros, de tal modo que el texto del error pueda variar en funcin de los parmetros del error. Otra ventaja, relacionada con la anterior, es el soporte multi-idioma, el cual no slo permite especificar el mismo error en distintos idiomas, sino que adems se puede especificar los parmetros en el orden deseado que se desea que aparezca en el texto del error (se debe tener en cuenta, que por las peculiaridades sintcticas de los distintos idiomas, los parmetros en el texto de error pueden no aparecer en el mismo orden para todos los idiomas). Otra situacin tpica es la necesidad de registrar mensajes en el Visor de Sucesos de Windows, para lo cual, tenemos varias alternativas: Aadir el parmetro @with_log=true al crear el mensaje de usuario con sp_addmessage. Aadir la opcin WITH LOG al final de las sentencias RAISERROR. Ejecutar el procedimiento almacenado xp_logevent, el cual, no enva ningn mensaje al cliente, tan slo se limita a escribir el mensaje en el Visor de Sucesos de Aplicacin.

ejemplos alterados o intentos de alterarlos por mi en este ejemplo se hace una division sobre cero lo cual logicamente dara error y dentro de la sentencia catch se muestran los parametros de error preestablecidos por sql BEGIN TRY SELECT 5/0 END TRY BEGIN CATCH SELECT ERROR_NUMBER() AS Numero_de_Error, ERROR_SEVERITY() AS Gravedad_del_Error, ERROR_STATE() AS Estado_del_Error, ERROR_PROCEDURE() AS Procedimiento_del_Error, ERROR_LINE() AS Linea_de_Error, ERROR_MESSAGE() AS Mensaje_de_Error; END CATCH en este ejemplo se inserta una clave repetida y al no poder insertar dicha clave da un rollback y deshace toda accion

BEGIN TRY BEGIN TRAN INSERT INTO Area VALUES (8,'a') INSERT INTO Area VALUES (8,'b') -- Violacin de Clave INSERT INTO Area VALUES (9,'c') COMMIT TRAN END TRY BEGIN CATCH ROLLBACK TRAN RAISERROR('Se ha producido un error al insertar ids repatidos.', 16, 1); END CATCH

el siguiente ejemplo es de una insercion con llave repetida en lo personal lo probe en server 2005 pero creo que solo funciona en sql server 2000 XACT_STATE() SET XACT_ABORT ON SET XACT_ABORT OFF BEGIN TRAN INSERT INTO Area VALUES (8,'a') IF @@ERROR<>0 GOTO TrataError INSERT INTO Area VALUES (8,'b') -- Violacin de Clave IF @@ERROR<>0 GOTO TrataError INSERT INTO Area VALUES (9,'c') IF @@ERROR<>0 GOTO TrataError COMMIT TRAN RETURN TrataError: ROLLBACK TRAN RETURN;

BEGIN TRAN INSERT INTO Area VALUES (8,'a') INSERT INTO Area VALUES (8,'b') -- Violacin de Clave INSERT INTO Area VALUES (9,'c') COMMIT TRAN RETURN