Pregunta

¿Cuál:

es la recomienda manera de almacenar la fecha y hora en SQL Server 2008 +?

Soy consciente de las diferencias en la precisión (y espacio de almacenamiento probablemente), pero haciendo caso omiso de las de ahora, ¿existe un documento de mejores prácticas sobre cuándo utilizar qué, o tal vez deberíamos usar datetime2 solamente?

¿Fue útil?

Solución

La documentación de MSDN para datetime recomienda utilizar datetime2 . Aquí es su recomendación:

  

Utilice la time, date, y datetime2   tipos de datos para los nuevos datetimeoffset   trabajo. Estos tipos se alinean con el SQL   Estándar. Son más fáciles de transportar.   time, datetime2 y datetimeoffset   proporcionar más segundos de precisión.   datetimeoffset ofrece zona horaria   apoyo a desplegado a nivel mundial   aplicaciones.

datetime2 tiene mayor rango de fechas, una precisión fraccionaria más grande predeterminado, y la precisión especificada por el usuario opcional. También en función de la precisión especificada por el usuario puede utilizar menos espacio de almacenamiento.

Otros consejos

DATETIME2 tiene un intervalo de fechas de "0001/01/01" a través de "9999/12/31", mientras que el tipo DATETIME sólo es compatible con el año 1753 hasta 9999.

Además, si es necesario, DATETIME2 puede ser más preciso en términos de tiempo; DATETIME se limita a 3 1/3 milisegundos, mientras que DATETIME2 puede ser precisa hasta 100 ns.

Ambos tipos se asignan a System.DateTime en .NET - no hay diferencia

.

Si usted tiene la opción, yo recomendaría el uso de DATETIME2 siempre que sea posible. No veo ningún beneficio utilizando DATETIME (a excepción de compatibilidad con versiones anteriores) -. Usted tendrá menos problemas (con fechas de estar fuera del rango y sin problemas por el estilo)

Además: si sólo se necesita la fecha (sin tiempo parcial), el uso FECHA - es sólo tan buena como DATETIME2 y le ahorra espacio, también! :-) El mismo va para única vez - utilizar TIME. Eso es lo que estos tipos están ahí para que!

datetime2 gana en la mayoría de los aspectos, excepto (antiguo aplicaciones de compatibilidad)

  1. mayor rango de valores
  2. mejor Precisión
  3. menor espacio de almacenamiento (si se especifica la precisión especificada por el usuario opcional)

Fecha y hora de SQL tipos de datos se comparan - fecha y hora, datetime2, fecha, hora

tenga en cuenta los siguientes puntos

  • Sintaxis
    • datetime2 [(fracciones de segundo de precisión => Mira debajo del tamaño de almacenamiento)]
  • Precisión, escala
    • 0 a 7 dígitos, con una precisión de 100 ns.
    • La precisión predeterminada es de 7 dígitos.
  • Tamaño de almacenamiento
    • 6 bytes para la precisión de menos de 3;
    • 7 bytes de precisión 3 y 4.
    • El resto de precisión requiere 8 bytes .
  • DateTime2 (3) tener el mismo número de dígitos como DateTime pero utiliza 7 bytes de almacenamiento en lugar de 8 bytes ( SQLHINTS- DateTime vs dateTime2 )
  • Para más información sobre datetime2 (Transact-SQL artículo de MSDN)

fuente de la imagen: MCTS Paced Training Kit (Exam 70-432): Microsoft SQL Server® 2008 - Implementación y Mantenimiento Capítulo 3: Tablas -> Lección 1: Creación de tablas -> página 66

I concurr con @marc_s y @Adam_Poward - DateTime2 es el método preferido de seguir adelante. Cuenta con una amplia gama de fechas, una mayor precisión, y utiliza el almacenamiento igual o menor (dependiendo de la precisión).

Una cosa que la discusión se perdió, sin embargo ...
@Marc_s afirma: Both types map to System.DateTime in .NET - no difference there. Esto es correcto, Sin embargo, la inversa no es cierto ... e importa al hacer búsquedas por rango de fecha (por ejemplo, "me encontrará todos los registros modificados en 5/5/2010").

