Come funzionano i valori DATETIME in SQLite?


110

Sto creando app Android e devo salvare la data / ora del record di creazione. I documenti SQLite dicono, tuttavia, "SQLite non dispone di una classe di archiviazione riservata per memorizzare date e / o ore" ed è "in grado di memorizzare date e ore come valori TEXT, REAL o INTEGER".

C'è una ragione tecnica per utilizzare un tipo rispetto a un altro? E una singola colonna può memorizzare le date in uno dei tre formati da riga a riga?

Avrò bisogno di confrontare le date più tardi. Ad esempio, nelle mie app mostrerò tutti i record creati tra la data A e la data B. Sono preoccupato che non avere una vera colonna DATETIME possa rendere difficili i confronti.


Risposte:


83

SQlite non ha un tipo di data e ora specifico. Puoi usare TEXT, REALoINTEGER tipi, a seconda delle tue esigenze.

Direttamente dai DOCS

SQLite non dispone di una classe di archiviazione riservata per la memorizzazione di date e / o orari. Invece, le funzioni di data e ora integrate di SQLite sono in grado di memorizzare date e ore come valori TEXT, REAL o INTEGER:

  • TESTO come stringhe ISO8601 ("AAAA-MM-GG HH: MM: SS.SSS").
  • REALE come i numeri del giorno giuliano, il numero di giorni trascorsi da mezzogiorno a Greenwich il 24 novembre 4714 a.C. secondo il prolettico calendario gregoriano.
  • INTEGER come Unix Time, il numero di secondi dal 1970-01-01 00:00:00 UTC.

Le applicazioni possono scegliere di memorizzare date e ore in uno qualsiasi di questi formati e di convertire liberamente tra i formati utilizzando le funzioni di data e ora integrate.

Le funzioni di data e ora integrate di SQLite possono essere trovate qui .


11
Importante da notare: tutti i metodi di memorizzazione delle date utilizzano formati che possono essere confrontati utilizzando gli operatori standard =, <,> e BETWEEN.
Larry Lustig

2
"SQLite non ha una classe di archiviazione riservata per la memorizzazione di date e / o orari" - tranne che ha i tipi DATE e DATETIME che non sono mai menzionati nella documentazione
Slabko

12
@Slabko Non lo fa. SQLite consente qualsiasi cosa (incluso DATETIME) come tipo dichiarato di una colonna. Sulla base di ciò, fornisce a quella colonna un'affinità con una classe di archiviazione (ha anche l'esempio di come funziona per DATETIME nella documentazione). Questa affinità è più simile a un suggerimento, poiché ogni voce della colonna può effettivamente avere una classe di archiviazione diversa. Una classe di archiviazione è ancora un passo più debole di un tipo e può essere supportata da più tipi. Quindi sì, puoi usare DATETIME. No, in realtà non lo supporta come tipo o classe di archiviazione. Sì, la documentazione contiene effettivamente la parola "DATETIME".
Jasper

20

SQLite non dispone di una classe di archiviazione riservata per la memorizzazione di date e / o orari. Invece, le funzioni di data e ora integrate di SQLite sono in grado di memorizzare date e ore come valori TEXT, REAL o INTEGER:

TESTO come stringhe ISO8601 ("AAAA-MM-GG HH: MM: SS.SSS"). REALE come i numeri del giorno giuliano, il numero di giorni trascorsi da mezzogiorno a Greenwich il 24 novembre 4714 a.C. secondo il prolettico calendario gregoriano. INTEGER come Unix Time, il numero di secondi dal 1970-01-01 00:00:00 UTC. Le applicazioni possono scegliere di memorizzare date e ore in uno qualsiasi di questi formati e di convertire liberamente tra i formati utilizzando le funzioni di data e ora integrate.

Detto questo, userei userei INTEGER e memorizzerei i secondi dall'epoca di Unix (1970-01-01 00:00:00 UTC).


1
Anch'io lo preferisco. Le classi standard relative a data / ora sono comunque supportate internamente da long ed è abbastanza facile confrontare i long.
Karakuri

