Implementar o tratamento de exceção estruturado

Concluído(a)

Agora que você tem uma compreensão da natureza dos erros e do tratamento de erros básicos no T-SQL, é hora de examinar uma forma mais avançada de tratamento de erros: tratamento estruturado de exceções.

Aqui, você verá como usá-lo e avaliar seus benefícios e limitações, incluindo o bloco TRY CATCH, o papel das funções de tratamento de erros e entender a diferença entre erros capturáveis e não capturáveis. Por fim, você verá como os erros podem ser gerenciados e revelados quando necessário.

O que é o bloco de programação TRY/CATCH

O tratamento de exceções estruturados é mais poderoso do que o tratamento de erros com base na variável do @@ERROR sistema. Ele permite que você impeça que o código seja repleto de código de tratamento de erros e centralize esse código de tratamento de erros. Centralização do código de tratamento de erros também significa que você pode se concentrar mais na finalidade do código do que no tratamento de erros presente nele.

Bloco TRY e bloco CATCH

Ao usar o tratamento de exceção estruturado, o código que pode gerar um erro é colocado em um bloco TRY. Os blocos TRY são colocados por BEGIN TRY e END TRY instruções.

Caso ocorra um erro capturável - a maioria dos erros pode ser capturada - o controle de execução é movido para o bloco CATCH. O bloco CATCH é uma série de instruções T-SQL entre BEGIN CATCH instruções e instruções END CATCH .

Observação

Embora BEGIN CATCH e END TRY sejam instruções separadas, a instrução BEGIN CATCH deve seguir imediatamente .END TRY

Limitações atuais

Idiomas de alto nível geralmente oferecem um constructo try/catch/finally e geralmente são usados para liberar recursos implicitamente. Não há nenhum bloco FINALLY equivalente no T-SQL.

Entender a diferença entre erros capturáveis e não capturáveis

É importante perceber que, embora os blocos TRY/CATCH permitam capturar uma gama muito maior de erros do que você poderia com @@ERROR, você não pode capturar todos os tipos.

Erros capturáveis ​​vs. erros não capturáveis

Nem todos os erros podem ser capturados pelos blocos TRY/CATCH dentro do mesmo escopo onde o bloco TRY/CATCH existe. Muitas vezes, erros que não podem ser detectados no mesmo escopo podem ser detectados em um escopo adjacente. Por exemplo, talvez você não consiga detectar um erro dentro do procedimento armazenado que contém o bloco TRY/CATCH. No entanto, é provável que você encontre esse erro em um bloco TRY/CATCH no código que chamou o procedimento armazenado onde o erro ocorreu.

Erros comuns não detectáveis

Alguns erros nunca são capturados por TRY/CATCH qualquer escopo:

  • Mensagens informativas ou avisos com severidade 10 ou inferior.
  • Erros com severidade 20 ou superior que interrompem a tarefa Mecanismo de Banco de Dados do SQL Server da sessão.
  • Atenção: solicitações de interrupção do cliente ou conexões de cliente interrompidas.
  • Sessões encerradas por um administrador do sistema usando KILL.

Outros erros não são capturados no mesmo escopo em que existem TRY/CATCH , mas podem ser capturados por um TRY/CATCH escopo ao redor (por exemplo, no lote de chamada ou procedimento armazenado):

  • Erros de compilação, como erros de sintaxe, que impedem a compilação de um lote.
  • Erros de resolução de nome de objeto causados pela resolução de nomes adiados, por exemplo, um procedimento armazenado que faz referência a uma tabela que ainda não existe. O erro só é gerado quando o procedimento tenta resolver o nome em tempo de execução.

Como relançar erros usando THROW

Se a THROW instrução for usada em um bloco CATCH sem parâmetros, ela irá relançar o erro que causou a inserção do código no bloco CATCH. Você pode usar essa técnica para implementar o log de erros no banco de dados capturando erros e registrando seus detalhes e, em seguida, lançando o erro original para o aplicativo cliente, para que ele possa ser tratado lá.

Aqui está um exemplo de como relançar um erro.

BEGIN TRY
    -- code to be executed
END TRY
BEGIN CATCH
    PRINT ERROR_MESSAGE();
    THROW
END CATCH

Em algumas versões anteriores do SQL Server, não havia nenhum método para gerar um erro do sistema. Embora THROW não possa especificar um erro do sistema a ser gerado, quando THROW for usado sem parâmetros em um bloco CATCH, ele executará novamente erros do sistema e do usuário.

O que são funções de tratamento de erros

Os blocos CATCH disponibilizam as informações relacionadas a erros durante toda a duração do bloco CATCH. Isso inclui subescopos, como procedimentos armazenados, executados dentro do bloco CATCH.

Funções de tratamento de erros

Lembre-se de que, ao programar com @@ERROR, o valor mantido pela variável do @@ERROR sistema foi redefinido assim que a próxima instrução foi executada.

Outra vantagem fundamental do tratamento estruturado de exceções no T-SQL é que uma série de funções de tratamento de erros foram fornecidas e mantêm seus valores em todo o bloco CATCH. Funções separadas fornecem cada propriedade de um erro que foi gerado.

Isso significa que você pode escrever procedimentos armazenados de tratamento de erros genéricos que ainda podem acessar as informações relacionadas a erros.

  • Os blocos CATCH disponibilizam as informações relacionadas a erros durante toda a duração do bloco CATCH.
  • @@Error é redefinido quando a próxima instrução é executada.

Gerenciar transações em blocos CATCH

Um erro que normalmente encerraria uma transação fora de um TRY bloco pode, em vez disso, deixar a transação em um estado não comprometido quando o erro ocorre dentro de um TRY bloco. Uma transação não compromissável só pode executar operações de leitura ou uma ROLLBACK TRANSACTIONtentativa de confirmar ou modificar dados gera outro erro.

Use a XACT_STATE() função dentro CATCH de blocos para determinar o que fazer com a transação atual:

  • XACT_STATE() = 1 — há uma transação ativa e committable. Você pode COMMIT ou ROLLBACK.
  • XACT_STATE() = 0 — não há nenhuma transação ativa. Nenhuma confirmação ou reversão é necessária.
  • XACT_STATE() = -1 — há uma transação ativa, mas não compromissável. Você deve ROLLBACK; a confirmação falhará.

@@TRANCOUNT por si só não é possível detectar o estado não compromissável, assim XACT_STATE() como a verificação recomendada para blocos CATCH que gerenciam transações.

O padrão de bloco CATCH canônico é:

BEGIN CATCH
    IF XACT_STATE() = -1
        ROLLBACK TRANSACTION;
    ELSE IF XACT_STATE() = 1
        COMMIT TRANSACTION;  -- or ROLLBACK, depending on intent

    THROW;  -- rethrow to caller
END CATCH;

Gerenciar erros no código

A integração do SQL CLR permite a execução do código gerenciado no SQL Server. Linguagens .NET de alto nível, como C# e VB, têm tratamento detalhado de exceções disponível para eles. Erros podem ser detectados usando blocos try/catch/finally padrão do .NET.

Erros no código gerenciado

Em geral, talvez você queira capturar erros dentro do código gerenciado o máximo possível. No entanto, é importante perceber que todos os erros não tratados no código gerenciado são passados de volta para o código T-SQL de chamada. Sempre que qualquer erro ocorrido no código gerenciado for retornado ao SQL Server, ele será exibido como um erro 6522. Erros podem ser aninhados e aquele erro específico envolverá a causa real do erro.

Outra causa rara, mas possível, de erros no código gerenciado seria que o código poderia executar uma RAISERROR instrução T-SQL por meio de um objeto SqlCommand.