En los procedimientos almacenados, es posible y necesario manejar errores mediante construcciones especiales.
En SQL Server los principales mecanismos son los bloques TRY...CATCH, donde se capturan todos los errores dentro de TRY, y en CATCH se pueden registrar los detalles. Hay funciones como ERROR_NUMBER(), ERROR_MESSAGE() para obtener detalles.
BEGIN TRY -- Operación arriesgada UPDATE Accounts SET balance = balance - 100 WHERE id = 1; END TRY BEGIN CATCH INSERT INTO ErrorLog( ErrorTime, ErrorNumber, ErrorMessage, UserName ) VALUES ( GETDATE(), ERROR_NUMBER(), ERROR_MESSAGE(), SUSER_SNAME() ); -- Recuperación adicional o ROLLBACK END CATCH
En Oracle se utilizan más frecuentemente bloques EXCEPTION:
BEGIN UPDATE ...; EXCEPTION WHEN OTHERS THEN INSERT INTO error_log VALUES (..., SQLERRM); END;
Puntos a tener en cuenta:
¿Puede una excepción en el bloque CATCH llevar a la pérdida del contexto del error? ¿Cómo implementar un manejo de errores anidado?
Respuesta y ejemplo: Si ocurre un error en el bloque CATCH (por ejemplo, debido a la inaccesibilidad de la tabla ErrorLog), se pierde el contexto original del error, y la información sobre la causa de la falla puede perderse.
Para protegerse, encapsule el registro en un procedimiento separado con su propio TRY...CATCH, para siempre capturar "error en el manejador de errores".
BEGIN TRY -- código principal END TRY BEGIN CATCH EXEC LogError @Error = ERROR_MESSAGE(); END CATCH -- El procedimiento LogError contiene su propio TRY...CATCH
Historia
Proyecto: Informes financieros. En los procedimientos almacenados se añadieron bloques TRY...CATCH, pero no se registraron los parámetros que causaron el error. Como resultado, al capturar fallos críticos se tuvo que buscar manualmente la situación desde un respaldo; la causa raíz no era obvia.
Historia
Proyecto: Automatización del flujo de documentos (Oracle). En el bloque EXCEPTION se olvidó registrar el nombre de usuario. Después de una semana de investigación, se descubrió que alguien estaba intencionadamente "rompiendo" documentos; esto solo se supo a través de indicios indirectos en el registro de auditoría.
Historia
Proyecto: Comercio electrónico. El procedimiento al fallar escribía un error en ErrorLog. Un día, la tabla Log fue bloqueada por una transacción en expansión, y el intento de registro provocó un error anidado que sobrescribió la causa original y limpió la pila de errores. Se solucionó implementando una tabla adicional para fallas críticas y un registro multinivel.