TRY...CATCH (Transact-SQL)
Aplica-se a: SQL Server Banco de Dados SQL do Azure Instância Gerenciada de SQL do Azure Azure Synapse Analytics PDW (Analytics Platform System) Ponto de extremidade de análise do SQL Warehouse no Microsoft Fabric
Implementa o tratamento de erros para Transact-SQL semelhante ao tratamento de exceções nas linguagens C# e Visual C++. Um grupo de instruções Transact-SQL pode ser colocado em um TRY
bloco. Se ocorrer um erro no bloco, o TRY
controle geralmente é passado para outro grupo de instruções que está entre um CATCH
bloco.
Convenções de sintaxe de Transact-SQL
Sintaxe
BEGIN TRY
{ sql_statement | statement_block }
END TRY
BEGIN CATCH
[ { sql_statement | statement_block } ]
END CATCH
[ ; ]
Argumentos
sql_statement
Qualquer instrução Transact-SQL.
statement_block
Qualquer grupo de instruções Transact-SQL em um lote ou entre blocos BEGIN...END
.
Comentários
Um TRY...CATCH
constructo captura todos os erros de execução que têm uma gravidade maior que 10 que não fecham a conexão com o banco de dados.
Um TRY
bloco deve ser imediatamente seguido por um bloco associado CATCH
. Incluir quaisquer outras instruções entre as END TRY
instruções and BEGIN CATCH
gera um erro de sintaxe.
Um TRY...CATCH
constructo não pode abranger vários lotes. Um TRY...CATCH
constructo não pode abranger vários blocos de instruções Transact-SQL. Por exemplo, um TRY...CATCH
constructo não pode abranger dois BEGIN...END
blocos de instruções Transact-SQL e não pode abranger um IF...ELSE
constructo.
Se não houver erros no código que está entre um TRY
bloco, quando a última instrução no bloco for concluída, o TRY
controle passará para a instrução imediatamente após a instrução associada END CATCH
.
Se houver um erro no código que está entre um TRY
bloco, o controle passará para a primeira instrução no bloco associado CATCH
. Quando o código no bloco é concluído, o CATCH
controle passa para a instrução imediatamente após a END CATCH
instrução.
Observação
Se a END CATCH
instrução for a última instrução em um procedimento armazenado ou gatilho, o controle será passado de volta para a instrução que chamou o procedimento armazenado ou disparou o gatilho.
Os erros capturados por um CATCH
bloco não são retornados ao aplicativo de chamada. Se qualquer parte das informações de erro precisar ser retornada ao aplicativo, o código no CATCH
bloco deverá fazer isso usando mecanismos como SELECT
conjuntos de resultados ou instruções RAISERROR
and PRINT
.
TRY...CATCH
construções podem ser aninhadas. Um TRY
bloco ou um CATCH
bloco pode conter construções aninhadas TRY...CATCH
. Por exemplo, um CATCH
bloco pode conter uma construção incorporada TRY...CATCH
para lidar com erros encontrados pelo CATCH
código.
Os erros encontrados em um CATCH
bloco são tratados como erros gerados em qualquer outro lugar. Se o CATCH
bloco contiver uma construção aninhada TRY...CATCH
, qualquer erro no bloco aninhado TRY
passará o controle para o bloco aninhado CATCH
. Se não houver nenhuma construção aninhada TRY...CATCH
, o erro será passado de volta para o chamador.
TRY...CATCH
Os constructos capturam erros não tratados de procedimentos armazenados ou gatilhos executados pelo código no TRY
bloco. Como alternativa, os procedimentos armazenados ou gatilhos podem conter suas próprias TRY...CATCH
construções para lidar com erros gerados por seu código. Por exemplo, quando um TRY
bloco executa um procedimento armazenado e ocorre um erro no procedimento armazenado, o erro pode ser tratado das seguintes maneiras:
Se o procedimento armazenado não contiver sua própria
TRY...CATCH
construção, o erro retornará o controle para oCATCH
bloco associadoTRY
ao bloco que contém aEXECUTE
instrução.Se o procedimento armazenado contiver uma
TRY...CATCH
construção, o erro transferirá o controle para oCATCH
bloco no procedimento armazenado. Quando o código deCATCH
bloco é concluído, o controle é passado de volta para a instrução imediatamente após aEXECUTE
instrução que chamou o procedimento armazenado.
GOTO
As instruções não podem ser usadas para inserir um TRY
bloco OR CATCH
. GOTO
As instruções podem ser usadas para pular para um rótulo dentro do mesmo TRY
bloco OR CATCH
ou para sair de um TRY
bloco OR CATCH
.
A TRY...CATCH
construção não pode ser usada em uma função definida pelo usuário.
Recuperar informações de erro
No escopo de um CATCH
bloco, as seguintes funções do sistema podem ser usadas para obter informações sobre o erro que causou a execução do CATCH
bloco:
Função | Descrição |
---|---|
ERROR_NUMBER | Retorna o número do erro. |
ERROR_SEVERITY | Retorna a gravidade. |
ERROR_STATE | Retorna o número do estado do erro. |
ERROR_PROCEDURE | Retorna o nome do procedimento armazenado ou gatilho em que o erro ocorreu. |
ERROR_LINE | Retorna o número da linha dentro da rotina que causou o erro. |
ERROR_MESSAGE | Retorna o texto completo da mensagem de erro. O texto inclui os valores fornecidos para qualquer parâmetro substituível, como comprimentos, nomes de objeto ou horas. |
Essas funções retornarão NULL
se forem chamadas fora do escopo do CATCH
bloco. As informações de erro podem ser recuperadas usando essas funções de qualquer lugar dentro do escopo do CATCH
bloco. Por exemplo, o script a seguir mostra um procedimento armazenado que contém funções de tratamento de erros. No bloco CATCH
de uma construção TRY...CATCH
, o procedimento armazenado é chamado e as informações sobre o erro são retornadas.
-- 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;
As ERROR_*
funções também funcionam em um CATCH
bloco dentro de um procedimento armazenado compilado nativamente.
Erros não afetados por um TRY... Construção CATCH
TRY...CATCH
Os constructos não interceptam as seguintes condições:
Avisos ou mensagens informativas que têm uma severidade 10 ou menor.
Erros que têm uma severidade 20 ou maior, que param o processamento de tarefa do Mecanismo de Banco de Dados do SQL Server para a sessão. Se ocorrer um erro com gravidade de 20 ou superior e a conexão com o banco de dados não for interrompida,
TRY...CATCH
o manipulará o erro.Atenções, como solicitações da interrupção de cliente ou conexões de cliente desfeitas.
Quando um administrador do sistema usa a
KILL
instrução para encerrar a sessão.
Os seguintes tipos de erros não são tratados por um CATCH
bloco quando ocorrem no mesmo nível de execução que o constructo TRY...CATCH
:
Erros de compilação, como erros de sintaxe, que impeçam a execução de um lote.
Erros que ocorrem durante a recompilação em nível de instrução, como os erros de resolução do nome de objeto que ocorrem após a compilação, devido à resolução adiada do nome.
Erros de resolução de nome de objeto
Esses erros são retornados ao nível que executou o lote, o procedimento armazenado ou o gatilho.
Se ocorrer um erro durante a compilação ou recompilação no nível da instrução em um nível de execução inferior (por exemplo, durante a execução sp_executesql
ou um procedimento armazenado definido pelo usuário) dentro do TRY
bloco, o erro ocorrerá em um nível inferior ao TRY...CATCH
da construção e será tratado pelo bloco associado CATCH
.
O exemplo a seguir mostra como um erro de resolução de nome de objeto gerado por uma SELECT
instrução não é capturado pelo constructo TRY...CATCH
, mas é capturado CATCH
pelo bloco quando a mesma SELECT
instrução é executada dentro de um procedimento armazenado.
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
O erro não é detectado e o controle passa do constructo TRY...CATCH
para o próximo nível superior.
A execução da SELECT
instrução dentro de um procedimento armazenado faz com que o erro ocorra em um nível inferior ao TRY
bloco. O erro é tratado pelo constructo TRY...CATCH
.
-- 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;
Transações e XACT_STATE não confirmáveis
Se um erro gerado em um TRY
bloco fizer com que o estado da transação atual seja invalidado, a transação será classificada como uma transação não confirmável. Um erro que normalmente encerra uma transação fora de um TRY
bloco faz com que uma transação entre em um estado não confirmável quando o erro ocorre dentro de um TRY
bloco. Uma transação não confirmável só pode executar operações de leitura ou um ROLLBACK TRANSACTION
. A transação não pode executar nenhuma instrução Transact-SQL que gere uma operação de gravação ou um COMMIT TRANSACTION
. A XACT_STATE
função retorna um valor de if uma transação foi classificada -1
como uma transação não confirmável. Quando um lote é concluído, o Mecanismo de Banco de Dados reverte quaisquer transações ativas não confirmáveis. Se nenhuma mensagem de erro tiver sido enviada quando a transação entrar em um estado não confirmável, quando o lote for concluído, uma mensagem de erro será enviada ao aplicativo cliente. Isso indica que uma transação não confirmável foi detectada e revertida.
Para obter mais informações sobre transações não confirmáveis e a função, consulte XACT_STATEXACT_STATE
.
Exemplos
R. Usar TRY... PEGAR
O exemplo a seguir mostra uma instrução SELECT
que gera um erro de divisão por zero. O erro faz com que a execução salte para o bloco CATCH
associado.
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 em uma transação
O exemplo a seguir mostra como um bloco TRY...CATCH
funciona dentro de uma transação. A instrução dentro do bloco TRY
gera um erro de violação de restrição.
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... PEGUE com XACT_STATE
O exemplo a seguir mostra como usar a construção TRY...CATCH
para tratar erros que ocorrem dentro de uma transação. A função XACT_STATE
determina se a transação deve ser confirmada ou revertida. Neste exemplo, SET XACT_ABORT
é ON
. Isso torna a transação não confirmável quando o erro de violação de restrição ocorrer.
-- 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
Conteúdo relacionado
- THROW (Transact-SQL)
- Severidades de erro do Mecanismo de Banco de Dados
- 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)