Implementar o tratamento de SQL T

Concluído

Um erro indica um problema ou um problema notável que surge durante uma operação de banco de dados. Erros podem ser gerados pelo Mecanismo de Banco de Dados do SQL Server em resposta a um evento ou falha no nível do sistema; ou você pode gerar erros de aplicativo em seu código Transact-SQL.

Elementos de erros do mecanismo de banco de dados

Seja qual for a causa, cada erro é composto pelos seguintes elementos:

  • Número de erro – número exclusivo que identifica o erro específico.
  • Mensagem de erro – Texto que descreve o erro.
  • Gravidade – Indicação numérica de gravidade de 1 a 25.
  • Estado – Código de estado interno para a condição do mecanismo de banco de dados.
  • Procedimento – o nome do procedimento armazenado ou gatilho no qual o erro ocorreu.
  • Número de linha – qual instrução no lote ou procedimento gerou o erro.

Erros do sistema

Os erros do sistema são predefinidos, e você pode visualizá-los na visão de sistema sys.messages. Quando ocorre um erro do sistema, o SQL Server pode executar uma ação corretiva automática, dependendo da gravidade do erro. Por exemplo, quando ocorre um erro de alta gravidade, o SQL Server pode deixar um banco de dados offline ou até mesmo parar o serviço do mecanismo de banco de dados.

Erros personalizados

Você pode gerar erros no código Transact-SQL para responder a condições específicas do aplicativo ou para personalizar as informações enviadas a aplicativos cliente em resposta a erros do sistema. Esses erros de aplicativo podem ser definidos diretamente quando são gerados, ou você pode predefini-los na tabela sys.messages, além dos erros fornecidos pelo sistema. Os números de erro usados para erros personalizados devem ser 50001 ou superior.

Para adicionar uma mensagem de erro personalizada a sys.messages, use sp_addmessage. O usuário da mensagem deve ser membro das funções de servidor fixas sysadmin ou serveradmin.

Esta é a sintaxe sp_addmessage:

sp_addmessage [ @msgnum= ] msg_id , [ @severity= ] severity , [ @msgtext= ] 'msg' 
     [ , [ @lang= ] 'language' ] 
     [ , [ @with_log= ] { 'TRUE' | 'FALSE' } ] 
     [ , [ @replace= ] 'replace' ]

Aqui está um exemplo de uma mensagem de erro personalizada usando esta sintaxe:

sp_addmessage 50001, 10, N’Unexpected value entered’;

Observação

sp_addmessageé compatível apenas com SQL Server. Em Banco de Dados SQL do Azure e Instância Gerenciada de SQL do Azure, sp_addmessage não há suporte, portanto, você não pode referenciar um msg_id maior que 50000. Nessas plataformas, use embutido RAISERROR com uma cadeia de caracteres de mensagem ou THROW combinado com FORMATMESSAGE(), em vez disso.

Além disso, você pode definir mensagens de erro personalizadas, os membros da função de servidor sysadmin também podem usar um parâmetro adicional, @with_log. Quando definido como TRUE, o erro também será registrado no log de aplicativos do Windows. Qualquer mensagem gravada no log de aplicativos do Windows também é gravada no log de erros do SQL Server. Seja criterioso ao usar a opção @with_log porque administradores de rede e de sistema tendem a não gostar de aplicativos que são "tagarela" nos logs do sistema. No entanto, se o erro precisar ser interceptado por um alerta, o erro deverá primeiro ser gravado no registro de aplicativos do Windows.

Observação

Não há suporte para geração de erros do sistema.

As mensagens podem ser substituídas sem excluí-las primeiro usando a opção @replace = 'replace'.

As mensagens são personalizáveis e diferentes podem ser adicionadas para o mesmo número de erro em vários idiomas, com base no valor do identificador de idioma (language_id).

Observação

As mensagens em inglês são language_id 1033.

Levantar erros usando RAISERROR

Observação

RAISERROR é preterido para novo desenvolvimento. Use THROW para o novo código T-SQL. RAISERROR permanece útil para código herdado, para elevar os níveis de severidade acima de 16 (o que THROW não pode fazer diretamente) e para printfformatação de mensagem dinâmica de estilo (a alternativa moderna é FORMATMESSAGE() combinada com THROW).

Ambos PRINT e RAISERROR podem ser usados para retornar informações ou mensagens de aviso para aplicativos. RAISERROR permite que os aplicativos gerem um erro que pode ser capturado pelo processo de chamada.

RAISERROR

A capacidade de gerar erros no T-SQL facilita o tratamento de erros no aplicativo, pois ele é enviado como qualquer outro erro do sistema. RAISERROR é usado para:

  • Ajude a solucionar problemas de código T-SQL.
  • Verifique os valores dos dados.
  • Retornar mensagens que contêm texto variável.

Observação

Usar uma PRINT instrução é semelhante a gerar um erro de gravidade 10.

Aqui está um exemplo de uma mensagem de erro personalizada usando RAISERROR.

RAISERROR (N'%s %d', -- Message text,
    10, -- Severity,
    1, -- State,
    N'Custom error message number',
    2)

Quando disparado, ele retorna:

Custom error message number 2

