2011-08-03 26 views
10

Aquí hay uno más o menos por el bien de la perfección.SQL Server: forma más óptima de almacenar el tiempo (sin fecha)

Microsoft SQL Server solo contiene el tipo de campo datetime para almacenar fechas y horas.

Pero digamos que quiero almacenar una lista de horas hábiles, donde la fecha es completamente irrelevante. Actualmente estoy usando el tipo datetime y luego simplemente visualizo la porción de tiempo de los datos. Pero tengo dos problemas con esto.

  1. Parece torpemente ineficiente.
  2. Puede confundir a los futuros desarrolladores para ver una fecha completa junto con el tiempo, que pueden no saber si se utiliza en cualquier lugar o no.

Y entonces, surge la pregunta; en ausencia de un campo específico time (como en MySQL), ¿cuál es la forma más óptima de almacenar solo una hora particular del día, de 00:00 a 23:59?

ACTUALIZACIÓN: Es SQL Server 2005. (También me gustaría simplemente interesado en saber qué hacer, en general, cuando no hay time tipo.)

+2

Es este SQL Server 2008 o posterior (cruzando los dedos) porque entonces solo puede usar el tipo de datos Time. –

+1

SQL Server 2008+ tiene un tipo de datos de tiempo: http: //msdn.microsoft.com/en-us/library/ms187752.aspx –

+0

SQL Server introdujo un [tiempo] (http://msdn.microsoft.com/en -us/library/bb677243.aspx) datatype en 2008. –

Respuesta

7

Para SQL Server 2005 o más ...

Si sólo desea saber al minuto, se puede almacenar como un entero en el rango de 1-1440. 1 es 00:01 y 1440 es 0:00.

Sería fácil hacer la pantalla como un tiempo nuevo si te gusta:

SELECT CAST((605/60) as varchar) + ':' + RIGHT('0' + CAST((605 % 60) as varchar), 2)

Una ventaja adicional de esto es que si se utiliza un conjunto de datos smallint tipo que está guardando 1-3 bytes por registro desde el tipo de datos TIME incorporado.

TIME utiliza 3-5 bytes por fila y smallint es de 2 bytes por fila.

Los bytes adicionales son para segundos y segundos fraccionarios, creo.

EDITAR

es más complicado con el segundo pero se puede hacer lo creo ...

1-86400 rango (segundos por día)

DECLARE @i INT 
SET @i = 3661 

SELECT RIGHT('0' + CAST((@i/3600) as varchar),2) --hours 
+ ':' + RIGHT('0' + CAST((@i % 3600)/60 as varchar), 2) -- minutes 
+ ':' + RIGHT('0' + CAST((@i % 3600)%60 as varchar), 2) -- seconds 
+0

Interesante. ¿Qué pasa si quiero horas, minutos y segundos, lo sabes? – Teekin

+1

@Helgi ver la edición – JNK

+0

Usaría el rango '0 a n-1'; La medianoche normalmente se considera el primer instante al comienzo del día, en lugar del último instante al final del día. (Depende del caso en cuestión, pero esto es mucho más normal en mi experiencia.) – MatBailie

2
+2

Esto solo es aplicable en 'SQL Server 2008' actualmente. – JNK

+1

@JNK verdadero, pero el autor no especificó el requisito de versión. –

+0

Lo sé, pero solo necesita asegurarse de calificar en estos casos. Si no se especifica la versión pero su solución es específica de la versión, mencione eso en su respuesta. – JNK

5

SQL Server 2008 tiene una TIME tipo de datos:

http://www.sql-server-performance.com/2007/datetime-2008/

DECLARE @dt as TIME 
SET @dt = getdate() 
PRINT @dt 

¿Actualizar a SQL 2008?

+0

+1 SQL Server 2005 ya tuvo su "final de vida": ¡definitivamente es el momento de actualizar! –

+0

¡Ya sabe cómo funciona con software comercial de código cerrado! El costo de propiedad no importa hasta que tenga que actualizar. ;) – Teekin

2

Personalmente no considerarían las cuestiones planteadas como suficiente para dejar de utilizar DATETIME o SMALLDATETIME.

  • un int utiliza 4 bytes, al igual que una SMALLDATETIME
  • la gente comete errores con SMALLINT que causan las conversiones de tipo implícitas (aumento de la carga de la CPU)
  • espacio en disco es barato, necesita una gran cantidad de bytes para agregar hasta anythign significativa Código
  • como WHERE minutes < 720 es menos comprensible que WHERE time < '12:00'
  • problemas de visualización (como la conversión de fecha y hora a hh: mm) es a menudo el mejor lugar en el cliente
  • Usando DATETIME permite flexibilidad en el futuro, tales mover a segundos en lugar de minutos

Dicho esto, he utilizado los campos de enteros para mantener el número de segundos, por ejemplo, cuando se usan predominantemente para el cálculo de las duraciones medias, etc.

Mi mayor consideración al elegir el tipo es cómo se usará el valor; para garantizar un código legible y planes de ejecución de rendimiento.

+0

+1 - Todos los puntos muy válidos. Mi punto sobre los bytes en mi respuesta probablemente esté más relacionado con mi experiencia personal. Tengo muchas tablas MUY grandes (600m-2b), y si puedo reducir algunos bytes por fila, se acumula rápidamente. – JNK

+0

Muy cierto, pero hay una fuerte discusión que incluso 4 GB es relativamente pequeño. – MatBailie

0

SQL 2008 fija este problema como han dicho otros, pero en 2005:

¿Es necesario realizar ninguna fecha en matemáticas los tiempos? Si no, puede almacenarlo como una cadena.

Si necesita realizar la fecha matemática, un día de fecha con el día establecido en cero junto con un nombre de columna descriptivo no debe confundir a ningún desarrollador futuro (y gracias por recordarnos).

Y sí, datetime es torpe por tiempo de almacenamiento, pero funciona muy bien.

Cuestiones relacionadas