Introdução ao tratamento de Exceções

O seu código vai dar erro. Isso é um fato. Mesmo que seja a pessoa mais cuidadosa do mundo, você tem que preparar o seu código para o pior: O bug! Até porque no momento que os erros aparecerem, você vai precisar verificar o que está ocorrendo e ajustar da forma mais rápida possível.
E tem outra: Ninguém gosta de rodar uma aplicação e dar de cara com uma tela exibindo o stack do erro.
E para isso, você deve tratar as exceções que o teu código pode gerar.

Mas antes de entrar no assunto de tratamento de erros, primeiramente, gostaria de alinhar algumas ideias…

Esse será o primeiro de uma série de 2 ou 3 posts, veremos como ficará o próximo, pois este já ficou consideravelmente grande.

Tente fazer uma consulta em um objeto que não existe, uma tabela, por exemplo, e veja o erro que irá aparecer:

Msg 208, Level 16, State 1, Line 2
Invalid object name ‘dbo.TabelaErrada’.

Repare, temos 5 ‘itens’ a avaliar:

  1. Msg: Valor da coluna message_id na tabela sys.messages.
  2. Level: Severidade. É o tipo de erro que o SQL Server gerou. O nível varia de 0 (zero) a 24. Um resumo:
    1. 0 a 10: Mensagens não severas ou informacionais.
    2. 11 a 16: Erros que podem ser corrigidos pelo usuário, como: deadlocks, erros de sintaxe ou permissão, por exemplo.
    3. 17 a 19: Erros que devem ser repassados para o administrador, que o usuário não tem como resolver por conta própria, como: Falta de memória ou espaço em disco. Detalhes:
      1. Erros com severidade 18 ainda mantem a conexão ativa e o batch continua a execução, porém o administrador deve ser informado do problema ocorrido.
      2. Erros com severidade 19 encerram todo o batch em execução e o administrador do sistema deve ser contactado imediatamente.
    4. 20 a 24: Erros fatais. Erros com esta severidade indicam que a tarefa que está executando o processo do Database Engine parou a execução ou que existe algum objeto que está danificado.
      1. Os Erros de severidade 19 a 24 são gravador no Error Log.
  3. State: Um único erro pode ser disparado por diversas condições. Cada uma dessas condições são os estados. Ele é muito utilizado ao pesquisar por um erro nas bases de conhecimento, ou pelo time da Microsoft para identificar a posição onde o erro foi gerado.
  4. Line: A linha onde o erro foi chamado.
  5. Invalid Object Name: A descrição do erro propriamente dito.

Para maiores detalhes no que diz respeito ao Level e ao State, vejam os seguintes links:

Agora, encapsule essa tabela em uma procedure e veja o que acontece:

Msg 208, Level 16, State 1, Procedure prListaTabelaNaoExistente, Line 9
Invalid object name ‘TabelaNaoExistente’.

Note que agora existe mais um item a avaliar: o local que chamou o objeto inválido.

Para mostrar o comportamento do que foi dito acima, criarei uma tabela e, então, vou forçar alguns erros…

Agora, veja o erro que ocorre ao tentar inserir o mesmo registro, causando um conflito de Primary Key.

Msg 2627, Level 14, State 1, Line 13
Violation of PRIMARY KEY constraint ‘PK__Clientes__C1FE6AA95FA89FA3’.
Cannot insert duplicate key in object ‘dbo.Clientes’. The duplicate key value is (1).
The statement has been terminated.

Lembra-se quando eu comentei sobre a severidade dos erros? Veja o que acontece quando tentos inserir 3 registros, sendo o segundo duplicado.

Veja, mesmo tendo um registro duplicado no meio do batch, tive a execução do último insert. Veja o “level 14”, que indica que o erro pode ser ajustado pelo usuário. Nesse caso, apenas o statement é abortado, mas o batch continua sendo executado normalmente até o final.

E se eu quisesse que o batch restante fosse encerrado no momento do erro, e não apenas o statement? Para isto, existe uma opção chamada XACT_ABORT, que realiza esse comportamento. Agora, note que o comportamento é diferente caso o batch esteja dentro da mesma transação. Veja:

Percebeu? Quando existe uma transação, é realizado o rollback de toda a transação. Ficou mais claro o uso do XACT_ABORT? Para maiores detalhes, veja em: https://msdn.microsoft.com/pt-br/library/ms188792%28v=sql.120%29.aspx?f=255&MSPPError=-2147217396

Antes de entrar nos tratamentos de exceções, gostaria de explicar algo muito comum no processo de desenvolvimento: Procedures aninhadas. Quando ocorre um erro, qual o comportamento?

Imagine a situação: Usuário executa a procedure1 que, dentro dela, chama a procedure2 e, em seguida, a procedure3. O que vai acontecer? A resposta: Depende. Vejamos:

  • Se o conteúdo da procedure2 causar a finalização de um statement, todo o resto da procedure será exectada, bem como a procedure3.
  • Um erro na procedure2 pode causar a finalização de toda a procedure, mas permitir que a procedure3 seja executada normalmente – uma consulta a uma tabela inexistente pode causar esse tipo de erro:
  • Um erro na procedure2 pode causar o encerramento de todo o batch subsequente. Um exemplo: Erro de conversão:

    Posso ir além e dizer que, no meio da execução, ocorre um erro de severidade 20 ou maior. Lembra o que ocorre? A finalização da conexão, com a possibilidade de registro em log. Quer saber quais os erros que podem causar o encerramento da conexão?

  • Troque o language_id para 1046 para ver as mensagens em português.

Nos vemos no próximos post sobre o assunto!

Um comentário

Deixe uma resposta

Esse site utiliza o Akismet para reduzir spam. Aprenda como seus dados de comentários são processados.