No exemplo anterior, %d é um espaço reservado para um número e %s é um espaço reservado para uma cadeia de caracteres. Além disso, você deve observar que um número de mensagem não foi mencionado. Quando erros com cadeias de caracteres de mensagem são gerados usando essa sintaxe, eles sempre têm o número de erro 50000.

Levantar erros usando THROW

A THROW instrução oferece um método mais simples de gerar erros no código e é a abordagem recomendada para o novo desenvolvimento T-SQL. Os erros devem ter um número de erro de pelo menos 50000.

THROW

THROW difere de RAISERROR várias maneiras:

  • Quando THROW gera uma nova exceção, a gravidade é sempre 16. Quando THROW é usado para reexame uma exceção existente (sem THROW parâmetros dentro de um CATCH bloco), a severidade da exceção original é preservada; é por isso que sem THROW parâmetros é preferível para o crescimento de erros do sistema de um CATCH bloco.
  • As mensagens retornadas por THROW não estão relacionadas a entradas em sys.messages.
  • THROW honras SET XACT_ABORT. Quando SET XACT_ABORT ON estiver ativo, uma exceção gerada pela THROW transação atual será revertida automaticamente. RAISERROR não respeita SET XACT_ABORT— essa é uma das principais razões THROW para o novo desenvolvimento.

Importante

A instrução imediatamente antes THROW deve terminar com um ponto-e-vírgula (;), caso contrário, você receberá um erro de sintaxe. Esse é um obstáculo comum ao adotar THROW no código existente que omite ponto-e-vírgula.

; THROW 50001, 'An error occurred', 1;

Capturar códigos de erro usando @@Error

A maioria dos códigos de tratamento de erros tradicionais em aplicativos SQL Server foi criada usando @@ERROR. A manipulação de exceções estruturadas fornece uma alternativa mais poderosa ao uso @@ERROR e é a abordagem recomendada para o novo código T-SQL. Será discutido na próxima lição. Uma grande quantidade de código de tratamento de erros de SQL Server existente é baseada @@ERRORem, portanto, é importante entender como trabalhar com ele.

@@ERROR

@@ERROR é uma variável do sistema que contém o número de erro do último erro que ocorreu. Um desafio significativo é @@ERROR que o valor que ele mantém é rapidamente redefinido à medida que cada instrução adicional é executada.

Por exemplo, considere o seguinte código:

RAISERROR(N'Message', 16, 1);
IF @@ERROR <> 0
PRINT 'Error=' + CAST(@@ERROR AS VARCHAR(8));
GO

Você pode esperar que, quando o código for executado, ele retorne o número de erro em uma cadeia de caracteres impressa. No entanto, quando o código é executado, ele retorna:

Msg 50000, Level 16, State 1, Line 1
Message
Error=0

O erro foi gerado, mas a mensagem impressa foi "Error=0". Na primeira linha da saída, você pode ver que o erro, conforme o esperado, era, na verdade, 50000, com uma mensagem passada para RAISERROR. Isso ocorre porque a instrução IF que segue a RAISERROR instrução foi executada com êxito e fez com que o @@ERROR valor fosse redefinido. Por esse motivo, ao trabalhar com @@ERROR, é importante capturar o número de erro em uma variável assim que ele for gerado e, em seguida, continuar o processamento com a variável.

Examine o seguinte código que demonstra isso:

DECLARE @ErrorValue int;
RAISERROR(N'Message', 16, 1);
SET @ErrorValue = @@ERROR;
IF @ErrorValue <> 0
PRINT 'Error=' + CAST(@ErrorValue AS VARCHAR(8));

Quando esse código é executado, ele retorna a seguinte saída:

Msg 50000, Level 16, State 1, Line 2
Message
Error=50000

O número de erro é relatado corretamente agora.

Centralizando o tratamento de erros

Outro problema significativo com o uso @@ERROR para tratamento de erros é que é difícil centralizar dentro do código T-SQL. O tratamento de erros tende a acabar espalhado por todo o código. Seria possível centralizar o tratamento de erros usando @@ERROR até certo ponto, usando rótulos e GOTO instruções. No entanto, isso seria desaprovado pela maioria dos desenvolvedores hoje como uma prática de codificação ruim.

Criar alertas de erro

Para determinadas categorias de erros, os administradores podem criar alertas do SQL Server, pois desejam ser notificados assim que eles ocorrerem. Isso pode até se aplicar a mensagens de erro definidas pelo usuário. Por exemplo, talvez você queira gerar um alerta sempre que um log de transações for preenchido. O alerta geralmente é usado para trazer erros de alta gravidade (como severidade 19 ou superior) para a atenção dos administradores.

Levantando alertas

Alertas podem ser criados para mensagens de erro específicas. O serviço de alerta funciona registrando-se como um serviço de retorno de chamada no serviço de registro de eventos. Isso significa que os alertas só funcionam em erros registrados.

Há duas maneiras de fazer um erro gerar um alerta: você pode usar a opção WITH LOG ao gerar o erro ou a mensagem pode ser alterada para torná-la registrada em log executando sp_altermessage. A opção WITH LOG afeta apenas a instrução atual. Usar sp_altermessage altera o comportamento de erro para todo o uso futuro.