¡Hola, chicos!
¿Todas las joyas?

Después de casi 15 días sin publicar debido a varios proyectos en los que estaba trabajando, encontré algo de tiempo para hacer esta publicación rápida sobre un error que encontré al agregar una columna DATETIME a una columna TIME. Este tipo de operación normalmente ocurría cuando el modo de compatibilidad de la base de datos estaba configurado en 100 (SQL), pero al cambiar el modo de compatibilidad a 110 (SQL 2012), 120 (SQL 2014) o superior, algunos trabajos que administro comenzaron a mostrar el siguiente mensaje de error:

Mensaje 402, Nivel 16, Estado 1, Línea 1
Los tipos de datos fecha, hora y hora son incompatibles en el operador de adición.

Simulando el error

Hay varias formas de simular, como crear una tabla con una columna de tipo DATETIME y otra de tipo TIME, pero creo que la prueba es más práctica si creamos el select manualmente, como en el siguiente script:

USE [Testes]
GO

PRINT 'Horário atual: ' + CONVERT(VARCHAR(19), GETDATE())

ALTER DATABASE Testes SET COMPATIBILITY_LEVEL = 100 -- SQL 2008
GO

PRINT GETDATE() + CAST('00:12:13' AS TIME)
GO

ALTER DATABASE Testes SET COMPATIBILITY_LEVEL = 110 -- SQL 2012
GO

PRINT GETDATE() + CAST('00:12:13' AS TIME)
GO

ALTER DATABASE Testes SET COMPATIBILITY_LEVEL = 120 -- SQL 2014
GO

PRINT GETDATE() + CAST('00:12:13' AS TIME)
GO

SQL Server - The data types datetime and time are incompatible in the add operator
SQL Server: los tipos de datos fecha, hora y hora son incompatibles en el operador agregar

¿Por qué ocurre este error?

Este error comenzó a ocurrir porque Microsoft realizó mejoras en el motor de base de datos a partir de SQL Server 2012, y la idea de realizar operaciones entre variables de diferentes tipos de datos sin una conversión explícita (dejar que la base de datos haga la conversión implícita) nunca es una buena idea.

Un ejemplo clásico de que esta práctica no debe usarse se puede ver cuando se trabaja con datos de tipo INT y FLOAT sin una conversión explícita:

SQL Server - The data types datetime and time are incompatible in the add operator 2
SQL Server: los tipos de datos fecha, hora y hora son incompatibles en el operador agregar 2

Según la definición universal de matemáticas, la forma en que SQL Server realiza este cálculo simple es INCORRECTA. Esto ocurre porque al dividir 1 entre 2, SQL Server hace la división considerando que los 2 números son enteros, y por lo tanto, el resultado también debe ser entero, provocando que 1/2 que es 0.5 se devuelva como 0 y luego se sume a 1.

Asegúrese siempre de que los tipos de datos involucrados sean compatibles con las operaciones realizadas:

SQL Server - The data types datetime and time are incompatible in the add operator 3
SQL Server: los tipos de datos fecha, hora y hora son incompatibles en el operador agregar 3

Realicé las mismas pruebas en Oracle Database y MySQL y ambos bancos pudieron realizar el cálculo correctamente, pues estos bancos ya realizan la conversión implícita de entero a flotante en casos de división y multiplicación, algo que SQL Server no hace. Por eso siempre recomiendo que el desarrollador de Query se encargue de pensar en este tipo de situaciones, y no dejes que el banco “piense” por ti.

He tenido experiencia personal y he visto lo desastrosos que pueden ser los informes de gestión que tienen este tipo de falla entre INT y FLOAT, especialmente en tasas e indicadores porcentuales.

Dicho esto, Microsoft ha estado tratando de reducir este tipo de malentendidos y ya no permite operaciones que involucran DATETIME y TIME usando operadores simples (+) y (-), solo con conversiones como CAST y CONVERT, donde puedes (y debes) definir el estilo de la conversión que se realizará, evitando la pérdida de precisión de los datos al convertir.

¿Cómo puedo sortear esta limitación y resolver el problema?

Bueno, ya encontré varias soluciones sorprendentes en Internet, varios tratamientos de cadenas y otras cosas que no tienen mucho rendimiento, cuando existe una solución tan simple y tonta para resolver esto, que es convertir la columna TIME a DATETIME:

SQL Server - The data types datetime and time are incompatible in the add operator solved
SQL Server: los tipos de datos fecha, hora y hora son incompatibles en el operador agregar resuelto

¡Eso es todo, amigos!
Gracias por visitarnos y nos vemos en el próximo post.