Aplicando Tratamento de Erros no Microsoft SQL Server 2012 e 2014 – Utilizando o Comando THROW.

Bom tarde, Comunidade e Amantes do Microsoft SQL Server.

Tudo bem? No último mês de Abril a Microsoft lançou a última versão do Microsoft SQL Server, conhecida como 2014, que internamente é tratada como versão de número 12. Mas ainda estou focado em evoluir o meu conhecimento e experiência na versão 2012, que particularmente foi que mais apresentou evolução e melhorias consideráveis desde a versão 2000.

Por isso, nos últimos dias, estava estudando um mais sobre Tratamento de Erros e Exceções no SQL Server, e tive a oportunidade de utilizar e aplicar o comando THROW, introduzido a partir da versão 2012. Por isso, decidi compartilhar com vocês um pouco mais sobre este comando, destacar algumas diferenças em relação a alternativas como o comando RAISERROR, existente desde a versão 2000 do Microsoft SQL Server.

Como de costume, vou realizar uma pequena Introdução sobre este comando, sua forma de uso, uma comparação básica em relação ao comando RAISERROR e alguns exemplos de utilização do comando THROW.

 

Introdução

Implementado a partir da versão 2012 do Microsoft SQL Server, lançado em 2012, a instrução ou comando THROW possibilita ser utilizada como uma funcionalidade que permite ao profissional que esta trabalhando com Banco de Dados, mais especificamente com a linguagem Transact-SQL no desenvolvimento dos seus recursos, aplicarem uma nova técnica de tratamento de erros e controle de exceções.

O comando THROW, não pode ser considerado somente uma melhoria em relação ás formas de identificação e tratamento de erros, o mesmo apresenta comportamentos e características similares ao RAISERROR e @@ERROR, onde o SQL Server retorna possíveis sintomas que representam um erro no processamento da transação.

Mas a sua principal diferença em relação a estas antigas funcionalidades é a possibilidade do comando THROW, apresentar uma mensagem de erro de forma personalizada, como também, que erros oriundos do SQL Server possam ser retornados na aplicação do usuário de forma amigável.

 

Comportamento

A partir do momento que utilizamos o comando THROW, o SQL Server trabalha de uma forma mais versátil não obrigando a necessidade que a mensagem de erro que será apresentada ou retornada esteja necessariamente cadastradas na System Table Sys.Messages.

 

Além disso, uma das obrigatoriedades do comando THROW é que o código de erro que será apresentando deva ser superior a 50000, suas exceções geradas durante a identificação do erro são internamente identificadas com o nível de gravidade de número 16, o que representa e informa para o SQL Server que se trata de um erro de sintaxe ou instrução escrita incorretamente.

 

Considerações

A instrução antes do comando THROW deve ser seguido o terminador de instrução com o uso do sinal de ponto e vírgula (;).

 

Quando o comando THROW for utilizado sem a passagem de argumento ou parâmetro, o mesmo deve ser declarado de forma obrigatória dentro de um bloco CATCH.

 

Caso não exista ou não seja identificado à declaração de um bloco TRY…CATCH a instrução de processamento do comando THROW ou sua sessão será encerrada.

 

Dependência

A partir do Microsoft SQL Server 2005 introduziu o TRY… CATCH para tratar de forma eficaz os erros dentro de uma instrução ou transação T-SQL. Usando um bloco CATCH podemos facilmente escrever o erro manipulação que será executado sempre que ocorrer um problema dentro de um bloco TRY. Por isso o comando THROW também se faz dependente de um bloco TRY…CATCH para lançar e apresentar uma exceção ou erro ao usuário.

 

Sintaxe

O comando THROW, apresenta uma sintaxe de uso muito simples:

 

Sintaxe: THROW erro número, mensagem, estado

 

Argumentos e Parâmetros:

 

  • Número de erro: Valor do tipo inteiro declarado ou passado através de variáveis, constantes ou qualquer outra forma.  Seu valor deve ser do tipo inteiro, maior ou igual a 50000 e menor ou igual ao valor máximo de INT 2147483647.
  •  Mensagem: Este é um valor do tipo string que representa a descrição da exceção. Seu tipo de dados deve ser NVARCHAR, com tamanho máximo de 2048 caracteres.
  • Estado: Valor do tipo Tinyint, declarado entre 0 e 255, obtido através de variáveis, constantes ou qualquer outra forma. Identifica associado à mensagem de erro.

 

Comparativo com o comando RAISERROR

Como toda e qualquer nova funcionalidade, sempre existe alguns cenários ou até mesmo pequenas restrições na utilização de uma novidade. Isso é muito comum, ainda mais quando falamos de um comando ou instrução que possa mudar ou gerar impactos em procedimentos, processos e sistemas que estão em uso a algum tipo.

 

