TRY...CATCH (Transact-SQL)
Actualizado: 14 de abril de 2006
Implementa un mecanismo de control de errores para Transact-SQL que es similar al control de excepciones en los lenguajes Microsoft Visual C# y Microsoft Visual C++. Se puede incluir un grupo de instrucciones Transact-SQL en un bloque TRY. Si se produce un error en el bloque TRY, el control se transfiere a otro grupo de instrucciones que está incluido en un bloque CATCH.
Sintaxis
BEGIN TRY
{ sql_statement | statement_block }
END TRY
BEGIN CATCH
[ { sql_statement | statement_block } ]
END CATCH
[ ; ]
Argumentos
- sql_statement
Es cualquier instrucción Transact-SQL.
- statement_block
Grupo de instrucciones Transact-SQL incluidas en un lote o en un bloque BEGIN…END.
Notas
Una construcción TRY...CATCH detecta todos los errores de ejecución que tienen una gravedad mayor de 10 y que no cierran la conexión de la base de datos.
Un bloque TRY debe ir seguido inmediatamente por un bloque CATCH asociado. Si se incluye cualquier otra instrucción entre las instrucciones END TRY y BEGIN CATCH se genera un error de sintaxis.
Una construcción TRY…CATCH no puede abarcar varios lotes. Una construcción TRY…CATCH no puede abarcar varios bloques de instrucciones Transact-SQL. Por ejemplo, una construcción TRY…CATCH no puede abarcar dos bloques BEGIN…END de instrucciones Transact-SQL y no puede abarcar una construcción IF…ELSE.
Si no hay errores en el código incluido en un bloque TRY, cuando la última instrucción de este bloque ha terminado de ejecutarse, el control se transfiere a la instrucción inmediatamente posterior a la instrucción END CATCH asociada. Si hay un error en el código incluido en un bloque TRY, el control se transfiere a la primera instrucción del bloque CATCH asociado. Si la instrucción END CATCH es la última instrucción de un procedimiento almacenado o desencadenador, el control se devuelve a la instrucción que llamó al procedimiento almacenado o activó el desencadenador.
Cuando finaliza el código del bloque CATCH, el control se transfiere a la instrucción inmediatamente posterior a la instrucción END CATCH. Los errores capturados por un bloque CATCH no se devuelven a la aplicación que realiza la llamada. Si es necesario devolver cualquier parte de la información sobre el error a la aplicación, debe hacerlo el código del bloque CATCH a través de mecanismos como los conjuntos de resultados SELECT o las instrucciones RAISERROR y PRINT. Para obtener más información acerca de cómo utilizar RAISERROR con TRY…CATCH, vea Usar TRY...CATCH en Transact-SQL.
Las construcciones TRY…CATCH pueden estar anidadas. Un bloque TRY o un bloque CATCH puede contener construcciones TRY…CATCH anidadas. Por ejemplo, un bloque CATCH puede contener una construcción TRY…CATCH incrustada para controlar los errores detectados por el código de CATCH.
Los errores que se encuentren en un bloque CATCH se tratan como los errores generados en otros lugares. Si el bloque CATCH contiene una construcción TRY…CATCH anidada, los errores del bloque TRY anidado transferirán el control al bloque CATCH anidado. Si no hay ninguna construcción TRY…CATCH anidada, el error se devuelve al autor de la llamada.
Las construcciones TRY…CATCH capturan los errores no controlados de los procedimientos almacenados o desencadenadores ejecutados por el código del bloque TRY. Alternativamente, los procedimientos almacenados o desencadenadores pueden contener sus propias construcciones TRY…CATCH para controlar los errores generados por su código. Por ejemplo, cuando un bloque TRY ejecuta un procedimiento almacenado y se produce un error en éste, el error se puede controlar de las formas siguientes:
- Si el procedimiento almacenado no contiene su propia construcción TRY…CATCH, el error devuelve el control al bloque CATCH asociado al bloque TRY que contiene la instrucción EXECUTE.
- Si el procedimiento almacenado contiene una construcción TRY…CATCH, el error transfiere el control al bloque CATCH del procedimiento almacenado. Cuando finaliza el código del bloque CATCH, el control se devuelve a la instrucción inmediatamente posterior a la instrucción EXECUTE que llamó al procedimiento almacenado.
No se pueden utilizar instrucciones GOTO para entrar en un bloque TRY o CATCH. Estas instrucciones se pueden utilizar para saltar a una etiqueta dentro del mismo bloque TRY o CATCH, o bien para salir de un bloque TRY o CATCH.
La construcción TRY…CATCH no se puede utilizar en una función definida por el usuario.
Recuperar información sobre errores
En el ámbito de un bloque CATCH, se pueden utilizar las siguientes funciones del sistema para obtener información acerca del error que provocó la ejecución del bloque CATCH:
- ERROR_NUMBER() devuelve el número del error.
- ERROR_SEVERITY() devuelve la gravedad.
- ERROR_STATE() devuelve el número de estado del error.
- ERROR_PROCEDURE() devuelve el nombre del procedimiento almacenado o desencadenador donde se produjo el error.
- ERROR_LINE() devuelve el número de línea de la rutina que provocó el error.
- ERROR_MESSAGE() devuelve el texto completo del mensaje de error. Este texto incluye los valores suministrados para los parámetros reemplazables, como longitudes, nombres de objetos u horas.
Estas funciones devuelven NULL si se las llama desde fuera del ámbito del bloque CATCH. Con ellas se puede recuperar información sobre los errores desde cualquier lugar dentro del ámbito del bloque CATCH. Por ejemplo, en la siguiente secuencia de comandos se muestra un procedimiento almacenado que contiene funciones de control de errores. Se llama al procedimiento almacenado en el bloque CATCH
de una construcción TRY…CATCH
y se devuelve información sobre el error.
USE AdventureWorks;
GO
-- Verify that the stored procedure does not already exist.
IF OBJECT_ID ( 'usp_GetErrorInfo', 'P' ) IS NOT NULL
DROP PROCEDURE usp_GetErrorInfo;
GO
-- Create procedure to retrieve error information.
CREATE PROCEDURE usp_GetErrorInfo
AS
SELECT
ERROR_NUMBER() AS ErrorNumber,
ERROR_SEVERITY() AS ErrorSeverity,
ERROR_STATE() AS ErrorState,
ERROR_PROCEDURE() AS ErrorProcedure,
ERROR_LINE() AS ErrorLine,
ERROR_MESSAGE() AS ErrorMessage;
GO
BEGIN TRY
-- Generate divide-by-zero error.
SELECT 1/0;
END TRY
BEGIN CATCH
-- Execute error retrieval routine.
EXECUTE usp_GetErrorInfo;
END CATCH;
Errores no afectados por una construcción TRY…CATCH
Las construcciones TRY…CATCH no detectan lo siguiente:
- Advertencias o mensajes informativos que tienen la gravedad 10 o inferior.
- Errores que tienen la gravedad 20 o superior que detienen el procesamiento de las tareas de SQL Server Database Engine (Motor de base de datos de SQL Server) en la sesión. Si se produce un error con una gravedad 20 o superior y no se interrumpe la conexión con la base de datos, TRY…CATCH controlará el error.
- Atenciones, como solicitudes de interrupción de clientes o conexiones de cliente interrumpidas.
- Cuando el administrador del sistema finaliza la sesión mediante la instrucción KILL.
Un bloque CATCH no controla los siguientes tipos de errores cuando se producen en el mismo nivel de ejecución que la construcción TRY…CATCH:
- Errores de compilación, como errores de sintaxis, que impiden la ejecución de un lote.
- Errores que se producen durante la recompilación de instrucciones, como errores de resolución de nombres de objeto que se producen después de la compilación debido a una resolución de nombres diferida.
Estos errores se devuelven al nivel de ejecución del lote, procedimiento almacenado o desencadenador.
Si se produce un error durante la compilación o la recompilación de nivel de instrucción en un nivel de ejecución inferior (por ejemplo, al ejecutar sp_executesql o un procedimiento almacenado definido por el usuario) dentro del bloque TRY, el error se producirá en un nivel inferior a la construcción TRY…CATCH y lo controlará el bloque CATCH asociado. Para obtener más información, vea Usar TRY...CATCH en Transact-SQL.
En el ejemplo siguiente se muestra cómo la construcción TRY…CATCH
no captura un error de resolución de nombre de objeto generado por una instrucción SELECT
, sino que es el bloque CATCH
el que lo captura cuando la misma instrucción SELECT
se ejecuta dentro de un procedimiento almacenado.
USE AdventureWorks;
GO
BEGIN TRY
-- Table does not exist; object name resolution
-- error not caught.
SELECT * FROM NonexistentTable;
END TRY
BEGIN CATCH
SELECT
ERROR_NUMBER() as ErrorNumber,
ERROR_MESSAGE() as ErrorMessage;
END CATCH
El error no se captura y el control se transfiere fuera de la construcción TRY…CATCH
, al siguiente nivel superior.
Al ejecutar la instrucción SELECT
dentro de un procedimiento almacenado, el error se produce en un nivel inferior al bloque TRY
. La construcción TRY…CATCH
controlará el error.
-- Verify that the stored procedure does not exist.
IF OBJECT_ID ( N'usp_ExampleProc', N'P' ) IS NOT NULL
DROP PROCEDURE usp_ExampleProc;
GO
-- Create a stored procedure that will cause an
-- object resolution error.
CREATE PROCEDURE usp_ExampleProc
AS
SELECT * FROM NonexistentTable;
GO
BEGIN TRY
EXECUTE usp_ExampleProc
END TRY
BEGIN CATCH
SELECT
ERROR_NUMBER() as ErrorNumber,
ERROR_MESSAGE() as ErrorMessage;
END CATCH;
- Para obtener más información acerca de los lotes, vea Lotes.
Transacciones que no pueden confirmarse y XACT_STATE
Si un error generado en un bloque TRY hace que se invalide el estado de la transacción actual, la transacción se clasifica como una transacción que no puede confirmarse. Un error que normalmente termina una transacción fuera de un bloque TRY hace que la transacción no pueda confirmarse cuando se produce dentro de un bloque TRY. Una transacción que no puede confirmarse sólo puede realizar operaciones de lectura o ROLLBACK TRANSACTION. La transacción no puede ejecutar ninguna instrucción Transact-SQL que genere una operación de escritura o COMMIT TRANSACTION. La función XACT_STATE devuelve el valor -1 si una transacción se ha clasificado como transacción que no puede confirmarse. Cuando finaliza el lote, Database Engine (Motor de base de datos) revierte todas las transacciones activas que no se pueden confirmar. Si no se ha enviado ningún mensaje de error cuando la transacción pasó al estado en el que no se puede confirmar, cuando el lote termine, se enviará un mensaje de error a la aplicación cliente. Esto indica que se ha detectado y revertido una transacción que no se puede confirmar.
Para obtener más información acerca de las transacciones que no pueden confirmarse y la función XACT_STATE, vea Usar TRY...CATCH en Transact-SQL y XACT_STATE (Transact-SQL).
Ejemplos
A. Usar TRY…CATCH
En el siguiente ejemplo se muestra una instrucción SELECT
que generará un error de división por cero. El error hace que la ejecución salte al bloque CATCH
asociado.
USE AdventureWorks;
GO
BEGIN TRY
-- Generate a divide-by-zero error.
SELECT 1/0;
END TRY
BEGIN CATCH
SELECT
ERROR_NUMBER() AS ErrorNumber,
ERROR_SEVERITY() AS ErrorSeverity,
ERROR_STATE() AS ErrorState,
ERROR_PROCEDURE() AS ErrorProcedure,
ERROR_LINE() AS ErrorLine,
ERROR_MESSAGE() AS ErrorMessage;
END CATCH;
GO
B. Usar TRY…CATCH en una transacción
En este ejemplo se muestra cómo funciona un bloque TRY…CATCH
dentro de una transacción. La instrucción del bloque TRY
genera un error por infracción de restricción.
USE AdventureWorks;
GO
BEGIN TRANSACTION;
BEGIN TRY
-- Generate a constraint violation error.
DELETE FROM Production.Product
WHERE ProductID = 980;
END TRY
BEGIN CATCH
SELECT
ERROR_NUMBER() AS ErrorNumber,
ERROR_SEVERITY() AS ErrorSeverity,
ERROR_STATE() as ErrorState,
ERROR_PROCEDURE() as ErrorProcedure,
ERROR_LINE() as ErrorLine,
ERROR_MESSAGE() as ErrorMessage;
IF @@TRANCOUNT > 0
ROLLBACK TRANSACTION;
END CATCH;
IF @@TRANCOUNT > 0
COMMIT TRANSACTION;
GO
C. Usar TRY…CATCH con XACT_STATE
En este ejemplo se muestra cómo utilizar la construcción TRY…CATCH
para controlar los errores que se producen en una transacción. La función XACT_STATE
determina si la transacción debe confirmarse o revertirse. En este ejemplo SET XACT_ABORT
es ON
. Esto hace que la transacción no pueda confirmarse cuando se produce el error por infracción de restricción.
USE AdventureWorks;
GO
-- Check to see whether this stored procedure exists.
IF OBJECT_ID (N'usp_GetErrorInfo', N'P') IS NOT NULL
DROP PROCEDURE usp_GetErrorInfo;
GO
-- Create procedure to retrieve error information.
CREATE PROCEDURE usp_GetErrorInfo
AS
SELECT
ERROR_NUMBER() AS ErrorNumber,
ERROR_SEVERITY() AS ErrorSeverity,
ERROR_STATE() as ErrorState,
ERROR_LINE () as ErrorLine,
ERROR_PROCEDURE() as ErrorProcedure,
ERROR_MESSAGE() as ErrorMessage;
GO
-- SET XACT_ABORT ON will cause the transaction to be uncommittable
-- when the constraint violation occurs.
SET XACT_ABORT ON;
BEGIN TRY
BEGIN TRANSACTION;
-- A FOREIGN KEY constraint exists on this table. This
-- statement will generate a constraint violation error.
DELETE FROM Production.Product
WHERE ProductID = 980;
-- If the DELETE statement succeeds, commit the transaction.
COMMIT TRANSACTION;
END TRY
BEGIN CATCH
-- Execute error retrieval routine.
EXECUTE usp_GetErrorInfo;
-- Test XACT_STATE:
-- If 1, the transaction is committable.
-- If -1, the transaction is uncommittable and should
-- be rolled back.
-- XACT_STATE = 0 means that there is no transaction and
-- a commit or rollback operation would generate an error.
-- Test whether the transaction is uncommittable.
IF (XACT_STATE()) = -1
BEGIN
PRINT
N'The transaction is in an uncommittable state.' +
'Rolling back transaction.'
ROLLBACK TRANSACTION;
END;
-- Test whether the transaction is committable.
IF (XACT_STATE()) = 1
BEGIN
PRINT
N'The transaction is committable.' +
'Committing transaction.'
COMMIT TRANSACTION;
END;
END CATCH;
GO
Vea también
Referencia
ERROR_LINE (Transact-SQL)
ERROR_MESSAGE (Transact-SQL)
ERROR_NUMBER (Transact-SQL)
ERROR_PROCEDURE (Transact-SQL)
ERROR_SEVERITY (Transact-SQL)
ERROR_STATE (Transact-SQL)
RAISERROR (Transact-SQL)
@@ERROR (Transact-SQL)
GOTO (Transact-SQL)
BEGIN...END (Transact-SQL)
XACT_STATE (Transact-SQL)
SET XACT_ABORT (Transact-SQL)
Otros recursos
Usar TRY...CATCH en Transact-SQL
Niveles de gravedad de error del motor de base de datos
Recuperar información de errores en Transact-SQL
Controlar errores del motor de base de datos
Ayuda e información
Obtener ayuda sobre SQL Server 2005
Historial de cambios
Versión
Historial
14 de abril de 2006
Término
Definición
Contenido nuevo:
- Se agregó información acerca de un cambio en el comportamiento de las transacciones que no pueden confirmarse.