TRY...CATCH (Transact-SQL)
Se aplica a: SQL Server Azure SQL Database Azure SQL Managed Instance Azure Synapse Analytics Analytics Platform System (PDW) Punto de conexión de análisis SQL en Microsoft Fabric Almacenamiento en Microsoft Fabric
Implementa el control de errores para Transact-SQL similar al control de excepciones en los lenguajes C# y Visual C++. Un grupo de instrucciones Transact-SQL se puede incluir en un TRY
bloque. Si se produce un error en el TRY
bloque, el control normalmente se pasa a otro grupo de instrucciones que se incluye en un CATCH
bloque.
Convenciones de sintaxis de Transact-SQL
Sintaxis
BEGIN TRY
{ sql_statement | statement_block }
END TRY
BEGIN CATCH
[ { sql_statement | statement_block } ]
END CATCH
[ ; ]
Argumentos
sql_statement
Cualquier instrucción Transact-SQL.
statement_block
Cualquier grupo de instrucciones Transact-SQL en un lote o entre un BEGIN...END
bloque.
Comentarios
Una TRY...CATCH
construcción detecta todos los errores de ejecución que tienen una gravedad superior a 10 que no cierran la conexión de la base de datos.
Un TRY
bloque debe ir seguido inmediatamente de un bloque asociado CATCH
. La inclusión de cualquier otra instrucción entre las END TRY
instrucciones y BEGIN CATCH
genera un error de sintaxis.
Una TRY...CATCH
construcción no puede abarcar varios lotes. Una TRY...CATCH
construcción no puede abarcar varios bloques de instrucciones Transact-SQL. Por ejemplo, una TRY...CATCH
construcción no puede abarcar dos BEGIN...END
bloques de instrucciones Transact-SQL y no puede abarcar una IF...ELSE
construcción.
Si no hay errores en el código que se incluye en un TRY
bloque, cuando finaliza la última instrucción del TRY
bloque, el control pasa a la instrucción inmediatamente después de la instrucción asociada END CATCH
.
Si hay un error en el código que se incluye en un TRY
bloque, el control pasa a la primera instrucción del bloque asociado CATCH
. Cuando finaliza el código del CATCH
bloque, el control pasa a la instrucción inmediatamente después de la END CATCH
instrucción .
Nota:
Si la END CATCH
instrucción 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 desencadenó el desencadenador.
Los errores atrapados por un CATCH
bloque no se devuelven a la aplicación que realiza la llamada. Si se debe devolver cualquier parte de la información de error a la aplicación, el código del CATCH
bloque debe hacerlo mediante mecanismos como SELECT
conjuntos de resultados o las RAISERROR
instrucciones y PRINT
.
TRY...CATCH
las construcciones se pueden anidar. TRY
Un bloque o un CATCH
bloque puede contener construcciones anidadasTRY...CATCH
. Por ejemplo, un CATCH
bloque puede contener una construcción insertada TRY...CATCH
para controlar los errores detectados por el CATCH
código.
Los errores encontrados en un CATCH
bloque se tratan como errores generados en cualquier otro lugar. Si el CATCH
bloque contiene una construcción anidada TRY...CATCH
, cualquier error del bloque anidado TRY
pasa el control al bloque anidado CATCH
. Si no hay ninguna construcción anidada TRY...CATCH
, el error se devuelve al autor de la llamada.
TRY...CATCH
construye detectar errores no controladas a partir de procedimientos almacenados o desencadenadores ejecutados por el código del TRY
bloque. Como alternativa, los procedimientos almacenados o desencadenadores pueden contener sus propias TRY...CATCH
construcciones para controlar los errores generados por su código. Por ejemplo, cuando un TRY
bloque ejecuta un procedimiento almacenado y se produce un error en el procedimiento almacenado, el error se puede controlar de las maneras siguientes:
Si el procedimiento almacenado no contiene su propia
TRY...CATCH
construcción, el error devuelve el control alCATCH
bloque asociado alTRY
bloque que contiene laEXECUTE
instrucción .Si el procedimiento almacenado contiene una
TRY...CATCH
construcción, el control de transferencia de errores alCATCH
bloque del procedimiento almacenado. Cuando finaliza el código deCATCH
bloque, el control se devuelve a la instrucción inmediatamente después de laEXECUTE
instrucción que llamó al procedimiento almacenado.
GOTO
Las instrucciones no se pueden usar para escribir un TRY
bloque o CATCH
. GOTO
Las instrucciones se pueden usar para saltar a una etiqueta dentro del mismo TRY
bloque o CATCH
para dejar un TRY
bloque o CATCH
.
La TRY...CATCH
construcción no se puede usar en una función definida por el usuario.
Recuperar información de error
En el ámbito de un CATCH
bloque, se pueden usar las siguientes funciones del sistema para obtener información sobre el error que provocó la ejecución del CATCH
bloque:
Función | Descripción |
---|---|
ERROR_NUMBER | Devuelve el número del error. |
ERROR_SEVERITY | Devuelve la gravedad. |
ERROR_STATE | Devuelve el número de estado de 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 dentro de la rutina que provocó el error. |
ERROR_MESSAGE | Devuelve el texto completo del mensaje de error. El texto incluye los valores proporcionados para los parámetros sustituibles, como las longitudes, nombres de objeto o tiempos. |
Estas funciones devuelven NULL
si se llama fuera del ámbito del CATCH
bloque. La información de error se puede recuperar mediante estas funciones desde cualquier parte del ámbito del CATCH
bloque. Por ejemplo, en el siguiente script 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.
-- 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;
Las ERROR_*
funciones también funcionan en un CATCH
bloque dentro de un procedimiento almacenado compilado de forma nativa.
Errores no afectados por un TRY... Construcción CATCH
TRY...CATCH
las construcciones no interceptan las condiciones siguientes:
Advertencias o mensajes informativos que tienen una gravedad 10 o inferior.
Errores que tienen la gravedad 20 o superior que detienen el procesamiento de las tareas de Motor de base de datos de SQL Server en la sesión. Si se produce un error que tiene una gravedad de 20 o superior y la conexión de base de datos no se interrumpe,
TRY...CATCH
controla el error.Atenciones, como solicitudes de interrupción de clientes o conexiones de cliente interrumpidas.
Cuando un administrador del sistema usa la
KILL
instrucción para finalizar la sesión.
Los siguientes tipos de errores no se controlan mediante un CATCH
bloque cuando se producen en el mismo nivel de ejecución que la TRY...CATCH
construcción:
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.
Errores de resolución de nombres de objeto
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 en el 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 TRY
bloque, el error se produce en un nivel inferior al de la TRY...CATCH
construcción y lo controlará el bloque asociado CATCH
.
En el ejemplo siguiente se muestra cómo la TRY...CATCH
construcción no detecta un error de resolución de nombres de objeto generado por una SELECT
instrucción, pero el bloque detecta CATCH
cuando se ejecuta la misma SELECT
instrucción dentro de un procedimiento almacenado.
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 detecta y el control pasa de la TRY...CATCH
construcción al siguiente nivel superior.
La ejecución de la SELECT
instrucción dentro de un procedimiento almacenado hace que el error se produzca en un nivel inferior al TRY
bloque. La construcción controla el TRY...CATCH
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;
Transacciones no confirmadas y XACT_STATE
Si un error generado en un TRY
bloque hace que el estado de la transacción actual se invalide, la transacción se clasifica como una transacción no confirmada. Un error que normalmente finaliza una transacción fuera de un TRY
bloque hace que una transacción escriba un estado no confirmable cuando se produce el error dentro de un TRY
bloque. Una transacción sin confirmar solo puede realizar operaciones de lectura o .ROLLBACK TRANSACTION
La transacción no puede ejecutar ninguna instrucción Transact-SQL que generaría una operación de escritura o .COMMIT TRANSACTION
La XACT_STATE
función devuelve un valor de -1
si una transacción se ha clasificado como una transacción no confirmable. Cuando finaliza el lote, Motor de base de datos revierte todas las transacciones activas no confirmables. Si no se envió ningún mensaje de error cuando la transacción entró en un estado no confirmable, cuando finaliza el lote, se envía un mensaje de error a la aplicación cliente. Esto indica que se ha detectado y revertido una transacción no confirmable.
Para obtener más información sobre las transacciones no confirmadas y la XACT_STATE
función, consulte XACT_STATE.
Ejemplos
A Usar TRY...CATCH
En este ejemplo de código se muestra una instrucción SELECT
que genera un error de división por cero. El error hace que la ejecución salte al bloque CATCH
asociado.
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. Use 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.
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. Use 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 sea no confirmable cuando se produce el error por infracción de restricción.
-- 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.
-- You may want to commit a transaction in a catch block if you want to commit changes to statements that ran prior to the error.
IF (XACT_STATE()) = 1
BEGIN
PRINT N'The transaction is committable. Committing transaction.'
COMMIT TRANSACTION;
END;
END CATCH;
GO
Contenido relacionado
- THROW (Transact-SQL)
- gravedades de errores de Motor de base de datos
- 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)