ProgramaciónDesarrollador de Bases de Datos

¿Cómo implementar procedimientos efectivos de manejo de errores y depuración en procedimientos almacenados SQL? ¿Qué mecanismos están previstos para capturar y registrar errores? ¿Difieren estos enfoques en diferentes SGBD?

Supere entrevistas con el asistente de IA Hintsage

Respuesta.

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:

  • No todos los errores son manejados por CATCH, por ejemplo, los errores de análisis o compilación abortarán la transacción antes de entrar en TRY.
  • Para registrar información, es importante tener una tabla separada para errores.
  • Se debe registrar tanto como sea posible: texto del error, número, nombre de usuario, parámetros de operación.
  • En diferentes SGBD la sintaxis y las capacidades difieren.

Pregunta capciosa.

¿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.