Con la llegada de SQL Server 2008 llegan 4 nuevos tipos de datos para almacenamiento de fecha y hora.
- DATE: Este nuevo tipo de dato almacena únicamente fechas y cumple con el tipo de fecha estándar ANSI.
- TIME: Complementariamente al anterior, almacena únicamente horas y cumple con el tipo de hora estándar ANSI.
- DATETIMEOFFSET: Este nuevo tipo de dato gestiona la fecha y la hora teniendo en cuenta zonas horarias.
- DATETIME2: Este nuevo tipo lo podemos ver como una nueva versión mejorada del tipo DATETIME. Nos permite mayores rangos de fechas así como precisión variable.
Para los tres tipos nuevos que almacenan hora (TIME, DATETIMEOFFSET y DATETIME2) la precisión máxima pasa de 0.333 segundos a 100 nanosegundos lo cual nos permitirá utilizar estos tipos de datos en escenarios donde anteriormente no era viable por su poca precisión. Además éstos permiten ajustar la precisión de forma que podemos ahorrar espacio de almacenamiento a cambio de precisión. La precisión la indicaremos entre paréntesis detrás del tipo de dato y representa el número de posiciones decimales. Si no la especificamos se asignará la máxima precisión lo cual puede ser excesivo en muchos escenarios.
La siguiente tabla nos muestra los rangos mínimos y máximos y su tamaño para los nuevos tipos de datos:
Tipo de datos
|
Mínimo
|
Máximo
|
Tamaño
|
DATE |
01-01-0001
|
31-12-9999
|
3 bytes
|
TIME
|
00:00:00.0000000
|
23:59:59.9999999
|
3 a 5 bytes
|
DATETIMEOFFSET
|
01-01-0001 00:00:00.0000000
|
31-12-9999 23:59:59.9999999
|
8 a 10 bytes
|
DATETIME2
|
01-01-0001 00:00:00.0000000
|
31-12-9999 23:59:59.9999999 |
6 a 8 bytes
|
La mayoría nos hemos encontrado en situaciones en las cuales es necesario trabajar únicamente con fechas o con horas independientemente. Para cada caso nuestra mejor alternativa hasta SQL Server 2008 era utilizar el tipo de datos datetime o smalldatetime e ignorar o bien la fecha o bien la hora. Obviamente esto tenía inconvenientes como un mayor consumo de memoria y menor eficiencia de almacenamiento, manipulaciones de datos complejos, índices pesados y menos eficientes, etc.
Uno de los casos típicos lo encontramos cuando deseamos almacenar únicamente la fecha de un apunte contable, la fecha de nacimiento, etc. En este caso podíamos recurrir a smalldatetime (4 bytes) siempre y cuando no necesitemos fechas anteriores a 1900 o posteriores a 2079. Con el nuevo tipo de datos date (3 bytes) obtenemos un rango útil mucho más versátil desde año 1 hasta el año 9999 a la vez que ahorramos un byte y evitamos manipulaciones adicionales para obtener solo la parte de fecha.
Otra necesidad habitual es almacenar únicamente la hora sin la fecha asociada. Un ejemplo de esta situación es cuando almacenamos los tiempos de una media maratón. En este caso la situación es aún más crítica pues no podríamos utilizar un smalldatetime pues su precisión es de 1 minuto obligándonos a recurrir a un datetime (8 bytes). El nuevo tipo time nos permite ajustar la precisión del segundero desde 1s a 100ns (3-5 bytes). Buscando la eficiencia de espacio y la mayor precisión las siguientes definiciones son las óptimas:
Tipo de datos
|
Precisión
|
Tamaño
|
time(2) | (hh:mm:ss.00) |
3 bytes
|
time(4) |
(hh:mm:ss.0000)
|
4 bytes
|
time
|
(hh:mm:ss.0000000) |
5 bytes
|
Podemos ver que en el mejor de los casos ahorraremos un 62% del espacio obteniendo, además, una precisión mayor que la que disponíamos con datetime (0.01s vs 0.333s)
Otra situación complicada la encontrábamos cuando el manejo de fechas superaba el rango de datos aceptable por datetime. Datetime no puede manejar fechas anteriores al 01-01-1753. Esto plantea un inconveniente cuando utilizamos por ejemplo el framework .NET cuyo tipo de datos DateTime permite fechas y horas desde 01-01-0001. En casos extremos esto implicaba la engorrosa alternativa de utilizar representaciones en cadenas de texto, descomponiendo la fecha en partes o creando un tipo de datos de usuario (UDT) en SQL Server 2005. El nuevo tipo de datos datetime2 nos permite gestionar el mismo rango de fechas que .NET y otros entornos además de no ocupar más espacio que datetime:
Tipo de datos
|
Precisión
|
Tamaño
|
datetime2(2)
|
(YYYY-MM-DD hh:mm:ss.00)
|
6 bytes
|
datetime2(4)
|
(YYYY-MM-DD hh:mm:ss.0000) |
7 bytes
|
datetime |
(YYYY-MM-DD hh:mm:ss.0000000)
|
8 bytes
|
Finalmente el nuevo tipo de datos DATETIMEOFFSET nos puede resultar muy útil cuando gestionamos fechas procedentes de distintas zonas horarias. Hasta ahora nuestra alternativa pasaba por o bien transformar todas las fechas a una zona horaria (GMT por ejemplo) y luego volverlas a transformar en las consultas o bien almacenar la zona horaria en otra columna y ajustar el resultado en función de ésta. Con DATETIMEOFFSET podemos manejar en un mismo tipo de dato la fecha y hora junto con su zona horaria con la misma precisión configurable que DATETIME2:
Tipo de datos
|
Precisión
|
Tamaño
|
datetimeoffset(2)
|
(YYYY-MM-DD hh:mm:ss.00 {+|-}hh:mm)
|
8 bytes
|
datetimeoffset(4) | (YYYY-MM-DD hh:mm:ss.0000 {+|-}hh:mm) |
9 bytes
|
datetimeoffset | (YYYY-MM-DD hh:mm:ss.0000000 {+|-}hh:mm) |
10 bytes
|