Implementación del control estructurado de excepciones
Ahora que comprende la naturaleza de los errores y el control básico de errores en T-SQL, es el momento de examinar una forma más avanzada de control de errores. El control de excepciones estructurado se introdujo en SQL Server 2005.
Aquí, verá cómo usarlo y evaluar sus ventajas y limitaciones, incluido el bloque TRY CATCH, el rol de las funciones de control de errores y comprender la diferencia entre los errores detectables y no capturables. Por último, verá cómo se pueden administrar y mostrar los errores cuando sea necesario.
¿Qué es la programación de bloques TRY/CATCH?
El control estructurado de excepciones es más eficaz que el control de errores basado en la variable del sistema @@ERROR. Permite evitar que el código esté lleno con código de control de errores y centralizar ese código de control de errores. La centralización del código de control de errores también significa que puede centrarse más en el propósito del código en lugar del control de errores que contiene.
Bloque TRY y bloque CATCH
Al usar el control de excepciones estructurados, el código que podría generar un error se coloca dentro de un bloque TRY. Los bloques TRY se incluyen entre BEGIN TRY y END TRY.
Si se produce un error detectable: la mayoría de los errores se pueden detectar, el control de ejecución se mueve al bloque CATCH. El bloque CATCH es una serie de instrucciones T-SQL incluidas en instrucciones BEGIN CATCH y END CATCH .
Nota:
Aunque "BEGIN CATCH" y "END TRY" son instrucciones independientes, "BEGIN CATCH" debe seguir inmediatamente a "END TRY".
Limitaciones actuales
Los lenguajes de alto nivel suelen ofrecer una construcción try/catch/finally y a menudo se usan para liberar recursos implícitamente. No hay ningún bloque FINALLY equivalente en T-SQL.
Comprender la diferencia entre los errores detectables y no detectables
Es importante tener en cuenta que, mientras que los bloques TRY/CATCH le permiten detectar una gama mucho más amplia de errores de lo que podría con @@ERROR, no puede detectar todos los tipos.
Errores capturables frente a no capturables
No todos los errores se pueden detectar mediante bloques TRY/CATCH dentro del mismo ámbito en el que existe el bloque TRY/CATCH. A menudo, los errores que no se pueden detectar en el mismo ámbito se pueden detectar en un ámbito circundante. Por ejemplo, es posible que no pueda detectar un error dentro del procedimiento almacenado que contiene el bloque TRY/CATCH. Sin embargo, es probable que pueda detectarlo en un bloque TRY/CATCH en el código que llamó al procedimiento almacenado donde se produjo el error.
Errores comunes que no se pueden detectar
Los ejemplos comunes de errores que no se pueden detectar son:
- Errores de compilación, como errores de sintaxis, que impidan que un lote se compile.
- Problemas de recompilación de nivel de instrucción que suelen estar relacionados con la resolución de nombres diferida. Por ejemplo, podría crear un procedimiento almacenado que haga referencia a una tabla desconocida. Solo se produce un error cuando el procedimiento intenta resolver el nombre de la tabla en un objectid.
Cómo volver a producir errores mediante THROW
Si la instrucción THROW se usa en un bloque CATCH sin parámetros, volverá a generar el error que provocó que el código entrara en el bloque CATCH. Puede usar esta técnica para implementar el registro de errores en la base de datos capturando errores y registrando sus detalles, y a continuación lanzando el error original a la aplicación cliente, para que pueda ser gestionado allí.
Este es un ejemplo de cómo volver a producir un error.
BEGIN TRY
-- code to be executed
END TRY
BEGIN CATCH
PRINT ERROR_MESSAGE();
THROW
END CATCH
En algunas versiones anteriores de SQL Server, no había ningún método para producir un error del sistema. Aunque THROW no puede especificar que se genere un error del sistema, cuando este bloque se usa sin parámetros en un bloque CATCH, se volverán a producir los errores del sistema y del usuario.
¿Qué son las funciones de control de errores?
Los bloques CATCH hacen que la información relacionada con errores esté disponible durante toda la duración del bloque CATCH. Esto incluye los subámbitos, como los procedimientos almacenados, que se ejecutan desde el bloque CATCH.
Funciones de control de errores
Debe recordar que, al programar con @@ERROR, el valor mantenido por la variable del sistema @@ERROR se restablece en cuanto se ejecutó la siguiente instrucción.
Otra ventaja clave del control de excepciones estructurado en T-SQL es que se ha proporcionado una serie de funciones de control de errores y que mantienen sus valores a lo largo del bloque CATCH. Distintas funciones proporcionan cada una de las propiedades de los errores que se han generado.
Esto significa que puede escribir procedimientos almacenados genéricos de control de errores que todavía pueden acceder a la información relacionada con errores.
- Los bloques CATCH hacen que la información relacionada con errores esté disponible durante toda la duración del bloque CATCH.
- @@Error se restablece cuando se ejecuta la siguiente instrucción.
Administración de errores en el código
La integración clR de SQL permite la ejecución de código administrado en SQL Server. Los lenguajes de .NET de alto nivel, como C# y VB, tienen un control detallado de excepciones disponible para ellos. Los errores se pueden detectar mediante bloques estándar try/catch/finally de .NET.
Errores en código administrado
En general, es posible que quiera detectar errores en el código administrado tanto como sea posible. Sin embargo, es importante darse cuenta de que los errores que no se gestionan en el código administrado se devuelven al código T-SQL que realiza la llamada. Siempre que se devuelva cualquier error que se produzca en el código administrado a SQL Server, aparecerá un error 6522. Los errores se pueden anidar y ese error concreto encerrará la causa real del error.
Otra causa poco frecuente pero posible de errores en el código administrado sería que el código podría ejecutar una instrucción RAISERROR T-SQL a través de un objeto SqlCommand.