O comando THROW também não fica fora deste cenário, ao contrário o mesmo foi fortemente comparado com o comando RAISERROR em muitos casos até mesmo questionado se a sua implementação seria realmente lançada na versão final do Microsoft SQL Server 2012 e posteriormente mantida. O que normalmente não é adotado pelo Microsoft, lançar um recurso em uma vez e posteriormente remover o mesmo. Basicamente os comandos THROW e RAISERROR apresentam quatro diferenças em sua forma de uso, destacadas na Tabela 1 abaixo:

 

RAISERROR THROW
O valor declarado no argumento msg_id, deve existir obrigatoriamente na System Table Sys.Messages. O valor informado no parâmetro error_number, não precisa existir na System Table Sys.Messages.
O parâmetro msg_str pode conter estilos de formatação printf. O parâmetro message não aceita formatação de estilo printf. Para isso é necessário utilizar a Função FORMATMESSAGE, introduzida também no Microsoft SQL Server 2012.
O parâmetro severity especifica a severidade da exceção. Não existe um argumento ou parâmetro que informa o nível de severidade da exceção ou erro, todo e qualquer transação que o comando THROW faça parte terá o nível número aplicado 16.
Parâmetro Option que permite uma forma personalizada para o registro ou apresentação do erro. Além disso, possibilita que esta exceção ou erro seja registro nos logs do mecanismo de banco de dados. O comando THROW lança a exceção capturada e permite que a mesma seja armazenada internamente em tabelas, mas não envia ou registra o erro em logs do mecanismos de banco de dados.

Tabela 1 – Diferenças entre os comandos RAISERROR e THROW.

 

Perfeito, agora que já conhecemos um pouco mais sobre o comando THROW, podemos trabalhar com alguns exemplos e formas de utilização, você vai poder observar um exemplo que apresenta a forma de uso do comando THROW em comparação com o comando RAISERROR. Então vamos em frente e como diária o poeta “Siga-me os bons…”

 

Formas de Uso

— Exemplo 1 – Lançamento de Exceção sem Try…Catch —

 

THROW 62000, ‘Nova exceção lançada pelo comando THROW.’,2;

THROW

Figura 1 – Mensagem apresentada pelo comando THROW.

 

— Exemplo 2 – Lançando uma Exceção de Erro na divisão de valores por Zero —

Use TempDB

GO

 

CREATE TABLE ErrorHistory

(ErrorTime   DATETIME,

ErrorSeverityLevel VARCHAR(100),

ErrorMessage   VARCHAR(1000))

GO

 

BEGIN TRY

DECLARE @TryDivision int = 10/0

END TRY

BEGIN CATCH

 

INSERT INTO ErrorHistory VALUES(GETDATE(), ERROR_SEVERITY(), ERROR_MESSAGE());

 

THROW 60000,’Erro de Divisão por Zero’,1;

 

END CATCH

GO

 

SELECT * FROM ErrorHistory

GO

THROW2
Figura 2 – Exceção lançada pelo comando THROW armazenada na tabela ErrorHistory.

 

Neste exemplo, realizamos a criação de uma simples tabela chamada de ErrorHistory, que possui a função de armazenar e catalogar as mensagens de erro ou exceções capturadas dentro do bloco CATCH.

 

Você pode observar que ao executar este bloco de código a mensagem de erro apresentando pelo THROW esta em Português, conforme apresenta a Figura 3, mas a mensagem de erro armazenada na tabela esta em inglês, isso já nos permite entender e observar como o THROW pode ser personalizável.

THROW3
Figura 3 – Mensagem personalizada retornada pelo comando THROW.

 

— Exemplo 3 – Lançando uma Exceção – Violação de Chave Primária —

CREATE TABLE dbo.TestComandoTHROW

(ID INT PRIMARY KEY)

 

BEGIN TRY

INSERT dbo. TestComandoTHROW (ID) VALUES(1);

 

— Forçando a ocorrência do erro 2627, violação de chave primária –

INSERT dbo. TestComandoTHROW (ID) VALUES(1);

END TRY

BEGIN CATCH

 

THROW;

END CATCH;

 

Observe que o comando THROW mesmo declarado de forma simples dentro de um bloco CATCH lança a exceção e devolve o controle para o Mecanismo que banco de dados, mas especificamente para sessão que esta processando a transação.

Figura 4 – Mensagem de erro retornada pelo comando THROW.

 

— Exemplo 4 – Utilizando o Comando THROW e Comando RAISERROR —

— Bloco – Comando THROW —

BEGIN TRY

DECLARE @TryDivision int = 10/0

END TRY

BEGIN CATCH

 

THROW 60000,’Erro de Divisão por Zero’,1;

 

END CATCH

GO

— Bloco – Comando RAISERROR —

BEGIN TRY

DECLARE @TryDivision int = 10/0

END TRY

BEGIN CATCH

 

DECLARE @ErrorMessage NVARCHAR(2048),

@ErrorSeverity INT,

@ErrorState INT

 

SELECT @ErrorMessage =ERROR_MESSAGE(),

@ErrorSeverity =ERROR_SEVERITY(),

@ErrorState =ERROR_STATE()

 

RAISERROR (@ErrorMessage, @ErrorSeverity,@ErrorState)

 