1
@dtmilano Perché preferisci INTEGER qui invece di una stringa?
IgorGanapolsky

1
INTEGER utilizza solo 8 byte, TEXT utilizza 23 byte in questo esempio. Non è chiaro come scegliere in quale tipo memorizzare i dati. Significa che se creo una colonna di tipo INTEGER, le funzioni verranno automaticamente memorizzate come Unix Time?
rayzinnz

2
REAL utilizza anche 8 byte. I secondi dell'epoca saranno di 10 cifre fino alla fine del 2286 e poiché il doppio IEEE supporta 15-17 cifre significative , ciò offre una risoluzione migliore del millisecondo. RSQLitesembra che si stia convertendo POSIXctin epoca numerica, quindi funziona abbastanza bene per me.
r2evans

@ r2evans Non sono sicuro di quello che stai dicendo. Se voglio memorizzare millisecondi da Epoch, come posso farlo?
Michael

14

Una delle potenti funzionalità di SQLite ti consente di scegliere il tipo di archiviazione. Vantaggi / svantaggi di ciascuna delle tre diverse possibilità:

  • Stringa ISO8601

    • Il confronto tra stringhe fornisce risultati validi
    • Memorizza frazioni di secondo, fino a tre cifre decimali
    • Ha bisogno di più spazio di archiviazione
    • Vedrai direttamente il suo valore quando utilizzi un browser di database
    • Necessità di analisi per altri usi
    • Il modificatore di colonna "default current_timestamp" memorizzerà utilizzando questo formato
  • Numero reale

    • Alta precisione per quanto riguarda le frazioni di secondo
    • Intervallo di tempo più lungo
  • Numero intero

    • Spazio di archiviazione più basso
    • Operazioni rapide
    • Piccolo intervallo di tempo
    • Possibile problema dell'anno 2038

Se è necessario confrontare diversi tipi o esportare in un'applicazione esterna, sei libero di utilizzare le funzioni di conversione datetime di SQLite secondo necessità.


1
Perché c'è il problema 2038? INTEGER sembra supportare l'archiviazione a 64 bit.
guan boshen

1
@guanboshen Per quanto ne so, l'unico motivo per preoccuparsi del 2038 sarebbe il supporto sulla piattaforma host. La documentazione di SQLite afferma di utilizzare C localtime_r()( sqlite.org/lang_datefunc.html#caveats_and_bugs ) nell'implementazione di riferimento e localtime()può essere potenzialmente vulnerabile a 2038 se la piattaforma host ha un file a 32 bit time_t. Detto questo, dal momento che SQLite afferma di proteggersi da questa possibilità mappando le date esterne in una pre-conversione di intervallo sicuro (vedere lo stesso collegamento), penso che sia improbabile che sia un problema tranne forse in casi esoterici.
Zoë Sparks il

@ ZoëSparks Grazie per il chiarimento.
guan boshen,

7

Praticamente per tutte le questioni relative a data e ora preferisco semplificare le cose, molto, molto semplici ... Fino a secondi memorizzati in numeri interi.

I numeri interi saranno sempre supportati come numeri interi nei database, nei file flat, ecc. Fai un po 'di matematica e trasformali in un altro tipo e puoi formattare la data come preferisci.

In questo modo, non devi preoccuparti quando [inserisci il database preferito corrente qui] viene sostituito con [database preferito futuro] che casualmente non ha utilizzato il formato della data che hai scelto oggi.

È solo un piccolo sovraccarico di matematica (es. Metodi - richiede due secondi, posterò un riassunto se necessario) e semplifica le cose per molte operazioni relative a data / ora in seguito.


7

Conservalo in un campo di tipo long. Vedi Date.getTime()enew Date(long)


come posso confrontarlo ?? puoi darmi un esempio di query ..: D
Khairil Ushan

Guarda Joda Time per i confronti nel codice ( joda-time.sourceforge.net ) e usa un semplice confronto lungo in SQL (es. Confronto numerico).
Sintassi

seleziona * dalla tabella dove creazione tra a e b;
koem
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.