Comment les valeurs DATETIME fonctionnent-elles dans SQLite?

110

Je crée des applications Android et je dois enregistrer la date / l'heure de l'enregistrement de création. La documentation SQLite dit, cependant, "SQLite n'a pas de classe de stockage réservée pour stocker les dates et / ou les heures" et il est "capable de stocker les dates et les heures sous forme de valeurs TEXT, REAL ou INTEGER".

Y a-t-il une raison technique d'utiliser un type plutôt qu'un autre? Et une seule colonne peut-elle stocker des dates dans l'un des trois formats d'une ligne à l'autre?

J'aurai besoin de comparer les dates plus tard. Par exemple, dans mes applications, je montrerai tous les enregistrements créés entre la date A et la date B. Je crains que le fait de ne pas avoir une véritable colonne DATETIME puisse rendre les comparaisons difficiles.

Khairil Ushan
la source

Réponses:

83

SQlite n'a pas de type de date / heure spécifique. Vous pouvez utiliser TEXT, REALou INTEGERtypes, selon vos besoins.

Directement du DOCS

SQLite n'a pas de classe de stockage réservée pour stocker les dates et / ou les heures. Au lieu de cela, les fonctions de date et d'heure intégrées de SQLite sont capables de stocker des dates et des heures sous forme de valeurs TEXT, REAL ou INTEGER:

  • TEXTE sous forme de chaînes ISO8601 ("AAAA-MM-JJ HH: MM: SS.SSS").
  • REAL comme le nombre de jours juliens, le nombre de jours depuis midi à Greenwich le 24 novembre 4714 avant JC selon le calendrier grégorien prolptique.
  • INTEGER comme heure Unix, le nombre de secondes depuis le 01/01/1970 à 00:00:00 UTC.

Les applications peuvent choisir de stocker les dates et les heures dans n'importe lequel de ces formats et de convertir librement entre les formats à l'aide des fonctions de date et d'heure intégrées.

Les fonctions de date et d'heure intégrées à SQLite sont disponibles ici .

