Partilhar via


TENTA... CATCH (Transact-SQL)

Aplica-se a:SQL ServerBase de Dados SQL do AzureInstância Gerida do Azure SQLAzure Synapse AnalyticsSistema de Plataforma de Análise (PDW)Ponto de Extremidade de Análise SQL no Microsoft FabricArmazém no Microsoft FabricBase de Dados SQL no Microsoft Fabric

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

Transact-SQL convenções de sintaxe

Syntax

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

Arguments

sql_statement

Qualquer declaração Transact-SQL.

statement_block

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

Remarks

Uma TRY...CATCH construção captura todos os erros de execução com uma gravidade superior a 10 que não fecham a conexão do banco de dados.

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

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

Se não houver erros no código que está incluído em um TRY bloco, quando a última instrução no bloco terminar, o TRY controle passa para a instrução imediatamente após a instrução associada END CATCH .

Se houver um erro no código incluído em um TRY bloco, o controle passa para a primeira instrução no bloco associado CATCH . Quando o código no bloco termina, o CATCH controle passa para a instrução imediatamente após a END CATCH instrução.

Note

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 presos por um CATCH bloco não são retornados ao aplicativo de chamada. Se qualquer parte das informações de erro deve ser retornada ao aplicativo, o código no CATCH bloco deve fazê-lo usando mecanismos como SELECT conjuntos de resultados ou as RAISERROR instruções 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 manipular 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 passa 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 As construções 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 manipular 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 o CATCH bloco associado ao TRY bloco que contém a EXECUTE instrução.

  • Se o procedimento armazenado contiver uma TRY...CATCH construção, o erro transfere o controle para o CATCH bloco no procedimento armazenado. Quando o código de CATCH bloco termina, o controle é passado de volta para a instrução imediatamente após a EXECUTE instrução que chamou o procedimento armazenado.

GOTO As instruções não podem ser usadas para inserir um TRY ou CATCH bloquear. GOTO As instruções podem ser usadas para saltar para um rótulo dentro do mesmo TRY bloco OR CATCH ou para deixar 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:

Function Description
ERROR_NUMBER Retorna o número do erro.
ERROR_SEVERITY Devolve a gravidade.
ERROR_STATE Retorna o número do estado de erro.
ERROR_PROCEDURE Retorna o nome do procedimento armazenado ou gatilho onde 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 quaisquer parâmetros substituíveis, como comprimentos, nomes de objetos ou horários.

Essas funções retornam 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. CATCH No bloco de uma TRY...CATCH construção, 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 bloco dentro de CATCH um procedimento armazenado compilado nativamente.

Erros não afetados por um TRY... Construção CATCH

TRY...CATCH As construções não intercetam as seguintes condições:

  • Avisos ou mensagens informativas com gravidade igual ou inferior a 10.

  • Erros com uma gravidade igual ou superior a 20 que interrompem o processamento da tarefa do Mecanismo de Banco de Dados do SQL Server para a sessão. Se ocorrer um erro com gravidade igual ou superior a 20 e a conexão do banco de dados não for interrompida, TRY...CATCH o erro será manipulado.

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

  • Quando um administrador de sistema usa a KILL instrução para encerrar a sessão.

Os seguintes tipos de erros não são manipulados por um CATCH bloco quando ocorrem no mesmo nível de execução que a TRY...CATCH construção:

  • Erros de compilação, como erros de sintaxe, que impedem a execução de um lote.

  • Erros que ocorrem durante a recompilação no nível da instrução, como erros de resolução de nome de objeto que ocorrem após a compilação devido à resolução de nome adiada.

  • 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 em nível de 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 TRY bloco, o erro ocorre em um nível mais baixo do que a TRY...CATCH 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 TRY...CATCH pela construção, mas é capturado pelo bloco quando a mesma CATCH instrução é executada SELECT 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 é detetado e o controle passa da construção para o TRY...CATCH próximo nível superior.

Executar a 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 pela TRY...CATCH construção.

-- 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 autorizáveis e XACT_STATE

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 confirmada. Um erro que normalmente termina 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 confirmada só pode executar operações de leitura ou um ROLLBACK TRANSACTIONarquivo . A transação não pode executar nenhuma instrução Transact-SQL que geraria uma operação de gravação ou um COMMIT TRANSACTIONarquivo . A XACT_STATE função retorna um valor de se uma transação foi classificada -1 como uma transação não confirmada. Quando um lote é concluído, o Mecanismo de Banco de Dados reverte todas as transações ativas não confirmadas. 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 para o aplicativo cliente. Isso indica que uma transação não confirmada foi detetada e revertida.

Para obter mais informações sobre transações não confirmadas e a XACT_STATE função, consulte XACT_STATE.

Examples

A. Use TRY... CAPTURAS

O exemplo a seguir mostra uma SELECT instrução que gera um erro de divisão por zero. O erro faz com que a execução salte para o bloco associado CATCH .

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 numa transação

O exemplo a seguir mostra como um TRY...CATCH bloco funciona dentro de uma transação. A instrução dentro do TRY bloco 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... CATCH com XACT_STATE

O exemplo a seguir mostra como usar a TRY...CATCH construção para manipular erros que ocorrem dentro de uma transação. A XACT_STATE função determina se a transação deve ser confirmada ou revertida. Neste exemplo, SET XACT_ABORT é ON. Isso torna a transação não confirmada quando ocorre o erro de violação de restrição.

-- 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