¿Cómo funcionan los valores DATETIME en SQLite?

110

Estoy creando aplicaciones de Android y necesito guardar la fecha / hora del registro de creación. Los documentos de SQLite dicen, sin embargo, "SQLite no tiene una clase de almacenamiento reservada para almacenar fechas y / o horas" y es "capaz de almacenar fechas y horas como valores TEXT, REAL o INTEGER".

¿Existe una razón técnica para utilizar un tipo sobre otro? ¿Y puede una sola columna almacenar fechas en cualquiera de los tres formatos de fila a fila?

Tendré que comparar las fechas más tarde. Por ejemplo, en mis aplicaciones mostraré todos los registros que se crean entre la fecha A y la fecha B. Me preocupa que no tener una verdadera columna DATETIME pueda dificultar las comparaciones.

Khairil Ushan
fuente

Respuestas:

83

SQlite no tiene un tipo de fecha y hora específico. Puede utilizar TEXT, REALo INTEGERescribir, lo que se adapte a sus necesidades.

Directamente del DOCS

SQLite no tiene una clase de almacenamiento reservada para almacenar fechas y / o horas. En cambio, las funciones de fecha y hora incorporadas de SQLite son capaces de almacenar fechas y horas como valores TEXT, REAL o INTEGER:

  • TEXTO como cadenas ISO8601 ("AAAA-MM-DD HH: MM: SS.SSS").
  • REAL como números de días julianos, el número de días desde el mediodía en Greenwich el 24 de noviembre de 4714 a. C. según el proléptico calendario gregoriano.
  • INTEGER como Unix Time, el número de segundos desde 1970-01-01 00:00:00 UTC.

Las aplicaciones pueden elegir almacenar fechas y horas en cualquiera de estos formatos y convertir libremente entre formatos utilizando las funciones integradas de fecha y hora.

Las funciones de fecha y hora integradas de SQLite se pueden encontrar aquí .

neo108
fuente
11
Es importante tener en cuenta que todos los métodos de almacenamiento de fechas utilizan formatos que se pueden comparar con los operadores estándar =, <,> y BETWEEN.
Larry Lustig
2
"SQLite no tiene una clase de almacenamiento reservada para almacenar fechas y / o horas" - excepto que tiene tipos DATE y DATETIME que nunca se mencionan en la documentación
Slabko
12
@Slabko No lo hace. SQLite permite cualquier cosa (incluido DATETIME) como tipo declarado de columna. En base a eso, le da a esa columna una afinidad con una clase de almacenamiento (incluso tiene el ejemplo de cómo funciona esto para DATETIME en la documentación). Esa afinidad es más como una pista, ya que cada entrada de la columna puede tener una clase de almacenamiento diferente. Una clase de almacenamiento sigue siendo un paso más débil que un tipo y puede estar respaldada por varios tipos. Entonces sí, puedes usar DATETIME. No, en realidad no lo admite como tipo o clase de almacenamiento. Sí, la documentación contiene realmente la palabra "DATETIME".
Jasper
20

SQLite no tiene una clase de almacenamiento reservada para almacenar fechas y / o horas. En cambio, las funciones de fecha y hora incorporadas de SQLite son capaces de almacenar fechas y horas como valores TEXT, REAL o INTEGER:

TEXTO como cadenas ISO8601 ("AAAA-MM-DD HH: MM: SS.SSS"). REAL como números de días julianos, el número de días desde el mediodía en Greenwich el 24 de noviembre de 4714 a. C. según el proléptico calendario gregoriano. INTEGER como Unix Time, el número de segundos desde 1970-01-01 00:00:00 UTC. Las aplicaciones pueden elegir almacenar fechas y horas en cualquiera de estos formatos y convertir libremente entre formatos utilizando las funciones integradas de fecha y hora.

Habiendo dicho eso, usaría INTEGER y almacenaría segundos desde la época de Unix (1970-01-01 00:00:00 UTC).

