Tratamento de erros do SQL Server e TRY CATCH
- 24-07-2022
- Toanngo92
- 0 Comments
Mục lục
Introduzir
O tratamento de erros no SQL Server agora é mais fácil por meio de várias técnicas.
O SQL Server introduziu opções para ajudar os usuários a controlar os erros com mais eficiência
Normalmente, o usuário final não conseguirá detectar o erro que aparece no lado do aplicativo.
Portanto, o SQL Server fornece uma instrução TRY … CATCH para controle de erros mais eficiente no back-end.
Algumas funções do sistema podem imprimir informações relevantes sobre o erro, facilitando a correção do erro.
Tipos de erros
Os programadores de T-SQL terão que estar cientes dos tipos de erros que ocorrem ao trabalhar com instruções do SQL Server. O primeiro passo é identificar o tipo de erro e, em seguida, descobrir como lidar com o erro.
Lista de tipos de erro
Erros de sintaxe
Erro de sintaxe é encontrado quando o código está sintaticamente incorreto, o SQL Server não consegue entender. Esses erros são detectados pelo SQL Server antes de iniciar a execução do bloco T-SQL ou do procedimento armazenado.
Quando o usuário digita as palavras-chave ou operações erradas porque não se lembra da sintaxe válida, o editor de código apontará isso.
Se o usuário esquecer de digitar uma palavra-chave ou for necessária uma ação para concluir o comando, o editor de código informará um erro quando o usuário executar o comando.
Erros de sintaxe (erros de sintaxe) serão facilmente identificáveis como o editor de código indicará, no entanto, se estiver usando um aplicativo de linha de comando, o erro só aparecerá depois que o usuário executar o comando.
Erros em tempo de execução
Um erro de tempo de execução ocorre quando um aplicativo tenta processar uma tarefa que não é suportada pelo SQL Server ou pelo sistema operacional.
Alguns erros de tempo de execução que podem ser encontrados são os seguintes:
- Manipular o cálculo da divisão por 0
- Tenta executar código que não está definido explicitamente. (O exemplo abaixo tem uma situação em que o valor é maior do que o tipo de dados pode representar).
Situações comuns em que são encontrados erros em tempo de execução:
- Use procedimento armazenado, função ou gatilho que não esteja disponível (excluído).
- Tentativa de processar uma tarefa que opera em um objeto ou variável que não pode ser processada (tabela excluída, não no banco de dados…)
- A situação de estouro de Ram (estouro de pilha) quando o aplicativo está sobrecarregado
- Tente lidar com tarefas com tipos de dados incompatíveis.
- Uso indevido de declarações condicionais.
Implemente o tratamento de erros
No processo de desenvolvimento de software, uma das coisas importantes é prestar atenção ao tratamento de erros. De certa forma, os usuários precisam cuidar do tratamento de exceções ao projetar o banco de dados. Diferentes mecanismos de processamento podem ser usados.
- Ao executar instruções DML como INSERT,DELETE,UPDAte, os usuários podem manipular erros para garantir a saída correta.
- Quando a transação falha e o usuário precisa reverter a transação, uma mensagem de erro apropriada deve ser exibida ao usuário.
- Ao trabalhar com cursores no SQL Server, os usuários podem lidar com erros para garantir resultados precisos.
TRY … bloco de comando CATCH
O bloco TRY … CATCH é usado para implementar o tratamento de exceções no Transact SQL. Uma ou mais instruções T-SQl são limitadas por um bloco TR. Se ocorrer um erro em um bloco TRY, o controle flui para um bloco catch, que pode conter uma ou mais instruções dentro do bloco CATCH.
Sintaxe:
BEGIN TRY {sql_statement | statement_block} END TRY BEGIN CATCH [ {sql_statement | statement_block}] END CATCH [;]
Por exemplo:
BEGIN TRY DECLARE @num int; SELECT @num=217/0; END TRY BEGIN CATCH PRINT 'Error occurred, unable to devide by 0' END CATCH;
Informações de erro
A melhor solução é exibir as informações do erro junto com o erro, para que possa ajudar a resolver o erro de forma rápida e eficiente.
Para isso, é necessário utilizar funções do sistema dentro do bloco CATCH para encontrar informações sobre o erro gerado quando o bloco é executado.
Lista de funções do sistema que fornecem informações de erro:
- ERROR_NUMBER() : retorna o número do erro.
- ERROR_SERVERITY() : retorna a gravidade
- ERROR_STATE(): retorna o número do status do erro.
- ERROR_PROCEDURE(): Retorna o nome do gatilho ou procedimento armazenado que causou o erro.
- ERROR_LINE(): retorna o número de linhas que causaram o erro
- ERROR_MESSAGE(): retorna o texto completo do erro, o texto conterá os valores fornecidos como parâmetros como nomes de objetos, comprimento.
Essas funções retornarão NULL se forem chamadas fora do bloco CATCH
Use TRY…CATCH com informações de erro
USE AdventureWorks2019; GO BEGIN TRY SELECT 217/0; END TRY BEGIN CATCH SELECT ERROR_NUMBER() AS ErrorNumer, ERROR_SEVERITY() AS ErrorSeverity, ERROR_LINE() AS ErrorLine, ERROR_MESSAGE() AS ErrorMessage; END CATCH; GO
O procedimento armazenado de exemplo contém funções de tratamento de erros:
USE AdventureWorks2019; GO IF OBJECT_ID ('sp_ErrorInfo','P') IS NOT NULL DROP PROCEDURE sp_ErrorInfo; GO CREATE PROCEDURE sp_ErrorInfo AS SELECT ERROR_NUMBER() AS ErrorNumber, ERROR_SEVERITY() AS ErrorSeverity, ERROR_STATE() AS ErrorState, ERROR_PROCEDURE() AS ErrorProcedure, ERROR_LINE() AS ErrorLine, ERROR_MESSAGE() AS ErrorMessage; GO BEGIN TRY SELECT 217/0 END TRY BEGIN CATCH EXEC sp_ErrorInfo; END CATCH
Usando TRY…CATCH na transação
USE AdventureWorks2019; GO BEGIN TRANSACTION; BEGIN TRY DELETE FROM Production.Product WHERE ProductID = 980; END TRY BEGIN CATCH SELECT ERROR_NUMBER() AS ErrorNumber, ERROR_SEVERITY() AS ErrorSeverity, ERROR_STATE() AS ErrorState, ERROR_PROCEDURE() AS ErrorProcedure, ERROR_LINE() AS ErrorLine, ERROR_MESSAGE() AS ErrorMessage; IF @@TRANCOUNT > 0 ROLLBACK TRANSACTION; END CATCH; IF @@TRANCOUNT > 0 COMMIT TRANSACTION; GO
Transação não confirmável
Se um erro for gerado a partir do bloco TRY, ele entrará em vigor e a transação será tratada como uma transação não confirmada. Uma transação uncomitable executa apenas uma ROLLBACK TRANSACTION ou operação de leitura.
A transação não executará nenhuma instrução Transact-SQL que execute confirmações de transação ou operações de gravação.
@@ERRO
A função @@ERROR retorna o número do erro da última instrução T-SQL executada.
Sintaxe:
@@ERROR
Por exemplo:
USE AdventureWorks2019; GO BEGIN TRY UPDATE HumanResources.EmployeePayHistory SET PayFrequency = 4 WHERE BusinessEntityID = 1; END TRY BEGIN CATCH IF @@ERROR = 547 PRINT N'Check constraint violation has occurred.'; END CATCH
RAISERROR
A instrução RAISERROR inicia o tratamento de erros para uma sessão e exibe a mensagem de erro.
RAISERROR pode fazer referência a mensagens definidas pelo usuário armazenadas na exibição do catálogo sys.message ou construir uma mensagem de erro dinâmica em tempo de execução.
Sintaxe:
RAISERROR ( {msg_id | msg_str | @local_variable} {,serverity , state} [,argument,[,...n]]) [WITH option [,...n]]
Lá:
- msg_id : especifica mensagens de erro definidas pelo usuário armazenadas na exibição do catálogo sys.messages usando sp_addmessage.
- msg_str : define mensagens de erro definidas pelo usuário com formatação. msg_str é uma string de caracteres com opções de conversão. Os parâmetros podem ser d,i,o,s,x,X,u semelhantes ao formato de string na função printf.
Lista de valores para opções personalizadas:
Valor | Descrição |
REGISTRO | Erros de log no banco de dados e logs de erros do aplicativo. |
AGORA | Envie notificações diretamente para o cliente |
SETERROR | Atribua o valor ERROR_NUMBER e @@ERROR a msg_id ou 5000, independentemente da gravidade |
Os seguintes erros serão retornados se RAISERROR for executado:
- Fora do escopo do bloco TRY
- Tem uma gravidade de 10 ou menos no bloco TRY
- Gravidade 20 ou superior, desconexão do banco de dados.
Exemplo usando RAISERROR() para imprimir um erro personalizado:
RAISERROR (N'This is an error message %s %d',10,1,N'serial number',23); GO
Exemplo usando RAISERROR em TRY CATCH:
BEGIN TRY RAISERROR('Raises Error in the TRY block',16,1); END TRY BEGIN CATCH DECLARE @ErrorMessage NVARCHAR(4000); DECLARE @ErrorSeverity INT; DECLARE @ErrorState INT; SELECT @ErrorMessage = ERROR_MESSAGE() , @ErrorSeverity = ERROR_SEVERITY(), @ErrorState = ERROR_STATE(); RAISERROR(@ErrorMessage,@ErrorSeverity,@ErrorState); END CATCH;
ERROR_SEVERITY
A função ERROR_SEVERITY retorna a gravidade do erro no bloco catch da estrutura TRY CATCH.
Esta função retornará null se chamada fora do bloco CATCH. ERROR _SEVERITY pode ser chamado em qualquer lugar dentro do escopo do bloco CATCH.
Em um bloco CATCH aninhado, ERROR_SEVERITY retornará um erro ao determinar o escopo do bloco catch ao qual ele se refere.
Sintaxe:
ERROR_SEVERITY()
Por exemplo:
BEGIN TRY SELECT 217/0; END TRY BEGIN CATCH SELECT ERROR_SEVERITY() AS ErrorSeverity; END CATCH; GO
ERROR_PROCEDURE
A função ERROR_PROCEDURE retorna o nome do gatilho ou procedimento armazenado em que o erro de uma construção TRY CATCH foi executado.
Sintaxe:
ERROR_PROCEDURE()
Ele retorna o tipo de dados nvarchar. Quando a função é chamada no bloco CATCH, ela retorna o nome do procedimento armazenado onde o erro foi encontrado.
ERROR_PROCEDURE pode ser chamado em qualquer lugar dentro do bloco CATCH.
Por exemplo:
USE AdventureWorks2019; GO IF OBJECT_ID ('usp_Example','P') IS NOT NULL DROP PROCEDURE usp_Example; GO CREATE PROCEDURE usp_Example AS SELECT 217/0; GO BEGIN TRY EXECUTE usp_Example; END TRY BEGIN CATCH SELECT ERROR_PROCEDURE() AS ErrorProcedure; END CATCH; GO
ERROR_NUMBER
A função ERROR_NUMBER chamada no bloco CATCH retorna o número de erros gerados pelo bloco CATCH quando a estrutura TRY >> CATCH é executada.
Sintaxe:
ERROR_NUMBER()
ERROR_NUMBER retorna o código de erro correspondente independentemente do número de execuções de erro (no caso de várias exceções em instruções diferentes) e executa dentro do escopo do bloco CATCH. Isso é diferente de @@ERROR porque ele retorna apenas o número do erro interno imediatamente após um erro, e o escopo está apenas na primeira instrução do bloco CATCH.
Por exemplo:
BEGIN TRY SELECT 217/0; SELECT 218/0; END TRY BEGIN CATCH SELECT ERROR_NUMBER() AS ErrorNumber; END CATCH; GO
MENSAGEM DE ERRO
A função ERROR_MESSAGE retorna a mensagem de texto do erro causado na estrutura na estrutura TRY CATCH.
Sintaxe:
ERROR_LINE()
Quando esta função é chamada em um bloco CATCH, ela retorna o texto completo da mensagem de erro que fez com que o bloco CATCH fosse executado.
O texto inclui os valores fornecidos para qualquer parâmetro que possa ser substituído, como nome do objeto, hora ou comprimento.
Por exemplo:
BEGIN TRY SELECT 200/0; END TRY BEGIN CATCH SELECT ERROR_MESSAGE() AS ErrorMessage; END CATCH; GO
ERROR_LINE
A função ERROR_LINE retorna o número de linhas com erros no bloco TRY CATCH.
Sintaxe:
ERROR_LINE()
Quando a função é chamada no bloco CATCH, ela retorna o número de linhas que encontraram o erro. Se um erro for encontrado dentro de um gatilho ou procedimento armazenado, ele retornará o número de linhas nesse gatilho ou procedimento armazenado. Semelhante a outras funções, esta função retorna NULL se for chamada fora do escopo do bloco CATCH.
Por exemplo:
BEGIN TRY SELECT 217/0; END TRY BEGIN CATCH SELECT ERROR_LINE() AS ErrorLine; END CATCH; GO
Erros que não são afetados pela construção TRY CATCH
O bloco TRY CATCH não capturará as seguintes condições:
- As informações da mensagem ou alerta têm gravidade 10 ou inferior.
- Um erro de gravidade 20 ou superior interrompe a tarefa de execução do Mecanismo de Banco de Dados do SQL Server para a sessão.
- Se o erro encontrado tiver uma gravidade de 20 ou superior e a conexão com o banco de dados não for interrompida, TRY CATCH tratará o erro.
- Aviso como uma conexão de cliente interrompida ou solicitações interrompidas.
- Quando a sessão termina com a instrução KILL, por meio do administrador do sistema.
Os seguintes tipos de erro que não são tratados por um bloco CATCH ocorrem no mesmo nível de execução da construção TRY CATCH:
- Erro de compilação como erro legal.
- Erros que surgem durante a compilação em nível de instrução, como erros de resolução de nome de objeto (o nome de objeto não existe) ocorrem após a compilação devido à resolução de nome atrasada.
Por exemplo:
USE AdventureWorks2109; GO BEGIN TRY SELECT * FROM Nonexistent; END TRY BEGIN CATCH SELECT ERROR_NUMBER() AS ErrorNumber, ERROR_MESSAGE() AS ErrorMessage; END CATCH
LANÇAR
A instrução THROW gera uma exceção e transfere o controle de execução para um bloco CATCH de uma estrutura TRY…CATCH.
Sintaxe:
THROW [{error_number | @local_varibale}, {message | @local_variable}, {state | @local_variable}] [;]
Por exemplo:
USE tempdb; GO CREATE TABLE dbo.TestRethrow (ID INT PRIMARY KEY); BEGIN TRY INSERT dbo.TestRethrow(ID) VALUES(1); INSERT dbo.TestRethrow(ID) VALUES(1); END TRY BEGIN CATCH PRINT 'In catch block.'; THROW END CATCH;
Ao usar THROW, mesmo que o comando falhe ao vincular, a instrução PRINT dentro do bloco CATCH ainda é impressa, que é a função de THROW no SQL Server.