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

SQL Server – The data types datetime and time are incompatible in the add operator

Visualizações: 4.378 views
Tempo de Leitura: 3 minutos

Olá pessoal!
Tudo jóia ?

Depois de quase 15 dias sem postar em conta de vários trabalhos em que estava atuando, consegui um tempinho pra fazer esse post rápido pra vocês sobre um erro que encontrei ao somar uma coluna DATETIME com uma do tipo TIME. Esse tipo de operação ocorria normalmente quando o modo de compatibilidade do banco estava em 100 (SQL), mas ao alterar o modo de compatibilidade para 110 (SQL 2012), 120 (SQL 2014) ou superiores, alguns jobs que eu administro começaram a apresentar a seguinte mensagem de erro:

Msg 402, Level 16, State 1, Line 1
The data types datetime and time are incompatible in the add operator.

Simulando o erro

Existem várias formas de simular, como criando uma tabela com uma coluna do tipo DATETIME e outra do tipo TIME, mas acho que o teste fica mais prático se criarmos o select manualmente, como no script abaixo:

SQL Server - The data types datetime and time are incompatible in the add operator

Porque esse erro ocorre ?

Esse erro passou a ocorrer porque a Microsoft realizou melhorias na Engine dos databases a partir do SQL Server 2012, e a ideia de realizar operações entre variáveis de tipos de dados diferentes sem uma conversão explícita (deixando que o banco faça a conversão implícita) nunca é uma boa ideia.

Um exemplo clássico de que essa prática não deve ser utilizada pode ser visto ao trabalhar com dados do tipo INT e FLOAT sem uma conversão explícita:
SQL Server - The data types datetime and time are incompatible in the add operator 2

Pela definição universal da matemática, a forma como o SQL Server realiza essa conta simples está ERRADA. Isso ocorre porque na divisão de 1 por 2, o SQL Server faz a divisão considerando que os 2 números são inteiros, e por isso, o resultado também deve ser inteiro, fazendo com que 1/2, que é 0.5, seja retornado como 0 e depois somado 1.

Sempre garanta que os tipos de dados envolvidos são compatíveis com as operações realizadas:
SQL Server - The data types datetime and time are incompatible in the add operator 3

Fiz esse mesmo testes no Oracle Database e no MySQL e os dois bancos conseguiram realizar a conta corretamente, pois esses bancos já fazem a conversão implícita de inteiro para float em casos de divisão e multiplicação, coisa que o SQL Server não faz. Por este motivo, sempre recomendo que o desenvolvedor da Query se encarregue em pensar neste tipo de situação, e não deixe que o banco “pense” por você.

Já tive experiências pessoais e vi o quão desastroso podem ser relatórios gerenciais que tem esse tipo de falha entre INT e FLOAT, principalmente em taxas e indicadores percentuais.

Dito isso, a Microsoft vem tentando reduzir esse tipo de equívoco e não permite mais operações envolvendo DATETIME e TIME utilizando operadores simples (+) e (-), apenas com conversões como CAST e CONVERT, onde você pode (e deveria) definir o estilo da conversão que será realizada, evitando a perda de precisão dos dados quando convertidos.

Como contornar essa limitação e resolver o problema?

Pois bem, já encontrei diversas soluções mirabolantes na internet, vários tratamentos de strings e outras coisas não muito performáticas, quando se tem uma solução tão simples e boba para resolver isso, que é converter a coluna TIME para DATETIME:

SQL Server - The data types datetime and time are incompatible in the add operator solved

É isso aí, pessoal!
Obrigado pela visita e até o próximo post.