Diego Torres Milano
fuente
1
Yo también prefiero esto. Las clases estándar relacionadas con la fecha / hora están respaldadas internamente por largos de todos modos, y es bastante fácil comparar largos.
Karakuri
1
@dtmilano ¿Por qué prefiere INTEGER aquí en lugar de String?
IgorGanapolsky
1
INTEGER solo usa 8 bytes, TEXT usa 23 bytes en este ejemplo. No está claro cómo elegir en qué tipo se almacenan los datos. ¿Significa que si creo una columna de tipo INTEGER, las funciones se almacenarán automáticamente como Unix Time?
rayzinnz
2
REAL también usa 8 bytes. Los segundos de la época serán de 10 dígitos hasta finales de 2286, y dado que IEEE doble admite entre 15 y 17 dígitos significativos , esto le brinda una resolución mejor que milisegundos. RSQLiteparece que se está convirtiendo POSIXcta una época numérica, por lo que funciona bastante bien para mí.
r2evans
@ r2evans No estoy seguro de lo que estás diciendo. Si quiero almacenar milisegundos desde la Época, ¿cómo lo hago?
Michael
14

Una de las poderosas características de SQLite es permitirle elegir el tipo de almacenamiento. Ventajas / desventajas de cada una de las tres posibilidades diferentes:

  • Cadena ISO8601

    • La comparación de cadenas da resultados válidos
    • Almacena fracciones de segundo, hasta tres dígitos decimales
    • Necesita más espacio de almacenamiento
    • Verá directamente su valor cuando utilice un navegador de base de datos
    • Necesidad de analizar para otros usos
    • El modificador de columna "default current_timestamp" se almacenará usando este formato
  • Número Real

    • Alta precisión en fracciones de segundo
    • Rango de tiempo más largo
  • Número entero

    • Espacio de almacenamiento más bajo
    • Operaciones rápidas
    • Rango de tiempo pequeño
    • Posible problema del año 2038

Si necesita comparar diferentes tipos o exportar a una aplicación externa, puede usar las funciones de conversión de fecha y hora propias de SQLite según sea necesario.

Zso
fuente
1
¿Por qué hay un problema de 2038? INTEGER parece admitir almacenamiento de 64 bits.
guan boshen
1
@guanboshen Por lo que puedo decir, la única razón para preocuparse por 2038 sería el soporte en la plataforma de host. La documentación de SQLite afirma usar C localtime_r()( sqlite.org/lang_datefunc.html#caveats_and_bugs ) en la implementación de referencia, y localtime()puede ser potencialmente vulnerable a 2038 si la plataforma de host tiene un archivotime_t . Dicho esto, dado que SQLite afirma protegerse contra esta posibilidad al mapear fechas externas en un rango seguro antes de la conversión (ver el mismo enlace), creo que es poco probable que sea un problema, excepto quizás en casos esotéricos.
Zoë Sparks
@ ZoëSparks Gracias por la aclaración.
guan boshen
7

Para prácticamente todos los asuntos de fecha y hora prefiero simplificar las cosas, muy, muy simple ... Hasta segundos almacenados en números enteros.

Los enteros siempre se admitirán como enteros en bases de datos, archivos planos, etc. Haga un poco de matemática y la convierte en otro tipo y puede formatear la fecha de la forma que desee.

Haciéndolo de esta manera, no tiene que preocuparse cuando [inserte la base de datos favorita actual aquí] sea reemplazada por [futura base de datos favorita] que casualmente no usó el formato de fecha que eligió hoy.

Es solo una pequeña sobrecarga matemática (por ejemplo, métodos, toma dos segundos, publicaré una esencia si es necesario) y simplifica las cosas para muchas operaciones con respecto a la fecha / hora más adelante.

KelvinEWilliams
fuente
7

Guárdelo en un campo de tipo long. Ver Date.getTime()ynew Date(long)

Koem
fuente
¿cómo puedo compararlo? ¿Me puede dar una muestra de la consulta ...: D
Khairil Ushan
Mire Joda Time para comparaciones en código ( joda-time.sourceforge.net ) y use una comparación larga y simple en SQL (por ejemplo, comparación numérica).
Sintaxis
seleccione * de la tabla donde la creación entre ayb;
koem