Erro na hora de concatenar dados com variáveis diferentes

Olá pessoal,

No post de hoje vou compartilhar um problema que tive ao migrar o SQL Server 2008 R2 para o SQL Server 2014, a migração foi realizada com sucesso, mas mantive a compatibilidade dos bancos com SQL Server 2008 (100).

Na semana passada fiz o treinamento de SQL Server – Mastering the database engine, com o Luti (blog/twitter) a propósito recomendo o treinamento, e ele falou algo que me chamou a atenção que o novo cardinality estimate do SQL Server 2014 só funciona com as bases de dados com a compatibilidade SQL Server 2014 (120), fiz a alteração de uma base no servidor de homologação para testar, porém logo na alteração uma SP que é executada direto no servidor deu erro. “Msg 402, Level 16, State 1, Line 5 The data types datetime and time are incompatible in the add operator.”

Realizei um debug e o problema era na hora de concatenar dados, no exemplo abaixo vou mostrar o trecho da SP, ela funciona no SQL Server 2008, mas não funciona no SQL Server 2014.

-- Query executada em uma base com compatibilidade SQL server 2014 (120)  

DECLARE
    @Dt_Referencia DATETIME = '2016-05-12',
    @HR_REFERENCIA TIME = '09:47:01';

  SET @Dt_Referencia = CAST(FLOOR(CAST(@Dt_Referencia AS FLOAT)) AS DATETIME) 
      + ISNULL(@HR_REFERENCIA, '00:00:00');

  SELECT @Dt_Referencia

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

Errror_ao_concat_data_hora_Sql2014

Ao executar o mesmo comando em uma base com a compatibilidade SQL Server 2008 (100), o comando é executado sem erro.

 -- Query executada em uma base com compatibilidade SQL server 2008(100)  

ALTER DATABASE tempdb 
SET COMPATIBILITY_LEVEL = 100;
  
  DECLARE
    @Dt_Referencia DATETIME = '2016-05-12',
    @HR_REFERENCIA TIME = '09:47:01';

  SET @Dt_Referencia = CAST(FLOOR(CAST(@Dt_Referencia AS FLOAT)) AS DATETIME) 
      + ISNULL(@HR_REFERENCIA, '00:00:00');

  SELECT @Dt_Referencia

Sucesso_ao_concat_data_hora_Sql2008

Dei uma pesquisada pelo erro e encontrei a solução no blog do Pinal Dave (blog/twitter), ele não explicou o motivo do erro, mas postou a solução.

O que tem que ser feito é converter a variável do tipo TIME para DATETIME, por que a variável @Dt_Referencia é do tipo DATETIME, como eu disse, o porque no SQL Server 2008 ele faz a conversão dos dados e no SQL Server 2014 ele não faz eu não consigo explicar.

-- Comando executado com cast na variável @HR_REFERENCIA

 DECLARE
    @Dt_Referencia DATETIME = '2016-05-12',
    @HR_REFERENCIA TIME = '09:47:01';


  SET @Dt_Referencia = CAST(FLOOR(CAST(@Dt_Referencia AS FLOAT)) AS DATETIME)
      + CAST(ISNULL(@HR_REFERENCIA, '00:00:00') AS DATETIME);

  Select @Dt_Referencia

Sucesso_ao_concat_data_hora_Sql2014

Se alguém souber explicar o porque deste comportamento no SQL Server 2014, por favor deixe um comentário.

Bom pessoal por hoje é isso.

Abraços.

Tiago Neves

Deixe uma resposta