Tratamento de Excees. Parte 2

Essa a parte 2 de uma srie de 3 posts (ou 4, quem sabe), onde eu quero falar sobre as formas de realizar o tratamento de excees no SQL Server.

Se voc caiu aqui por acaso, sugiro antes dar uma olhada na parte 1 da srie, onde eutrato dealguns detalhes no que diz respeito forma que o SQL Server realiza o encerramento de processos, nos casos de erro.

Hoje irei falar sobre como realizar o tratamento de excees, via TRY / CATCH.

Estrutura:

Simples, no? 🙂
Oobjetivo: Fazer com que (quase) todo e qualquer erro de execuoque esteja dentro do TRY, seja direcionado para o CATCH (o “quase” porque isso acontece desde que a exceo tenha uma severidade maior que 10 ou queno aborte a conexo do usurio).
Caso o bloco em execuodentro do TRY no gere nenhuma exceo, o CATCH simplesmente no executado e o que existir aps o CATCH executado normalmente.
Se oCATCH a ltima linha sendo executada, o retorno vai para quem o chamou, seja uma procedure aninhada ou o prprio SSMS, por exemplo. Veja abaixo, como o CATCH no executado caso no ocorra erro na execuo:

Sem exceo…

Agora, deixe-me forar um erro de diviso por zero e veja o que acontece:

Agora sim, entrou no CATCH.
Agora sim, entrou no CATCH.

Repare que eu forceio mesmo erro duas vezes. A primeira, fora do TRY, para mostrar o erro que gerado, e a segunda, mostrando que o erro no exibido. Ao invs disso, gerado como resultado o que est dentro do CATCH. Note tambm que dentro do TRYexistia a execuo de 3 statements, porm apenas o primeiro PRINTfoi realizado.
No post anterior, eu comentei a respeito dos erros que podem ser tratados pelo usurio, onde o bloco continua a execuo do batch. Porm, quando o bloco estiver dentro de um TRY, assim que um erro surgir, o fluxo ser direcionado diretamente para o CATCH e os statements restantes sero ignorados. Veja:

Abortando todo o Batch
Abortando todo obloco do TRY

Caso voc queira que, no caso de uma exceo, nenhum registro inserido ou alterado seja commitado no banco, voc deve trabalhar com transaes:

Est faltando algo ainda…

Veja que, mesmo colocando o bloco dentro de uma transao, o registro com cdigo 2 foi inserido. Por que?

Se eu abrir uma nova conexo e tentar fazer um select simples, vou ficar com a janela travada, em lock, pois eu abri uma transao mas o commit no foi realizado, uma vez que a exceo foi gerada antes de chegar no commit (no vou entrar no mrito dos nveis de isolamento e hints aqui). Precisamos, portanto, colocar dentro do CATCH um ROLLBACK, para que a transao seja encerrada, os dados no sejam efetivadosno banco e um prximo select na tabela rode normalmente.
O CATCH deve ficar da seguinte forma:

Assim no preciso me preocuparcom locks, certo? , no bem assim.
Nem todo o bloco dentro do TRY estar sempre dentro de uma transao. Veja o que acontece se depois do COMMITeu forar um erro.

TryCatch5
Opa… ROLLBACK do que?

Ou seja, eu preciso, antes de fazer o ROLLBACK, validar se existe alguma transao no efetivada no banco para encerr-lo. Para isso,devo mudar o CATCH para:

Agora sim, como precisamos!
Agora sim, como precisamos!

Estamosquase chegando em um template para tratamento de excees, mas ainda est faltando uma coisa para encerrar esse post: Capturar o erro que est sendo executado.

No SQL Server existem algumas funes de erro que retornam todas as situaes j expostas (clique no link para acessar a referncia no BOL): nmero, severidade, estado, procedure, linha e mensagem:

Porm, imporante lembrar que estas funes retornam um valor apenas quando esto dentro do CATCH. Se executar diretamente, mesmo aps um erro, ser retornado nulo:

No ter retorno
Agora sim, com o erro.
Agora sim, com o erro.

Bom o que estar noselect, a regrade negcioque ditar as regras.

No prximo post, pretendo falar sobre o RAISERROR e o THROW. Suas diferenas e semelhanas.

Abrao!

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *

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