neo108
la source
11
Important à noter - toutes les méthodes de stockage des dates utilisent des formats qui peuvent être comparés à l'aide des opérateurs standard =, <,> et BETWEEN.
Larry Lustig
2
"SQLite n'a pas de classe de stockage réservée pour stocker les dates et / ou les heures" - sauf qu'il a des types DATE et DATETIME qui ne sont jamais mentionnés dans la documentation
Slabko
12
@Slabko Ce n'est pas le cas. SQLite autorise tout (y compris DATETIME) comme type déclaré d'une colonne. Sur cette base, il donne à cette colonne une affinité avec une classe de stockage (il a même l'exemple de la façon dont cela fonctionne pour DATETIME dans la documentation). Cette affinité ressemble plus à un indice, car chaque entrée de la colonne peut en fait avoir une classe de stockage différente. Une classe de stockage est toujours un pas plus faible qu'un type et peut être sauvegardée par plusieurs types. Alors oui, vous pouvez utiliser DATETIME. Non, il ne le prend pas en charge en tant que type ou classe de stockage. Oui, la documentation contient en fait le mot "DATETIME".
Jasper
20

SQLite n'a pas de classe de stockage réservée pour stocker les dates et / ou les heures. Au lieu de cela, les fonctions de date et d'heure intégrées de SQLite sont capables de stocker des dates et des heures sous forme de valeurs TEXT, REAL ou INTEGER:

TEXTE sous forme de chaînes ISO8601 ("AAAA-MM-JJ HH: MM: SS.SSS"). REAL comme le nombre de jours juliens, le nombre de jours depuis midi à Greenwich le 24 novembre 4714 avant JC selon le calendrier grégorien prolptique. INTEGER comme heure Unix, le nombre de secondes depuis le 01/01/1970 à 00:00:00 UTC. Les applications peuvent choisir de stocker les dates et les heures dans n'importe lequel de ces formats et de convertir librement entre les formats à l'aide des fonctions de date et d'heure intégrées.

Cela dit, j'utiliserais INTEGER et stockerais les secondes depuis l'époque Unix (1970-01-01 00:00:00 UTC).

Diego Torres Milan
la source
1
Je préfère cela aussi. Les classes standard liées à la date / heure sont de toute façon soutenues en interne par des longs, et il est assez facile de comparer les longs.
Karakuri
1
@dtmilano Pourquoi préférez-vous INTEGER ici au lieu d'une chaîne?
IgorGanapolsky
1
INTEGER utilise seulement 8 octets, TEXT utilise 23 octets dans cet exemple. Ce n'est pas clair comment choisir le type dans lequel les données sont stockées. Cela signifie-t-il que si je crée une colonne de type INTEGER, les fonctions seront automatiquement stockées sous Unix Time?
rayzinnz
2
REAL utilise également 8 octets. Les secondes d'époque seront de 10 chiffres jusqu'à la fin de 2286, et comme IEEE double prend en charge 15 à 17 chiffres significatifs , cela vous donne une résolution supérieure à la milliseconde. RSQLitesemble se convertir POSIXctà l'époque numérique, donc cela fonctionne assez bien pour moi.
r2evans le
@ r2evans Je ne suis pas sûr de ce que vous dites. Si je veux stocker des millisecondes depuis l'époque, comment puis-je faire cela?
Michael
14

L'une des fonctionnalités puissantes de SQLite vous permet de choisir le type de stockage. Avantages / inconvénients de chacune des trois possibilités:

  • Chaîne ISO8601

    • La comparaison de chaînes donne des résultats valides
    • Stocke les fractions de seconde, jusqu'à trois chiffres décimaux
    • Besoin de plus d'espace de stockage
    • Vous verrez directement sa valeur lors de l'utilisation d'un navigateur de base de données
    • Besoin d'analyse pour d'autres utilisations
    • Le modificateur de colonne "default current_timestamp" sera stocké en utilisant ce format
  • Nombre réel

    • Haute précision concernant la fraction de seconde
    • Plage de temps la plus longue
  • Nombre entier

    • Espace de stockage le plus bas
    • Opérations rapides
    • Petite plage de temps
    • Problème possible de l'année 2038

Si vous avez besoin de comparer différents types ou d'exporter vers une application externe, vous êtes libre d'utiliser les propres fonctions de conversion datetime de SQLite si nécessaire.

Zso
la source
1
Pourquoi y a-t-il un problème 2038? INTEGER semble prendre en charge le stockage 64 bits.
guan boshen
1
@guanboshen Autant que je sache, la seule raison de s'inquiéter pour 2038 serait le support sur la plate-forme hôte. La documentation SQLite prétend utiliser des C localtime_r()( sqlite.org/lang_datefunc.html#caveats_and_bugs ) dans l'implémentation de référence, et localtime()peut potentiellement être vulnérable à 2038 si la plate-forme hôte a un fichier 32 bits time_t. Cela dit, étant donné que SQLite prétend se prémunir contre cette possibilité en mappant des dates extérieures dans une plage sûre avant la conversion (voir le même lien), je pense que cela ne posera probablement pas de problème, sauf peut-être dans des cas ésotériques.
Zoë Sparks le
@ ZoëSparks Merci pour cette clarification.
guan boshen le
7

Pour pratiquement toutes les questions de date et d'heure, je préfère simplifier les choses, très, très simple ... Jusqu'à quelques secondes stockées en nombres entiers.

Les entiers seront toujours pris en charge en tant que nombres entiers dans les bases de données, les fichiers plats, etc. Vous faites un peu de calcul et le transtypez dans un autre type et vous pouvez formater la date comme vous le souhaitez.

En procédant de cette façon, vous n'avez pas à vous inquiéter lorsque [insérer la base de données favorite actuelle ici] est remplacé par [future base de données préférée] qui, par coïncidence, n'utilisait pas le format de date que vous avez choisi aujourd'hui.

C'est juste un peu de surcharge mathématique (par exemple, les méthodes - prend deux secondes, je posterai un résumé si nécessaire) et simplifie les choses pour de nombreuses opérations concernant la date / heure plus tard.

KelvinEWilliams
la source
7

Stockez-le dans un champ de type long. Voir Date.getTime()etnew Date(long)

koem
la source
comment puis-je le comparer ?? pouvez-vous me donner un échantillon de requête ..: D
Khairil Ushan
Regardez Joda Time pour des comparaisons dans le code ( joda-time.sourceforge.net ) et utilisez une simple comparaison longue en SQL (par exemple une comparaison numérique).
Syntaxe
sélectionnez * dans le tableau où création entre a et b;
koem