sexta-feira, dezembro 06, 2013

Tratamento de erros no SQL Server

Desde que comecei a trabalhar também com o SQL Server, sempre senti saudades da forma como o Oracle trata exceções (muito parecido com o Java/C# onde se pode ir encadeando os tipos de exceção e tal - ok, isso pode ser feito no SQL Server, mas de forma fedorenta usando um CASE WHEN!.

Eu estou deixando aqui postado um exemplo de como tratar erros.

Ao executar esse script irá ser lançada uma exceção indicando que se está tentando inserir um registro com informações além da capacidade do campo (o campo Name foi criado de propósito para dar erro com apenas 20 caracteres de comprimento).

Quando a exceção for lançada, as inserções serão desfeitas (rollback) e será apresentada uma mensagem de erro formatada com o código e a mensagem do erro além do indicativo da linha onde ele ocorreu.

Se você alterar a declaração do campo Name para VARCHAR(100), por exemplo, e executar novamente o script a tabela será recriada, os registros todos inseridos e depois selecionados e exibidos.

--| Se a tabela Driver já existir na base, será deletada e recriada           |--
IF OBJECT_ID('dbo.DRIVER', 'U') IS NOT NULL
  DROP TABLE DRIVER
 
CREATE TABLE DRIVER (
  ID   INT         NOT NULL IDENTITY,
  NAME VARCHAR(20) NOT NULL
)
 
--| Inicia uma transação                                                      |--
BEGIN TRAN
 
--| Inicia um bloco try                                                       |--
BEGIN TRY
  
  --| Vai inserir na tabela uma lista de caras que "dirigem" muito            |--
  INSERT INTO Driver (Name) VALUES ('Jean J. Michel') --| Esse é o melhor! ;) |--
  INSERT INTO Driver (Name) VALUES ('Alain Prost')
  INSERT INTO Driver (Name) VALUES ('Alberto Ascari')
  INSERT INTO Driver (Name) VALUES ('Ayrton Senna da Silva')
  INSERT INTO Driver (Name) VALUES ('Damon Hill')
  INSERT INTO Driver (Name) VALUES ('Emerson Fittipaldi')
  INSERT INTO Driver (Name) VALUES ('Graham Hill')
  INSERT INTO Driver (Name) VALUES ('Nigel Mansell')
  INSERT INTO Driver (Name) VALUES ('Jack Brabham')
  INSERT INTO Driver (Name) VALUES ('Jackie Stewart')
  INSERT INTO Driver (Name) VALUES ('Juan Manuel Fangio')
  INSERT INTO Driver (Name) VALUES ('Nelson Piquet')
  INSERT INTO Driver (Name) VALUES ('Niki Lauda')
  
  --| Encerra a transação confirmando as inserções (inserts) feitas           |--
  COMMIT TRAN
  
  --| Seleciona todos os registros inseridos                                  |--
  SELECT Id, Name FROM Driver
  
--| Finaliza o bloco try. Se a execução chegou até aqui não passará pelo      |--
--| bloco catch, pois tudo ocorreu corretamente não lançando exceções         |--
END TRY
--| Se acontecer qualquer erro a execução passará da linha aonde o erro o-    |--
--| correu para a primeira linha deste bloco. Onde deverá ser tratado         |--
BEGIN CATCH
  --| Seleciona e exibe o que aconteceu durante a execução, qual a exceção    |--
  --| lançada e em que linha                                                  |--
  SELECT 'Erro: ' +
         CAST(ERROR_NUMBER() AS VARCHAR(MAX)) + '-'+
         ERROR_MESSAGE() + ' Na linha ' +
         CAST(ERROR_LINE() AS VARCHAR(MAX)) + '.'
  
  --| Encerra a transação desfazendo todas as inserções feitas no bloco try   |--
  ROLLBACK TRAN
  
--| Finaliza o bloco catch                                                    |--
END CATCH

Era isso, mais um postzinho básico, rápido e indolor para manter a atividade do blog ;)