La versión de .NET de Datetime tiene rango similar y precisión a DateTime2. Al asignar un Datetime .net hasta la edad de SQL DateTime un redondeo implícita se produce . El viejo DateTime SQL tiene una precisión de 3 milisegundos. Esto significa que 11:59:59.997 es lo más cerca que puede llegar al final del día. Cualquier valor superior se redondea hasta el día siguiente.

Prueba esto:

declare @d1 datetime   = '5/5/2010 23:59:59.999'
declare @d2 datetime2  = '5/5/2010 23:59:59.999'
declare @d3 datetime   = '5/5/2010 23:59:59.997'
select @d1 as 'IAmMay6BecauseOfRounding', @d2 'May5', @d3 'StillMay5Because2msEarlier'

Evitar este redondeo implícita es una razón importante para mover a DateTime2. redondeo implícita de fechas provoca confusión claramente:

Casi todas las respuestas y comentarios se han pesado sobre los pros y los contras de luz sobre el. He aquí un resumen de todos los pros y los contras hasta ahora, además de algunos inconvenientes cruciales (en el # 2 abajo) sólo he visto mencionado una vez o ninguna en absoluto.

  1. PROS:

1.1. Más las normas ISO (ISO 8601) (aunque no sé cómo entra en juego en la práctica esto).

1,2. Más gama (1/1/0001 al 12/31/9999 vs 1/1 / 1753-12 / 31/9999) (aunque el rango adicional, todo antes del año 1753, es probable que no se use, excepto por ej., en el histórico, astronómico, geológico, etc. aplicaciones).

1.3. Iguala exactamente el rango de gama de de .NET Tipo DateTime (aunque ambos convertir un lado a otro sin la codificación especial si los valores están dentro del rango y precisión, excepto para Con # 2.1 a continuación else error / ocurrirá el redondeo del tipo de destino).

1,4. Más precisión (también conocido como 100 nanosegundos 0.000,000,1 seg. Vs. 3,33 milisegundos aka 0.003,33 seg.) (Aunque la precisión adicional no es probable que se use, excepto por ej., En aplicaciones de ingeniería / científicos).

1,5. Cuando se configura para similares (como en 1 milisegundos no "igual" (como en 3,33 milisegundos) como Iman Abidi ha reivindicado) de precisión como DateTime, utiliza menos espacio (7 vs. 8 bytes), pero luego de Por supuesto, sería perder el beneficio de precisión que es probable que uno de los (la otra gama bienestar) dos más promocionado aunque no sean necesarios beneficios probables).

  1. CONS:

2,1. Al pasar un parámetro a un SqlCommand .NET, debe especificar System.Data.SqlDbType.DateTime2 si se le puede pasar un valor fuera del rango y / o precisión de la DateTime SQL Server, ya que el valor predeterminado es System.Data.SqlDbType.DateTime.

2,2. No puede ser implícita / convertido fácilmente a un punto flotante numérico (# de días desde la fecha min-tiempo) el valor de hacer lo siguiente a / con él en las expresiones de SQL Server utilizando valores numéricos y los operadores:

2.2.1. sumar o restar # de días o días parciales. Nota: El uso de funciones. DateAdd como una solución no es trivial cuando haya necesidad de considerar múltiples si no todas las partes de la fecha-hora

2.2.2. tomar la diferencia entre dos pares fecha-hora para fines de cálculo de la “edad”. Nota: No se puede simplemente utilizar la función DateDiff de SQL Server en lugar, ya que no computa age ya que la mayoría de la gente espera de que si los dos pares fecha-hora pasa a cruzar un calendario / reloj de fecha y hora límite de las unidades especificadas aunque sea por una pequeña fracción de esa unidad, que va a devolver la diferencia como 1 de dicha unidad frente a 0. Por ejemplo, el DateDiff en dos de Day de fecha-hora sólo 1 milisegundo aparte volverá 1 vs 0 (días) si esos fecha- veces están en diferentes días naturales (es decir, “1999-12-31 23: 59: 59.9999999” y “2000-01-01 00: 00: 00,0000000”). Los mismos 1 milisegundo diferencia de fechas veces si se mueve de manera que no cruzan un día del calendario, devolverá un “DateDiff” en Day de de 0 (días).

2.2.3. tomar el Avg de fecha-veces (en una consulta Aggregate) simplemente convertir a “flotar” primero y luego de vuelta a DateTime.

NOTA: Para convertir DateTime2 a un valor numérico, que tiene que hacer algo parecido a la siguiente fórmula que sigue asume sus valores no son menos que en el año 1970 (lo que significa que está perdiendo toda la gama adicional más otros 217 años. Nota:. Puede no ser capaz de ajustar simplemente la fórmula para permitir un mayor rango porque es posible que tenga problemas de desbordamiento numérico

25567 + (DATEDIFF(SECOND, {d '1970-01-01'}, @Time) + DATEPART(nanosecond, @Time) / 1.0E + 9) / 86400.0 - Fuente: “ https : //siderite.blogspot.com/2015/08/how-to-translate-t-sql-datetime2-to.html “

Por supuesto, también se puede Cast a DateTime primera (y si es necesario volver a DateTime2), pero perdería la precisión y alcance (1753) todos los beneficios anteriores a años de DateTime2 vs. DateTime que son Prolly la 2 más grande y también al mismo tiempo la Prolly 2 menos probable que se necesiten, que plantea la pregunta de por qué lo utilizan cuando se pierde las conversiones implícitas / fáciles de punto flotante numérica (número de días) de suma / resta / la "edad" (vs. DateDiff) / beneficio calculadoras Avg que es un grande en mi experiencia.

Por cierto, la fecha de Avg veces es (o al menos debe ser) un importante caso de uso. a) Además de su uso en conseguir duración media cuando se utilizan pares fecha-hora (desde una base común de fecha y hora) para representar la duración (una práctica común), b) también es útil para obtener una estadística de tipo tablero, en lo que la fecha-media el tiempo es en la columna de la fecha-hora de una serie / grupo de filas. c) Un estándar (o al menos debe ser estándar) ad-hoc de consultas para supervisar / solucionar valores de una columna que puede no ser válida siempre / por más tiempo y / o pueden necesitar ser obsoleta es lista para cada valor de recuento de la ocurrencia y (si está disponible) los Min, Avg y Max sellos de fecha y hora asociada con ese valor.

