Wie funktionieren DATETIME-Werte in SQLite?

110

Ich erstelle Android-Apps und muss Datum und Uhrzeit des Erstellungsdatensatzes speichern. In den SQLite-Dokumenten heißt es jedoch: "In SQLite ist keine Speicherklasse zum Speichern von Datums- und / oder Uhrzeitangaben reserviert" und "Datums- und Uhrzeitangaben können als TEXT-, REAL- oder INTEGER-Werte gespeichert werden".

Gibt es einen technischen Grund, einen Typ einem anderen vorzuziehen? Und kann eine einzelne Spalte Daten in einem der drei Formate von Zeile zu Zeile speichern?

Ich muss die Daten später vergleichen. In meinen Apps werden beispielsweise alle Datensätze angezeigt, die zwischen Datum A und Datum B erstellt wurden. Ich befürchte, dass das Fehlen einer echten DATETIME-Spalte Vergleiche erschweren könnte.

Khairil Ushan
quelle

Antworten:

83

SQlite hat keinen bestimmten Datum / Uhrzeit-Typ. Sie können verwenden TEXT, REALoderINTEGER Arten, je nachdem , was Ihren Bedürfnissen entspricht.

Direkt aus dem DOCS

In SQLite ist keine Speicherklasse zum Speichern von Datum und / oder Uhrzeit reserviert. Stattdessen können die integrierten Datums- und Zeitfunktionen von SQLite Datums- und Uhrzeitangaben als TEXT-, REAL- oder INTEGER-Werte speichern:

  • TEXT als ISO8601-Zeichenfolgen ("JJJJ-MM-TT HH: MM: SS.SSS").
  • REAL als julianische Tageszahlen, die Anzahl der Tage seit Mittag in Greenwich am 24. November 4714 v. Chr. Nach dem proleptischen gregorianischen Kalender.
  • INTEGER als Unix-Zeit, die Anzahl der Sekunden seit 1970-01-01 00:00:00 UTC.

Anwendungen können Datums- und Uhrzeitangaben in einem dieser Formate speichern und mithilfe der integrierten Datums- und Uhrzeitfunktionen frei zwischen Formaten konvertieren.

Die in SQLite integrierten Datums- und Uhrzeitfunktionen finden Sie hier .

neo108
quelle
11
Wichtig zu beachten - Alle Methoden zum Speichern von Datumsangaben verwenden Formate, die mit den Operatoren standard =, <,> und BETWEEN verglichen werden können.
Larry Lustig
2
"SQLite hat keine Speicherklasse zum Speichern von Datum und / oder Uhrzeit reserviert" - außer es gibt DATE- und DATETIME-Typen, die in der Dokumentation nie erwähnt werden
Slabko
12
@ Slabko tut es nicht. SQLite erlaubt alles (einschließlich DATETIME) als deklarierten Spaltentyp. Auf dieser Grundlage erhält diese Spalte eine Affinität zu einer Speicherklasse (in der Dokumentation finden Sie sogar das Beispiel, wie dies für DATETIME funktioniert). Diese Affinität ist eher ein Hinweis, da jeder Eintrag in der Spalte tatsächlich eine andere Speicherklasse haben kann. Eine Speicherklasse ist immer noch einen Schritt schwächer als ein Typ und kann von mehreren Typen unterstützt werden. Also ja, Sie können DATETIME verwenden. Nein, es wird nicht als Typ oder Speicherklasse unterstützt. Ja, die Dokumentation enthält tatsächlich das Wort "DATETIME".
Jasper
20

In SQLite ist keine Speicherklasse zum Speichern von Datum und / oder Uhrzeit reserviert. Stattdessen können die integrierten Datums- und Zeitfunktionen von SQLite Datums- und Uhrzeitangaben als TEXT-, REAL- oder INTEGER-Werte speichern:

TEXT als ISO8601-Zeichenfolgen ("JJJJ-MM-TT HH: MM: SS.SSS"). REAL als julianische Tageszahlen, die Anzahl der Tage seit Mittag in Greenwich am 24. November 4714 v. Chr. Nach dem proleptischen gregorianischen Kalender. INTEGER als Unix-Zeit, die Anzahl der Sekunden seit 1970-01-01 00:00:00 UTC. Anwendungen können Datums- und Uhrzeitangaben in einem dieser Formate speichern und mithilfe der integrierten Datums- und Uhrzeitfunktionen frei zwischen Formaten konvertieren.

Trotzdem würde ich INTEGER verwenden und Sekunden seit der Unix-Epoche (1970-01-01 00:00:00 UTC) speichern.