END CATCH

GO

 

Neste último exemplo, estou realizando o mesmo procedimento de divisão de um simples valor inteiro por zero, e aplicando o tratamento de erro com os comandos THROW e RAISERROR, note que no primeiro bloco, estamos fazendo a captura e lançamento da exceção sem precisar capturar o código de erro, armazená-lo e posteriormente apresentar, totalmente ao contrário do que é necessário ser feito para o RAISERROR poder tratar e apresentar o erro e a mensagem.

Desta maneira, neste cenário o comando THROW acaba sendo de forma simples, mais prática e inteligente para seu uso.

Conclusão

Não é fácil destacar e apresentar uma nova funcionalidade do SQL Server, ainda mais estas que somente colocando a mão na massa, como é o caso do comando THROW, pode ser realmente ser perceptível, mas acredito que consegui apresentar de forma clara e simples como podemos fazer uso deste novo recurso, principalmente para os Profissionais que trabalham na área de desenvolvimento e á algum tempo já estavam solicitando este tipo de implementação.

Como foi apresentado o comando THROW, em alguns cenários pode ser considerado mais simples e de fácil utilização, sem requerer que sejam utilizados recursos de sistema do SQL Server, como o comando RAISERROR.

Muito comparado e questionado, o comando THROW, veio para ocupar um espaço que sempre existiu no SQL Server desde a versão 2000, que foi melhorado na versão 2005 com o bloco Try…Catch e agora fortalecido, que é justamente o conceito de tratamento de erros e exceções. Eu mesmo durante muito tempo preferia utilizar o comando RAISERROR e até mesma a variável de sistema @@ERROR do que os blocos Try…Catch, por costume e vício, mas nos últimos tempos a partir do momento em que alguns cenários e necessidade se apresentaram o uso das Funções de erro, como por exemplo: Error_State(), Error_Severity() e Error_Message() ficaram tão presentes no meio dia á dia que também, senti um pouco de restrição em usar o THROW.

Algo que não aconteceu com o THROW, pois em uma linha de código conseguimos de forma elegante capturar, tratar e até mesmo personalizar um erro, deixando nossa aplicação, stored procedure e transação mais intuitiva e amigável.

Sou um grande fã desta funcionalidade que a meu ver nas próximas versões do SQL Server, neste caso, se referindo a versões pós SQL Server 2014, tende a crescer muito e ser adotada de forma concreta.

——————————————————————————————————————————-

Agradeço a sua visita, espero que você tenha gostado e que este conteúdo possa te ajudar.

Um grande abraço.

Nos encontramos em breve.

Até mais.

THROW4

Autor: Junior Galvão - MVP

Profissional com vasta experiência na área de Tecnologia da Informação e soluções Microsoft. Graduado no Curso Superior em Gestão da Tecnologia de Sistemas de Informação pela Uninove - Campus São Roque. Pós-Graduado no Curso de Gestão e Engenharia de Processos para Desenvolvimento de Software com RUP na Faculdade FIAP - Faculdade de Informática e Administração Paulista de São Paulo. Pós-Graduado em Gestão da Tecnologia da Informação Faculdade - ESAMC Sorocaba. Cursando Mestrado em Ciências da Computação - UFSCar - Campus - Sorocaba. Formação MCDBA Microsoft, autor de artigos acadêmicos e profissionais postados em Revistas, Instituições de Ensino e WebSistes. Meu primeiro contato com tecnologia ocorreu em 1995 após meus pais comprarem nosso primeiro computador, ano em que as portas para este fantástico mundo se abriram. Neste mesmo ano, comecei o de Processamento de Dados, naquele momento a palavra TI não existia, na verdade a Tecnologia da Informação era conhecida como Computação ou Informática, foi assim que tudo começou e desde então não parei mais, continuando nesta longa estrada até hoje. Desde 2001 tenho atuado como Database Administrator - Administrador de Banco de Dados - SQL Server em tarefas de Administração, Gerenciamento, Migração de Servidores e Bancos de Dados, Estratégias de Backup/Restauração, Replicação, LogShipping, Implantação de ERPs que utilizam bancos SQL Server, Desenvolvimento de Funções, Stored Procedure, Triggers. Experiência na Coordenação de Projetos de Alta Disponibilidade de Dados, utilizando Database Mirroring, Replicação Transacional e Merge, Log Shipping, para versões: 2000, 2005, 2008, 2008 R2, 2012 e 2014. Atualmente trabalho como Administrador de Banco de Dados no FIT - Instituto de Tecnologia da Flextronics, como também, Consultor em Projetos de Tunnig e Performance para clientes. Desde 2008 exerço a função de Professor Universitário, para as disciplinas de Banco de Dados, Administração, Modelagem de Banco de Dados, Programação em Banco de Dados, Sistemas Operacionais, Análise e Projetos de Sistemas, entre outras. Possuo titulação Oficial Microsoft MVP - SQL Server renovada desde 2007.

Deixe uma resposta

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s