DateTime2 causa estragos si usted es un desarrollador de acceso tratando de escribir ahora () para el campo en cuestión. Acaba de hacer un acceso -> SQL 2008 R2 y la migración que poner todos los campos de fecha y hora en que DateTime2. Al añadir un registro con Ahora () como el valor bombardeada. Estaba bien en 1/1/2012 2:53:04 PM, pero no en 1/10/2012 02:53:04 PM.

Una vez personaje que hizo la diferencia. Espero que ayuda a alguien.

A continuación se muestra un ejemplo que le mostrará las diferencias en el tamaño de almacenamiento (bytes) y la precisión entre smalldatetime, fecha y hora, datetime2 (0), y datetime2 (7):

DECLARE @temp TABLE (
    sdt smalldatetime,
    dt datetime,
    dt20 datetime2(0),
    dt27 datetime2(7)
)

INSERT @temp
SELECT getdate(),getdate(),getdate(),getdate()

SELECT sdt,DATALENGTH(sdt) as sdt_bytes,
    dt,DATALENGTH(dt) as dt_bytes,
    dt20,DATALENGTH(dt20) as dt20_bytes,
    dt27, DATALENGTH(dt27) as dt27_bytes FROM @temp

que devuelve

sdt                  sdt_bytes  dt                       dt_bytes  dt20                 dt20_bytes  dt27                         dt27_bytes
2015-09-11 11:26:00  4          2015-09-11 11:25:42.417  8         2015-09-11 11:25:42  6           2015-09-11 11:25:42.4170000  8

Así que si quiero para almacenar información hasta el segundo - pero no a la milésima de segundo -. Puedo salvar 2 bytes cada uno si uso datetime2 (0) en vez de datetime o datetime2 (7)

Interpretación de las cadenas de fecha en datetime y datetime2 puede ser diferente también, cuando se utiliza la configuración DATEFORMAT no estadounidenses. Por ejemplo.

