Clique no banner para conhecer e adquirir o meu treinamento de Bancos de Dados no Azure

SQL Server – Porque NÃO utilizar SET ANSI_WARNINGS OFF

Visualizações: 5.419 views
Tempo de Leitura: 6 minutos

Olá pessoal,
Boa noite! Tudo bem ?

Neste post vou comentar sobre um recurso utilizado por muitos desenvolvedores para “resolver” rapidamente alguns problemas comuns no desenvolvimento de queries Transact-SQL. Esse recurso é o SET ANSI_WARNINGS OFF.

Para que serve o comando SET ANSI_WARNINGS OFF?

A opção de controle de sessão ANSI_WARNINGS altera o comportamento do motor do SQL Server para algumas condições, que são:

  • Truncamento de strings (Tentar armazenar um texto de 10 caracteres num VARCHAR(9))
  • Divisão por ZERO
  • Valores NULL em funções de agregação (MAX, SUM, COUNT, etc)

O valor padrão é o ON, que irá apresentar o comportamento padrão ISO para esse tipo de situação, fazendo com que mensagens de erro sejam geradas nas duas primeiras situações e um alerta seja gerado na última situação.

Se você utilizar o comando SET ANSI_WARNINGS OFF, o engine do SQL Server vai reproduzir um comportamento fora do padrão e tentar executar o comando SELECT 10/0, ao invés de uma mensagem de erro, vai retornar NULL e exibir apenas um alerta, permitindo que suas rotinas retornem informações erradas e dados incorretos.

Por este motivo, alguns desenvolvedores SQL, querendo evitar que a aplicação retorne erro nessas situações acabam optando pelo modo mais fácil de “resolver” erros como os listados acima ao invés de realmente atuar no problema e resolvê-lo efetivamente. Isso geralmente ocorre nas empresas devido a diversos motivos, os quais destaco:

  • Falta de conhecimento técnico para identificar e corrigir o erro
  • Falta de vontade de efetivamente resolver o problema
  • Prazos muito apertados para entrega do software funcionando e sem erros

Msg 8134 Divide by zero error encountered

Erro comum no dia a dia dos desenvolvedores SQL, a clássica mensagem de divisão por zero é um indício que algum valor nos seus cálculos está errado. Esse é um erro aritmético básico e que causa uma exceção grave no SQL Server, fazendo com que o comando seja interrompido e a transação sofra um rollback automático. Esse é o comportamento padrão da engine do SQL Server, seguindo o padrão ISO.

O controle desse comportamento é feito em conjunto com o comando ARITHABORT. Quando o ANSI_WARNIGS está ativado, o ARITHABORT é ativado automaticamente, fazendo com que a engine funcione em seu modo padrão (ISO).

Quando o ANSI_WARNINGS está desativado, o ARITHABORT pode ser alterado para mudar o comportamento padrão do Engine. Se ARITHABORT está desativado, ao encontrar um erro de divisão por zero, o SQL Server irá ignorar o erro e continuar a execução normalmente, apenas exibindo um alerta na aba Messages.

Exemplo:

Como vimos no exemplo acima, o ANSI_WARNINGS OFF permite que contas de divisão por zero sejam executadas silenciosamente, gerando dados incorretos e sem que a equipe de desenvolvimento fique sabendo, uma vez que não será gerada nenhuma exceção na aplicação.

Retorno com SET ANSI_WARNINGS ON (Padrão):

Retorno com SET ANSI_WARNINGS OFF:

Msg 8152 String or binary data would be truncated

Essa mensagem de erro é muito comum entre os desenvolvedores SQL e com certeza vocês já devem ter visto enquanto criam suas queries, fazem integrações entre sistemas, etc. Essa mensagem ocorre quando você tenta armazenar uma quantidade de caracteres maior que o permitido em uma coluna.

O comportamento padrão do motor do SQL Server, seguindo o padrão ANSI, faz com que seja gerado uma exceção na execução do seu código Transact-SQL caso você
tenha um texto de 10 caracteres e tente inserir esse texto em uma coluna que permite só até 9 caracteres.

Quando você utiliza o comando SET ANSI_WARNINGS OFF, você faz com que o motor do SQL Server não gere mais esse erro na execução, fazendo com que o seu texto de 10 caracteres seja truncado e armazenado na coluna de 9 caracteres. Os caracteres excedentes serão silenciosamente descartados, ignorando e mascarando um problema na gravação dos dados do seu sistema, sem que ninguém fique sabendo.

Exemplo:

Retorno com SET ANSI_WARNINGS ON (Padrão):

Retorno com SET ANSI_WARNINGS OFF:

Null value is eliminated by an aggregate or other SET operation

Mensagem de alerta que ocorre quando é aplicada uma função de agregação (MAX, SUM, COUNT, AVG, etc) em um conjunto de dados e ao menos 1 registro possui um valor nulo (NULL).

Exemplo:

Retorno com SET ANSI_WARNINGS ON (Padrão):

Retorno com SET ANSI_WARNINGS OFF

Reparem que neste caso, se a opção ANSI_WARNINGS estiver desativada, você pode estar ignorando a existência de valores nulos no seu conjunto de resultados, o que podem indicar um possível problemas, uma vez que em determinadas situações, isso pode representar algum erro na sua query e que você está mascarando.

Caso você queira saber como remover o warning “Null value is eliminated by an aggregate or other SET operation” da forma correta, saiba mais acessando o post SQL Server – Warning: Null value is eliminated by an aggregate or other SET operation.

INSERT failed because the following SET options have incorrect settings: ‘ANSI_WARNINGS’

Mais um grave efeito colateral do uso do ANSI_WARNINGS OFF é o impacto que esse comando influi sobre views indexadas e índices criados em colunas calculadas, que muitas vezes são desenhados para ganho de performance, mas que a simples criação de um índice com o intuito de melhorar, acaba criando uma grande dor de cabeça para o DBA, uma vez que todas as rotinas que inserem dados em tabelas que possuem colunas calculados irão falhar após a criação do índice na coluna calculada.

Diferente dos erros anteriores, que podem causar dados incorretos e inconsistentes, esse exemplo impede que as rotinas funcionem de um modo geral, inclusive já acontecendo comigo, que criei um índice para otimizar uma query lenta na produção e começou a disparar alertas de erros em um dos módulos do sistema de onde trabalho.

Exemplo:

Retorno com SET ANSI_WARNINGS ON (Padrão):

Retorno com SET ANSI_WARNINGS OFF:

Msg 1934, Level 16, State 1, Line 12
CREATE INDEX failed because the following SET options have incorrect settings: ‘ANSI_WARNINGS’. Verify that SET options are correct for use with indexed views and/or indexes on computed columns and/or filtered indexes and/or query notifications and/or XML data type methods and/or spatial index operations.

É isso aí, pessoal!
Espero que tenham gostado do post e até a próxima.