Partilhar via


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 Analytics Platform System (PDW) Ponto de extremidade de análise de SQL no Microsoft Fabric Warehouse no Microsoft Fabric Banco de Dados SQL 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 o CATCH bloco associado TRY ao bloco que contém a EXECUTE instrução.

  • Se o procedimento armazenado contiver uma TRY...CATCH construção, o erro transferirá o controle para o CATCH bloco no procedimento armazenado. Quando o código de CATCH bloco é concluído, 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 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