sql server - insertar - La mejor forma de almacenar el tiempo(hh: mm) en una base de datos
obtener hora sql server (15)
Quiero almacenar tiempos en una tabla de base de datos, pero solo necesito almacenar las horas y los minutos. Sé que podría usar DATETIME e ignorar los otros componentes de la fecha, pero ¿cuál es la mejor manera de hacerlo sin almacenar más información de la que realmente necesito?
DATETIME start DATETIME end
Le imploro que utilice dos valores DATETIME en su lugar, etiquetados como event_start y event_end .
El tiempo es un negocio complejo
La mayor parte del mundo ahora ha adoptado el sistema métrico basado en denery para la mayoría de las mediciones, correcta o incorrectamente. Esto es bueno en general, porque al menos todos podemos estar de acuerdo en que ag, es un ml, es un cm cúbico. Al menos aproximadamente así. El sistema métrico tiene muchos defectos, pero al menos es internacionalmente defectuoso.
Con el tiempo, sin embargo, tenemos; 1000 milisegundos en un segundo, 60 segundos a un minuto, 60 minutos a una hora, 12 horas por cada medio día, aproximadamente 30 días por mes, que varían según el mes e incluso el año en cuestión, cada país tiene su tiempo compensado de los demás , la forma en que se formatea el tiempo en cada país varía.
Es mucho para digerir, pero a la larga es imposible que un escenario tan complejo tenga una solución simple.
Algunas esquinas se pueden cortar, pero hay otras donde es más prudente no
Aunque la respuesta principal sugiere que almacenar un número entero de minutos después de la medianoche puede parecer perfectamente razonable, he aprendido a evitar hacerlo de la manera difícil.
Las razones para implementar dos valores DATETIME son para aumentar la precisión, resolución y retroalimentación.
Todo esto es muy útil para cuando el diseño produce resultados indeseables.
¿Estoy almacenando más datos de los requeridos?
Al principio puede parecer que se está almacenando más información de la que necesito, pero hay una buena razón para tomar este golpe.
Almacenar esta información adicional casi siempre me ahorra tiempo y esfuerzo a largo plazo, porque inevitablemente descubro que cuando alguien sabe cuánto tiempo tomó algo, también querrán saber cuándo y dónde ocurrió el evento.
Es un gran planeta
En el pasado, he sido culpable de ignorar que hay otros países en este planeta aparte del mío. Parecía una buena idea en ese momento, pero SIEMPRE esto ha resultado en problemas, dolores de cabeza y pérdida de tiempo más adelante. SIEMPRE considere todas las zonas horarias.
DO#
Un DateTime se ve muy bien a una cadena en C #. El método ToString (formato de cadena) es compacto y fácil de leer.
P.ej
new TimeSpan(EventStart.Ticks - EventEnd.Ticks).ToString("h''h ''m''m ''s''s''")
Servidor SQL
Además, si está leyendo su base de datos separadamente de la interfaz de su aplicación, entonces dateTimes es agradable para leer de un vistazo y realizar cálculos sobre ellos es sencillo.
P.ej
SELECT DATEDIFF(MINUTE, event_start, event_end)
Estándar de fecha ISO8601
Si usa SQLite, entonces no tiene esto, entonces use un campo de Texto y guárdelo en formato ISO8601, por ejemplo.
"2013-01-27T12: 30: 00 + 0000"
Notas:
Esto usa 24 horas de reloj *
La parte +0000 del ISO8601 se asigna directamente a Lattitude en una coordinación de GPS. Por lo tanto, vale la pena considerar si valdría la pena almacenar longitud, latitud y altitud junto con los datos. Esto variará en la aplicación.
ISO8601 es un formato internacional.
El wiki es muy bueno para más detalles en http://en.wikipedia.org/wiki/ISO_8601 .
La fecha y la hora se almacenan en horario internacional y la compensación se registra dependiendo de en qué parte del mundo se almacenó la hora.
Según mi experiencia, siempre existe la necesidad de almacenar la fecha y la hora completas, independientemente de si creo que las hay cuando empiezo el proyecto. ISO8601 es una muy buena forma de hacerlo.
Consejos adicionales gratis
También vale la pena agrupar eventos como una cadena. Por ejemplo, si se graba una carrera, el evento completo se puede agrupar por corredor, circuito de carrera, puntos de verificación de circuito y salto de circuito.
En mi experiencia, también es sabio identificar quién almacenó el registro. Ya sea como una tabla separada poblada a través del desencadenador o como una columna adicional dentro de la tabla original.
Cuanto más pones, más saldrás
Comprendo completamente el deseo de ser lo más económico posible con el espacio, pero raramente lo haría a expensas de perder información.
Una regla general con las bases de datos es, como dice el título, que una base de datos solo puede decirle tanto como datos, y puede ser muy costoso volver a los datos históricos, llenando los vacíos.
La solución es hacerlo bien la primera vez. Esto es ciertamente más fácil de decir que de hacer, pero ahora debería tener una visión más profunda del diseño efectivo de la base de datos y, posteriormente, tener una mejor oportunidad de hacerlo bien la primera vez.
Cuanto mejor sea su diseño inicial, menos costosas serán las reparaciones más adelante.
Solo digo todo esto, porque si pudiera retroceder en el tiempo sería lo que me diría a mí mismo cuando llegue allí.
¿Estás seguro de que solo necesitarás las horas y los minutos? Si desea hacer algo significativo con él (como, por ejemplo, cálculos de tiempos entre dos puntos de datos), no tener información sobre las zonas horarias y el horario de verano puede dar resultados incorrectos. Es posible que las zonas horarias no se apliquen en su caso, pero DST ciertamente lo hará.
El ahorro de tiempo en formato UTC puede ayudar mejor, como sugirió Kristen.
Asegúrese de estar utilizando un reloj de 24 horas porque no hay un meridiano AM o PM en UTC.
Ejemplo:
- 4:12 a.m. - 0412
- 10:12 a.m. - 1012
- 2:28 p.m. - 1428
- 11:56 p.m. - 2356
Todavía es preferible usar el formato estándar de cuatro dígitos.
En lugar de minutos, pasada la medianoche, lo almacenamos como reloj de 24 horas, como SMALLINT.
09:12 = 912 14:15 = 1415
Al convertir de nuevo a "forma legible para humanos" simplemente insertamos dos puntos ":" dos caracteres de la derecha. Almohadilla izquierda con ceros si es necesario. Guarda las matemáticas en todos los sentidos, y utiliza algunos bytes menos (en comparación con varchar), además hace cumplir que el valor es numérico (en lugar de alfanumérico)
Aunque fue bastante tonto ... debería haber habido un tipo de datos TIME en MS SQL durante muchos años, ya en mi humilde opinión ...
En mi humilde opinión, la mejor solución depende en cierta medida de cómo se almacena el tiempo en el resto de la base de datos (y el resto de la aplicación)
Personalmente, he trabajado con SQLite y trato de usar siempre marcas de tiempo Unix para almacenar tiempo absoluto, así que cuando se trata de la hora del día (como usted pide) hago lo que Glen Solsberry escribe en su respuesta y almaceno el número de segundos desde la medianoche
Al tomar este enfoque general, las personas (¡incluido yo!) Que leen el código se sienten menos confundidas si utilizo el mismo estándar en todos lados
Guarde las ticks
como un bigint
long
/ long
, que actualmente se mide en milisegundos. El valor actualizado se puede encontrar mirando el valor TimeSpan.TicksPerSecond
.
La mayoría de las bases de datos tienen un tipo DateTime que almacena automáticamente la hora como marcas detrás de las escenas, pero en el caso de algunas bases de datos, como SqlLite, el almacenamiento de ticks puede ser una forma de almacenar la fecha.
La mayoría de los idiomas permiten la fácil conversión de Ticks
→ TimeSpan
→ Ticks
.
Ejemplo
En C # el código sería:
long TimeAsTicks = TimeAsTimeSpan.Ticks;
TimeAsTimeSpan = TimeSpan.FromTicks(TimeAsTicks);
Tenga en cuenta, sin embargo, porque en el caso de SqlLite, que solo ofrece un pequeño número de tipos diferentes, que son; INT
, REAL
y VARCHAR
Será necesario almacenar el número de ticks como una cadena o dos celdas INT
combinadas. Esto es, porque un INT
es un número firmado de 32 bits, mientras que BIGINT
es un número firmado de 64 bits.
Nota
Sin embargo, mi preferencia personal sería almacenar la fecha y la hora como una cadena ISO8601
.
Lo que creo que estás pidiendo es una variable que almacenará los minutos como un número. Esto se puede hacer con los diferentes tipos de variables enteras:
SELECT 9823754987598 AS MinutesInput
Luego, en su programa, simplemente puede ver esto en la forma que desee calculando:
long MinutesInAnHour = 60;
long MinutesInADay = MinutesInAnHour * 24;
long MinutesInAWeek = MinutesInADay * 7;
long MinutesCalc = long.Parse(rdr["MinutesInput"].toString()); //BigInt converts to long. rdr is an SqlDataReader.
long Weeks = MinutesCalc / MinutesInAWeek;
MinutesCalc -= Weeks * MinutesInAWeek;
long Days = MinutesCalc / MinutesInADay;
MinutesCalc -= Days * MinutesInADay;
long Hours = MinutesCalc / MinutesInAnHour;
MinutesCalc -= Hours * MinutesInAnHour;
long Minutes = MinutesCalc;
Surge un problema en el que solicita que se use la eficiencia. Pero, si tiene poco tiempo, simplemente use un BigInt con nulos para almacenar el valor de sus minutos.
Un valor de nulo significa que el tiempo no se ha registrado todavía.
Ahora, explicaré en forma de un viaje de ida y vuelta al espacio exterior.
Lamentablemente, una columna de tabla solo almacenará un solo tipo. Por lo tanto, deberá crear una nueva tabla para cada tipo según sea necesario.
Por ejemplo:
Si MinutesInput = 0 .. 255 entonces use TinyInt (Convert como se describió anteriormente).
Si MinutesInput = 256 .. 131071 entonces use SmallInt (Nota: el valor mínimo de SmallInt es -32,768. Por lo tanto, niegue y agregue 32768 cuando almacene y recupere el valor para utilizar el rango completo antes de la conversión como se indicó anteriormente).
Si MinutesInput = 131072 .. 8589934591 , utilice Int (Nota: Negate y agregue 2147483648 según sea necesario).
Si MinutesInput = 8589934592 .. 36893488147419103231 entonces use BigInt (Nota: Agregue y niegue 9223372036854775808 según sea necesario).
Si MinutesInput > 36893488147419103231 entonces personalmente usaría VARCHAR (X) incrementando X según sea necesario dado que un carácter es un byte. Tendré que volver a visitar esta respuesta en una fecha posterior para describir esto en su totalidad (o tal vez un compañero ee puede terminar esta respuesta).
Dado que cada valor indudablemente requerirá una clave única, la eficiencia de la base de datos solo será evidente si el rango de los valores almacenados es una buena combinación entre muy pequeño (cerca de 0 minutos) y muy alto (mayor que 8589934591).
Hasta que los valores que se almacenan realmente lleguen a un número mayor que 36893488147419103231, entonces también podría tener una sola columna BigInt para representar sus minutos, ya que no tendrá que perder un Int en un identificador único y otro int para almacenar el valor de los minutos.
Los convertiría a un número entero (HH * 3600 + MM * 60) y lo almacenaría de esa manera. Tamaño de almacenamiento pequeño, y aún lo suficientemente fácil para trabajar.
Pruebe smalldatetime. Puede que no le brinde lo que desea, pero lo ayudará en sus necesidades futuras de manipulación de fecha / hora.
Puede almacenarlo como un número entero de minutos después de la medianoche:
p.ej.
0 = 00:00
60 = 01:00
252 = 04:12
Sin embargo, necesitaría escribir algún código para reconstituir la hora, pero eso no debería ser complicado.
SQL Server realmente almacena el tiempo como fracciones de un día. Por ejemplo, 1 día completo = valor de 1. 12 horas es un valor de 0.5.
Si desea almacenar el valor de tiempo sin utilizar un tipo DATETIME, almacenar la hora en forma decimal se adecuaría a esa necesidad, al tiempo que haría simple la conversión a DATETIME.
Por ejemplo:
SELECT CAST(0.5 AS DATETIME)
--1900-01-01 12:00:00.000
Almacenar el valor como DECIMAL (9,9) consumiría 5 bytes. Sin embargo, si la precisión no es de suma importancia, un REAL consumiría solo 4 bytes. En cualquier caso, el cálculo agregado (es decir, el tiempo medio) se puede calcular fácilmente en valores numéricos, pero no en los tipos Datos / Tiempo.
Si está utilizando MySQL use un tipo de campo de TIEMPO y la funcionalidad asociada que viene con TIEMPO.
00:00:00 es el formato de tiempo estándar de Unix.
Si alguna vez tiene que mirar atrás y revisar las tablas a mano, los enteros pueden ser más confusos que una marca de tiempo real.
Si está utilizando SQL Server 2008+, considere el tipo de datos TIME
. Artículo de SQLTeam con más ejemplos de uso.
Solo almacene una fecha de tiempo regular e ignore todo lo demás. ¿Por qué dedicar más tiempo a la escritura de código que carga un int, lo manipula y lo convierte en un datetime, cuando solo puede cargar un datetime?
ya que no lo mencionaste, si estás en SQL Server 2008 puedes usar el tipo de datos de tiempo; de lo contrario, usar los minutos desde la medianoche