TRY...CATCH (Transact-SQL)

Aplica-se a:SQL ServerBanco de Dados SQL do AzureInstância Gerenciada de SQL do AzureAzure Synapse AnalyticsPDW (Analytics Platform System)Ponto de extremidade de SQL no Microsoft FabricWarehouse no Microsoft Fabric

Implementa tratamento de erros para Transact-SQL semelhante ao tratamento de exceções nas linguagens Microsoft Visual C# e Microsoft Visual C++. Um grupo de instruções Transact-SQL pode ser encapsulado em um bloco TRY. Se ocorre um erro no bloco TRY, o controle geralmente passa para outro grupo de instruções que está incluído em um bloco CATCH.

Convenções de sintaxe de Transact-SQL

Sintaxe

BEGIN TRY  
     { sql_statement | statement_block }  
END TRY  
BEGIN CATCH  
     [ { sql_statement | statement_block } ]  
END CATCH  
[ ; ]  

Observação

Para exibir a sintaxe do Transact-SQL para o SQL Server 2014 (12.x) e versões anteriores, confira a Documentação das versões anteriores.

Argumentos

sql_statement
Qualquer instrução Transact-SQL.

statement_block
Qualquer grupo de instruções Transact-SQL em um lote ou incluído em um bloco BEGIN...END.

Comentários

Um constructo TRY...CATCH captura todos os erros de execução com gravidade maior que 10 que não fecham a conexão de banco de dados.

Um bloco TRY deve ser seguido imediatamente por um bloco CATCH associado. A inclusão de qualquer outra instrução entre as instruções END TRY e BEGIN CATCH gera um erro de sintaxe.

Um constructo TRY...CATCH não pode abranger vários lotes. Um constructo TRY...CATCH não pode abranger vários blocos de instruções Transact-SQL. Por exemplo, um constructo TRY...CATCH não pode abranger dois blocos BEGIN...END de instruções Transact-SQL e não pode abranger um constructo IF...ELSE.

Se não houver erros no código incluído em um bloco TRY, quando a execução da última instrução no bloco TRY for concluída, o controle passará para a instrução imediatamente posterior à instrução END CATCH associada.

Se houver um erro no código incluído em um bloco TRY, o controle passará para a primeira instrução do bloco CATCH associado. Quando o código no bloco CATCH for concluído, o controle passará para a instrução imediatamente posterior à instrução END CATCH.

Observação

Se a instrução END CATCH for a última instrução de um procedimento armazenado ou gatilho, o controle voltará para a instrução que chamou o procedimento armazenado ou acionou o gatilho.

Os erros interceptados por um bloco CATCH não são retornados ao aplicativo que o chamou. Se qualquer parte das informações de erro precisar ser retornada ao aplicativo, o código no bloco CATCH deverá fazê-lo usando mecanismos como conjuntos de resultados SELECT ou as instruções RAISERROR e PRINT.

Os constructos TRY...CATCH podem ser aninhados. Um bloco TRY ou um bloco CATCH pode conter constructos TRY...CATCH aninhados. Por exemplo, um bloco CATCH pode conter um constructo TRY...CATCH inserido para tratar erros encontrados pelo código CATCH.

Os erros encontrados em um bloco CATCH são tratados como erros gerados em qualquer outro lugar. Se o bloco CATCH contiver um constructo TRY...CATCH aninhado, qualquer erro no bloco TRY aninhado passará o controle para o bloco CATCH aninhado. Se não houver nenhum constructo TRY...CATCH aninhado, o erro voltará para o chamador.