Diego Torres Milano
quelle
1
Ich bevorzuge das auch. Die Standardklassen für Datum und Uhrzeit werden ohnehin intern von Longs unterstützt, und es ist ziemlich einfach, Longs zu vergleichen.
Karakuri
1
@dtmilano Warum bevorzugen Sie hier INTEGER anstelle eines Strings?
IgorGanapolsky
1
INTEGER verwendet nur 8 Bytes, TEXT verwendet in diesem Beispiel 23 Bytes. Dies ist nicht klar, wie der Typ ausgewählt werden soll, in dem die Daten gespeichert werden. Bedeutet dies, dass beim Erstellen einer Spalte vom Typ INTEGER die Funktionen automatisch als Unix-Zeit gespeichert werden?
Rayzinnz
2
REAL verwendet ebenfalls 8 Bytes. Die Epochensekunden werden bis Ende 2286 10 Stellen lang sein. Da IEEE Double 15-17 signifikante Stellen unterstützt , erhalten Sie eine Auflösung von mehr als Millisekunden. RSQLitescheint sich in eine POSIXctnumerische Epoche umzuwandeln , also funktioniert es gut genug für mich.
R2evans
@ r2evans Ich bin mir nicht sicher, was du sagst. Wie mache ich das, wenn ich Millisekunden seit der Epoche speichern möchte?
Michael
14

Eine der leistungsstarken Funktionen von SQLite ist die Auswahl des Speichertyps. Vor- / Nachteile jeder der drei verschiedenen Möglichkeiten:

  • ISO8601-Zeichenfolge

    • Der Zeichenfolgenvergleich liefert gültige Ergebnisse
    • Speichert Sekundenbruchteile mit bis zu drei Dezimalstellen
    • Benötigt mehr Speicherplatz
    • Sie sehen den Wert direkt, wenn Sie einen Datenbankbrowser verwenden
    • Parsing für andere Zwecke erforderlich
    • Der Spaltenmodifikator "default current_timestamp" wird in diesem Format gespeichert
  • Reelle Zahl

    • Hohe Präzision in Sekundenbruchteilen
    • Längste Zeitspanne
  • Ganzzahl

    • Niedrigster Speicherplatz
    • Schnelle Operationen
    • Kleiner Zeitbereich
    • Mögliches Problem des Jahres 2038

Wenn Sie verschiedene Typen vergleichen oder in eine externe Anwendung exportieren müssen, können Sie bei Bedarf die SQLite- eigenen Konvertierungsfunktionen für Datum und Uhrzeit verwenden .

Zso
quelle
1
Warum gibt es 2038 Problem? INTEGER scheint 64-Bit-Speicher zu unterstützen.
Guan Boshen
1
@guanboshen Soweit ich das beurteilen kann, wäre der einzige Grund, sich über 2038 Sorgen zu machen, die Unterstützung auf der Host-Plattform. Die SQLite-Dokumentation behauptet, Cslocaltime_r() ( sqlite.org/lang_datefunc.html#caveats_and_bugs ) in der Referenzimplementierung zu verwenden, und localtime()kann möglicherweise für 2038 anfällig sein, wenn die Hostplattform über 32-Bit verfügt time_t. Da SQLite behauptet, sich vor dieser Möglichkeit zu schützen, indem externe Daten einer Vorkonvertierung für einen sicheren Bereich zugeordnet werden (siehe denselben Link), ist es meines Erachtens unwahrscheinlich, dass dies ein Problem darstellt, außer vielleicht in esoterischen Fällen.
Zoë Sparks
@ ZoëSparks Vielen Dank für die Klarstellung.
Guan Boshen
7

Für praktisch alle Datums- und Zeitangelegenheiten ziehe ich es vor, Dinge zu vereinfachen, sehr, sehr einfach ... Bis auf Sekunden, die in ganzen Zahlen gespeichert sind.

Ganzzahlen werden in Datenbanken, Einfachdateien usw. immer als Ganzzahlen unterstützt. Sie rechnen ein wenig und wandeln sie in einen anderen Typ um. Sie können das Datum beliebig formatieren.

Auf diese Weise müssen Sie sich keine Sorgen machen, wenn [aktuelle Lieblingsdatenbank hier einfügen] durch [zukünftige Lieblingsdatenbank] ersetzt wird, die zufällig nicht das heute gewählte Datumsformat verwendet hat.

Es ist nur ein kleiner Rechenaufwand (z. B. Methoden - dauert zwei Sekunden, ich werde bei Bedarf eine Zusammenfassung veröffentlichen) und vereinfacht die Dinge für viele Operationen in Bezug auf Datum / Uhrzeit später.

KelvinEWilliams
quelle
7

Speichern Sie es in einem Feld vom Typ long. Siehe Date.getTime()undnew Date(long)

Koem
quelle
Wie kann ich es vergleichen?
Kannst du
Schauen Sie sich Joda Time für Vergleiche im Code an ( joda-time.sourceforge.net ) und verwenden Sie einen einfachen langen Vergleich in SQL (z. B. numerischen Vergleich).
Syntax
Wählen Sie * aus der Tabelle aus, in der die Erstellung zwischen a und b erfolgt.
Koem