SQLite dapat menggunakan tipe data teks, nyata, atau bilangan bulat untuk menyimpan tanggal. Terlebih lagi, setiap kali Anda melakukan kueri, hasilnya ditampilkan menggunakan format %Y-%m-%d %H:%M:%S
.
Sekarang, jika Anda memasukkan / memperbarui nilai tanggal / waktu menggunakan fungsi tanggal / waktu SQLite, Anda sebenarnya dapat menyimpan milidetik juga. Jika itu masalahnya, hasilnya ditampilkan menggunakan format %Y-%m-%d %H:%M:%f
. Sebagai contoh:
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
Sekarang, lakukan beberapa pertanyaan untuk memverifikasi apakah kami benar-benar dapat membandingkan waktu:
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
Anda dapat memeriksa SELECT
menggunakan yang sama col2
dan col3
dan Anda akan mendapatkan hasil yang sama. Seperti yang Anda lihat, baris kedua (126 milidetik) tidak dikembalikan.
Perhatikan bahwa BETWEEN
itu inklusif, oleh karena itu ...
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');
... akan mengembalikan set yang sama.
Cobalah bermain-main dengan rentang tanggal / waktu yang berbeda dan semuanya akan berperilaku seperti yang diharapkan.
Bagaimana tanpa strftime
fungsi?
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
Bagaimana dengan tanpa strftime
fungsi dan tanpa milidetik?
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
Bagaimana dengan 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
Bekerja dengan baik.
Akhirnya, ketika berhadapan dengan operasi aktual dalam suatu program (tanpa menggunakan sqlite yang dapat dieksekusi ...)
BTW: Saya menggunakan JDBC (tidak yakin tentang bahasa lain) ... driver sqlite-jdbc v3.7.2 dari xerial - mungkin revisi yang lebih baru mengubah perilaku yang dijelaskan di bawah ini ... Jika Anda mengembangkan di Android, Anda tidak membutuhkan driver jdbc. Semua operasi SQL dapat dikirimkan menggunakan SQLiteOpenHelper
.
JDBC memiliki metode yang berbeda untuk mendapatkan nilai tanggal / waktu yang sebenarnya dari database: java.sql.Date
, java.sql.Time
, dan java.sql.Timestamp
.
Metode terkait di java.sql.ResultSet
yang (jelas) getDate(..)
, getTime(..)
dan getTimestamp()
masing-masing.
Sebagai contoh:
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.
Karena SQLite tidak memiliki tipe data DATE / TIME / TIMESTAMP yang sebenarnya, ketiga metode ini mengembalikan nilai seolah-olah objek diinisialisasi dengan 0:
new java.sql.Date(0)
new java.sql.Time(0)
new java.sql.Timestamp(0)
Jadi, pertanyaannya adalah: bagaimana kita dapat benar-benar memilih, menyisipkan, atau memperbarui objek Tanggal / Waktu / Stempel Waktu? Tidak ada jawaban yang mudah. Anda dapat mencoba kombinasi yang berbeda, tetapi mereka akan memaksa Anda untuk menanamkan fungsi SQLite di semua pernyataan SQL. Jauh lebih mudah untuk mendefinisikan kelas utilitas untuk mengubah teks menjadi objek Tanggal di dalam program Java Anda. Tetapi selalu ingat bahwa SQLite mengubah nilai tanggal apa pun menjadi UTC + 0000.
Singkatnya, meskipun aturan umum untuk selalu menggunakan tipe data yang benar, atau, bahkan bilangan bulat yang menunjukkan waktu Unix (milidetik sejak zaman), saya menemukan jauh lebih mudah menggunakan format SQLite default ( '%Y-%m-%d %H:%M:%f'
atau di Jawa 'yyyy-MM-dd HH:mm:ss.SSS'
) daripada mempersulit semua pernyataan SQL Anda dengan Fungsi SQLite. Pendekatan sebelumnya jauh lebih mudah untuk dipertahankan.
TODO: Saya akan memeriksa hasilnya ketika menggunakan getDate / getTime / getTimestamp di dalam Android (API15 atau lebih baik) ... mungkin driver internal berbeda dari sqlite-jdbc ...