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. */
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
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
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