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:
- Msg: Valor da coluna message_id na tabela sys.messages.
- Level: Severidade. É o tipo de erro que o SQL Server gerou. O nível varia de 0 (zero) a 24. Um resumo:
- 0 a 10: Mensagens não severas ou informacionais.
- 11 a 16: Erros que podem ser corrigidos pelo usuário, como: deadlocks, erros de sintaxe ou permissão, por exemplo.
- 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:
- 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.
- Erros com severidade 19 encerram todo o batch em execução e o administrador do sistema deve ser contactado imediatamente.
- 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.
- Os Erros de severidade 19 a 24 são gravador no Error Log.
- 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.
- Line: A linha onde o erro foi chamado.
- 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:
- Level: https://technet.microsoft.com/en-us/library/ms164086(v=sql.105).aspx
- State: https://msdn.microsoft.com/en-us/library/ms180031.aspx
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…
1 2 3 4 5 6 7 8 9 10 |
-- Criação da tabela CREATE TABLE Clientes ( Cod int NOT NULL PRIMARY KEY, Nome VARCHAR(50) NOT NULL, CPF VARCHAR(11) NOT NULL CHECK (LEN(CPF) = 11) ) GO -- Inserção de um registro INSERT INTO Clientes values (1, 'Logan', '99999999999') GO |
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?
-
12select * from sys.messageswhere severity > 20 and language_id = 1033
Troque o language_id para 1046 para ver as mensagens em português.
Nos vemos no próximos post sobre o assunto!
[…] você caiu aqui por acaso, sugiro antes dar uma olhada na parte 1 da série, onde eu trato de alguns detalhes no que diz respeito à forma que o SQL Server realiza o […]