SQLite có thể sử dụng các kiểu dữ liệu văn bản, thực hoặc số nguyên để lưu trữ ngày. Thậm chí, bất cứ khi nào bạn thực hiện một truy vấn, kết quả được hiển thị bằng định dạng %Y-%m-%d %H:%M:%S
.
Bây giờ, nếu bạn chèn / cập nhật giá trị ngày / giờ bằng các hàm ngày / giờ SQLite, bạn thực sự có thể lưu trữ cả mili giây. Nếu đó là trường hợp, kết quả được hiển thị bằng cách sử dụng định dạng %Y-%m-%d %H:%M:%f
. Ví dụ:
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
Bây giờ, thực hiện một số truy vấn để xác minh xem chúng tôi có thực sự có thể so sánh thời gian không:
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
Bạn có thể kiểm tra tương tự SELECT
sử dụng col2
và col3
và bạn sẽ nhận được kết quả tương tự. Như bạn có thể thấy, hàng thứ hai (126 mili giây) không được trả lại.
Lưu ý rằng đã BETWEEN
bao gồm, do đó ...
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');
... sẽ trả lại cùng một bộ.
Hãy thử chơi xung quanh với các phạm vi ngày / giờ khác nhau và mọi thứ sẽ hoạt động như mong đợi.
Còn về strftime
chức năng thì sao?
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
Điều gì về không có strftime
chức năng và không có mili giây?
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
Thế còn 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
Hoạt động tốt.
Cuối cùng, khi xử lý các hoạt động thực tế trong một chương trình (không sử dụng tệp thực thi sqlite ...)
BTW: Tôi đang sử dụng JDBC (không chắc chắn về các ngôn ngữ khác) ... trình điều khiển sqlite-jdbc v3.7.2 từ xerial - có thể các phiên bản mới hơn thay đổi hành vi được giải thích bên dưới ... Nếu bạn đang phát triển trong Android, bạn không cần một trình điều khiển jdbc. Tất cả các hoạt động SQL có thể được gửi bằng cách sử dụng SQLiteOpenHelper
.
JDBC có phương pháp khác nhau để có được giá trị ngày / thời gian thực tế từ một cơ sở dữ liệu: java.sql.Date
, java.sql.Time
, và java.sql.Timestamp
.
Các phương pháp có liên quan trong java.sql.ResultSet
là (rõ ràng) getDate(..)
, getTime(..)
và getTimestamp()
tương ứng.
Ví dụ:
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.
Vì SQLite không có kiểu dữ liệu DATE / TIME / TIMESTAMP thực tế, cả 3 phương thức này trả về giá trị như thể các đối tượng được khởi tạo với 0:
new java.sql.Date(0)
new java.sql.Time(0)
new java.sql.Timestamp(0)
Vì vậy, câu hỏi là: làm thế nào chúng ta thực sự có thể chọn, chèn hoặc cập nhật các đối tượng Ngày / Thời gian / Dấu thời gian? Không có câu trả lời dễ dàng. Bạn có thể thử các kết hợp khác nhau, nhưng chúng sẽ buộc bạn nhúng các hàm SQLite trong tất cả các câu lệnh SQL. Việc định nghĩa một lớp tiện ích để chuyển đổi văn bản thành các đối tượng Date trong chương trình Java của bạn dễ dàng hơn nhiều. Nhưng luôn nhớ rằng SQLite biến đổi bất kỳ giá trị ngày nào thành UTC + 0000.
Tóm lại, mặc dù quy tắc chung là luôn sử dụng đúng loại dữ liệu hoặc thậm chí các số nguyên biểu thị thời gian Unix (mili giây kể từ epoch), tôi thấy dễ dàng hơn khi sử dụng định dạng SQLite mặc định ( '%Y-%m-%d %H:%M:%f'
hoặc trong Java 'yyyy-MM-dd HH:mm:ss.SSS'
) thay vì làm phức tạp tất cả các câu lệnh SQL của bạn Hàm SQLite. Cách tiếp cận trước đây là dễ dàng hơn nhiều để duy trì.
TODO: Tôi sẽ kiểm tra kết quả khi sử dụng getDate / getTime / getTimestamp bên trong Android (API15 hoặc tốt hơn) ... có thể trình điều khiển nội bộ khác với sqlite-jdbc ...