set dateformat dmy
declare @d datetime, @d2 datetime2
select @d = '2013-06-05', @d2 = '2013-06-05'
select @d, @d2

Esto devuelve 2013-05-06 (es decir 6 Mayo) para datetime, y 2013-06-05 (es decir, 5 de junio) para datetime2. Sin embargo, con el conjunto de dateformat a mdy, tanto @d y el retorno @d2 2013-06-05.

El comportamiento datetime está en agudo contraste con la MSDN la documentación de SET DATEFORMAT que establece: Algunos formatos de cadenas de caracteres, por ejemplo ISO 8601, se interpretan de forma independiente de la configuración DATEFORMAT . Obviamente no es cierto!

Hasta que me picaron por esto, yo siempre había pensado que las fechas yyyy-mm-dd solo serían manejadas derecho, independientemente de la configuración de idioma / locale.

, mientras que hay un aumento de precisión datetime2 , algunos clientes no es compatible con fecha , tiempo o datetime2 y la fuerza que le permite convertir a una cadena literal. Específicamente menciona Microsoft ODBC "nivel inferior", OLE DB, JDBC y cuestiones SqlClient con estos tipos de datos y tiene un diagrama que muestra cómo cada uno puede representar el tipo.

Si el valor compatibilidad más precisión, utilizar fecha y hora

Pregunta viejo ... Pero quiero añadir algo que no se ha dicho por nadie aquí ... (Nota: Este es mi propia observación, así que no pedir ninguna referencia)

datetime2 es más rápido cuando se utiliza en criterios de filtro.

TLDR:

En SQL 2016 que tenía una mesa con cientos de miles de filas y una columna de fecha y hora ENTRY_TIME, ya que se requiere para almacenar la hora exacta hasta segundos. Durante la ejecución de una consulta compleja con muchas une y una consulta sub, cuando solía cláusula where como:

WHERE ENTRY_TIME >= '2017-01-01 00:00:00' AND ENTRY_TIME < '2018-01-01 00:00:00'

La consulta estaba bien al principio, cuando había cientos de filas, pero cuando aumenta el número de filas, la consulta comenzaron a dar este error:

Execution Timeout Expired. The timeout period elapsed prior
to completion of the operation or the server is not responding.

I eliminado la cláusula where, y de forma inesperada, la consulta se realizó en 1 seg, aunque ahora todas las filas para todas las fechas eran descabellada. Corro la consulta interna con cláusula where, y tardó 85 segundos, y sin cláusula donde tomó 0.01 segundos.

Me encontré con muchos hilos aquí para este problema como filtrado de fecha y hora rendimiento

optimicé consulta un poco. Sin embargo, la velocidad real que obtuve fue cambiando la columna de la fecha y hora a datetime2.

Ahora la misma consulta que Tiempo de espera agotado previamente tarda menos de un segundo.

aplausos

Según este artículo , si le gustaría tener la misma precisión de DateTime usando DateTime2 sólo tiene que utilizar DateTime2 (3). Esto debería dar la misma precisión, que cargue con uno menos bytes, y proporcionar una gama más amplia.

Yo sólo encontré con una ventaja más para DATETIME2: evita un error en el módulo adodbapi Python, que explota si se pasa un valor biblioteca datetime estándar que tiene no cero microsegundos para una columna DATETIME pero funciona bien si la columna se define como DATETIME2.

Select ValidUntil + 1
from Documents

El SQL anterior no funcionará con un campo DateTime2. Devuelve y error "tipo de operando choque: datetime2 es incompatible con int"

La adición de 1 a llegar al día siguiente, es algo que los desarrolladores han estado haciendo con fechas de años. Ahora Microsoft tiene un super nuevo campo datetime2 que no puede manejar esta funcionalidad sencilla.

"Vamos a usar este nuevo tipo que es peor que el anterior", yo no lo creo!

Creo DATETIME2 es la mejor manera de almacenar el date, porque tiene más eficacia que la DATETIME. En SQL Server 2008 puede utilizar DATETIME2, almacena una fecha y hora, tarda 6-8 bytes para almacenar y tiene una precisión de 100 nanoseconds. Por lo tanto cualquier persona que necesite una mayor precisión el tiempo querrá DATETIME2.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top