SQLite kann Text-, Real- oder Integer-Datentypen zum Speichern von Datumsangaben verwenden. Darüber hinaus werden die Ergebnisse bei jeder Abfrage im Format angezeigt %Y-%m-%d %H:%M:%S
.
Wenn Sie jetzt Datums- / Zeitwerte mithilfe von SQLite-Datums- / Uhrzeitfunktionen einfügen / aktualisieren, können Sie auch Millisekunden speichern. In diesem Fall werden die Ergebnisse im Format angezeigt %Y-%m-%d %H:%M:%f
. Beispielsweise:
sqlite> create table test_table(col1 text, col2 real, col3 integer);
sqlite> insert into test_table values (
strftime('%Y-%m-%d %H:%M:%f', '2014-03-01 13:01:01.123'),
strftime('%Y-%m-%d %H:%M:%f', '2014-03-01 13:01:01.123'),
strftime('%Y-%m-%d %H:%M:%f', '2014-03-01 13:01:01.123')
);
sqlite> insert into test_table values (
strftime('%Y-%m-%d %H:%M:%f', '2014-03-01 13:01:01.126'),
strftime('%Y-%m-%d %H:%M:%f', '2014-03-01 13:01:01.126'),
strftime('%Y-%m-%d %H:%M:%f', '2014-03-01 13:01:01.126')
);
sqlite> select * from test_table;
2014-03-01 13:01:01.123|2014-03-01 13:01:01.123|2014-03-01 13:01:01.123
2014-03-01 13:01:01.126|2014-03-01 13:01:01.126|2014-03-01 13:01:01.126
Führen Sie nun einige Abfragen durch, um zu überprüfen, ob wir die Zeiten tatsächlich vergleichen können:
sqlite> select * from test_table /* using col1 */
where col1 between
strftime('%Y-%m-%d %H:%M:%f', '2014-03-01 13:01:01.121') and
strftime('%Y-%m-%d %H:%M:%f', '2014-03-01 13:01:01.125');
2014-03-01 13:01:01.123|2014-03-01 13:01:01.123|2014-03-01 13:01:01.123
Sie können das gleiche SELECT
mit col2
und überprüfen col3
und erhalten die gleichen Ergebnisse. Wie Sie sehen können, wird die zweite Zeile (126 Millisekunden) nicht zurückgegeben.
Beachten Sie, dass dies BETWEEN
inklusive ist, daher ...
sqlite> select * from test_table
where col1 between
/* Note that we are using 123 milliseconds down _here_ */
strftime('%Y-%m-%d %H:%M:%f', '2014-03-01 13:01:01.123') and
strftime('%Y-%m-%d %H:%M:%f', '2014-03-01 13:01:01.125');
... gibt den gleichen Satz zurück.
Versuchen Sie, mit verschiedenen Datums- / Zeitbereichen herumzuspielen, und alles wird sich wie erwartet verhalten.
Was ist ohne strftime
Funktion?
sqlite> select * from test_table /* using col1 */
where col1 between
'2014-03-01 13:01:01.121' and
'2014-03-01 13:01:01.125';
2014-03-01 13:01:01.123|2014-03-01 13:01:01.123|2014-03-01 13:01:01.123
Was ist ohne strftime
Funktion und ohne Millisekunden?
sqlite> select * from test_table /* using col1 */
where col1 between
'2014-03-01 13:01:01' and
'2014-03-01 13:01:02';
2014-03-01 13:01:01.123|2014-03-01 13:01:01.123|2014-03-01 13:01:01.123
2014-03-01 13:01:01.126|2014-03-01 13:01:01.126|2014-03-01 13:01:01.126
Was ist mit ORDER BY
?
sqlite> select * from test_table order by 1 desc;
2014-03-01 13:01:01.126|2014-03-01 13:01:01.126|2014-03-01 13:01:01.126
2014-03-01 13:01:01.123|2014-03-01 13:01:01.123|2014-03-01 13:01:01.123
sqlite> select * from test_table order by 1 asc;
2014-03-01 13:01:01.123|2014-03-01 13:01:01.123|2014-03-01 13:01:01.123
2014-03-01 13:01:01.126|2014-03-01 13:01:01.126|2014-03-01 13:01:01.126
Funktioniert gut.
Schließlich, wenn es um tatsächliche Operationen innerhalb eines Programms geht (ohne die ausführbare SQLite-Datei zu verwenden ...)
Übrigens: Ich verwende JDBC (bei anderen Sprachen nicht sicher) ... den sqlite-jdbc-Treiber v3.7.2 von xerial - möglicherweise ändern neuere Versionen das unten erläuterte Verhalten ... Wenn Sie in Android entwickeln, tun Sie dies nicht brauche einen JDBC-Treiber. Alle SQL-Operationen können mit dem gesendet werden SQLiteOpenHelper
.
JDBC hat verschiedene Methoden aktuelle Datum / Zeit - Werte aus einer Datenbank zu erhalten: java.sql.Date
, java.sql.Time
, und java.sql.Timestamp
.
Die zugehörigen Verfahren in java.sql.ResultSet
sind (natürlich) getDate(..)
, getTime(..)
und getTimestamp()
jeweils.
Beispielsweise:
Statement stmt = ... // Get statement from connection
ResultSet rs = stmt.executeQuery("SELECT * FROM TEST_TABLE");
while (rs.next()) {
System.out.println("COL1 : "+rs.getDate("COL1"));
System.out.println("COL1 : "+rs.getTime("COL1"));
System.out.println("COL1 : "+rs.getTimestamp("COL1"));
System.out.println("COL2 : "+rs.getDate("COL2"));
System.out.println("COL2 : "+rs.getTime("COL2"));
System.out.println("COL2 : "+rs.getTimestamp("COL2"));
System.out.println("COL3 : "+rs.getDate("COL3"));
System.out.println("COL3 : "+rs.getTime("COL3"));
System.out.println("COL3 : "+rs.getTimestamp("COL3"));
}
// close rs and stmt.
Da SQLite keinen tatsächlichen Datentyp DATE / TIME / TIMESTAMP hat, geben alle diese 3 Methoden Werte zurück, als ob die Objekte mit 0 initialisiert worden wären:
new java.sql.Date(0)
new java.sql.Time(0)
new java.sql.Timestamp(0)
Die Frage ist also: Wie können wir Datums- / Zeit- / Zeitstempelobjekte tatsächlich auswählen, einfügen oder aktualisieren? Es gibt keine einfache Antwort. Sie können verschiedene Kombinationen ausprobieren, diese zwingen Sie jedoch dazu, SQLite-Funktionen in alle SQL-Anweisungen einzubetten. Es ist viel einfacher, eine Dienstprogrammklasse zu definieren, um Text in Datumsobjekte in Ihrem Java-Programm umzuwandeln. Denken Sie jedoch immer daran, dass SQLite einen beliebigen Datumswert in UTC + 0000 umwandelt.
Zusammenfassend lässt sich sagen, dass ich trotz der allgemeinen Regel, immer den richtigen Datentyp oder sogar Ganzzahlen zu verwenden, die die Unix-Zeit (Millisekunden seit der Epoche) angeben, die Verwendung des Standard-SQLite-Formats ( '%Y-%m-%d %H:%M:%f'
oder in Java 'yyyy-MM-dd HH:mm:ss.SSS'
) viel einfacher finde , als alle Ihre SQL-Anweisungen zu komplizieren SQLite-Funktionen. Der erstere Ansatz ist viel einfacher zu pflegen.
TODO: Ich werde die Ergebnisse überprüfen, wenn ich getDate / getTime / getTimestamp in Android (API15 oder besser) verwende ... vielleicht unterscheidet sich der interne Treiber von sqlite-jdbc ...