Os constructos TRY...CATCH capturam erros não tratados de procedimentos armazenados nem gatilhos executados pelo código do bloco TRY. Como alternativa, os procedimentos armazenados ou os gatilhos podem conter os próprios constructos TRY...CATCH para tratar os erros gerados por seu código. Por exemplo, quando um bloco TRY executa um procedimento armazenado e ocorre um erro no procedimento, o erro pode ser tratado das seguintes maneiras:

  • Se o procedimento armazenado não contiver seu próprio constructo TRY...CATCH, o erro retornará o controle para o bloco CATCH associado ao bloco TRY que contém a instrução EXECUTE.

  • Se o procedimento armazenado contiver um constructo TRY...CATCH, o erro transferirá o controle para o bloco CATCH do procedimento armazenado. Quando o código do bloco CATCH for concluído, o controle voltará para a instrução imediatamente posterior à instrução EXECUTE que chamou o procedimento armazenado.

As instruções GOTO não podem ser usadas para inserir um bloco TRY ou CATCH. As instruções GOTO podem ser usadas para saltar para um rótulo dentro do mesmo bloco TRY ou CATCH ou para sair de um bloco TRY ou CATCH.

O constructo TRY...CATCH não pode ser usado em uma função definida pelo usuário.

Recuperando informações de erro

No escopo de um bloco CATCH, as seguintes funções de sistema podem ser usadas para obter informações sobre o erro que causou a execução do bloco CATCH.

  • ERROR_NUMBER() retorna o número do erro.

  • ERROR_SEVERITY() retorna a severidade.

  • ERROR_STATE() retorna o número do estado do erro.

  • ERROR_PROCEDURE() retorna o nome do procedimento armazenado ou do gatilho no qual ocorreu o erro.

  • ERROR_LINE() retorna o número de 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 bloco CATCH. As informações de erro podem ser recuperadas com o uso dessas funções em qualquer lugar no escopo do bloco CATCH. 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 funções ERROR*_ também funcionam em um bloco CATCH dentro de um procedimento armazenado compilado nativamente.

Erros não afetados por um constructo TRY...CATCH

Os constructos TRY...CATCH 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 20 ou maior e a conexão de banco de dados não for interrompida, TRY...CATCH tratará o erro.

  • Atenções, como solicitações da interrupção de cliente ou conexões de cliente desfeitas.

  • Quando a sessão for finalizada por um administrador de sistema com o uso da instrução KILL.

Os seguintes tipos de erros não são tratados por um bloco CATCH quando ocorrerem 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 a recompilação no nível da instrução em um nível de execução inferior (por exemplo, ao executar sp_executesql ou um procedimento armazenado definido pelo usuário) dentro do bloco TRY, o erro ocorrerá em um nível inferior ao do constructo TRY...CATCH e será tratado pelo bloco CATCH associado.

O exemplo a seguir mostra como um erro de resolução de nome de objeto gerado por uma instrução SELECT não é capturado pela construção TRY...CATCH, mas é capturado pelo bloco CATCH quando a mesma instrução SELECT é 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 é capturado e o controle é transmitido para fora da construção TRY...CATCH para o próximo nível mais alto.

A execução da instrução SELECT dentro de um procedimento armazenado fará com que o erro ocorra em um nível inferior ao do bloco TRY. O erro será tratado pela construção 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 não confirmáveis e XACT_STATE

Se um erro gerado em um bloco TRY fizer com que o estado da transação atual seja invalidado, a transação será classificada como não confirmável. Um erro que normalmente finaliza uma transação fora de um bloco TRY faz com que uma transação entre em um estado não confirmável quando o erro ocorre dentro de um bloco TRY. Uma transação não confirmável só pode executar operações de leitura ou uma ROLLBACK TRANSACTION. A transação não pode executar nenhuma instrução Transact-SQL que possa gerar uma operação de gravação ou uma COMMIT TRANSACTION. A função XACT_STATE retornará o valor -1 se uma transação foi classificada como 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 foi enviada quando a transação entrou em um estado não confirmável, quando o lote terminar, 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 XACT_STATE, confira XACT_STATE (Transact-SQL).

Exemplos

a. Usando TRY...CATCH

O exemplo a seguir mostra uma instrução SELECT que gerará 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. Usando 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. Usando TRY...CATCH 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  

Consulte Também

THROW (Transact-SQL)
Gravidades de erros 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)