我一直在寻找,我仍然无法理解这是如何工作的。
我知道SQLite不存储Date类型值,我们必须将它们格式化为TEXT。我已经这样做了,但我的问题是如何按日期删除它们?
因为如果我做DELETE * FROM TABLE WHERE COLUMN_DATE >= '09-05-2017'
,我会比较字符串而不是日期,所以我想比较不对。
我已经看到人们进行这种类型的比较,即使它是TEXT类型。我对我没有意义。
如果您使用规范文本格式并使用正确的语法,它将起作用,例如,
DELETE FROM TABLE WHERE COLUMN_DATE >= '2017-05-09'
在SQLite边日期比较/算术方面,更有效和更简单的方法是在SQLite中将日期存储为INT
s。
Android中的Date
实际上只是毫秒级以来的容器(自1970年1月1日以来的UTC时间以来的几毫秒),这是时区独立的。
SQLite中的INT
是根据列中的值自动选择的1,2,4,8字节数据类型。
为了在DB中存储数据时将Java Date
转换为SQLite INT
值,请使用getTime()
方法:
Date javaDate = ...;
long sqlDate = date.getTime();
要从SQLite中检索日期,请使用Cursor
的getLong()
方法并将其传递给Date(long)
构造函数:
SQLiteDatabase db = ...;
Cursor c = db.query(..);
long sqlDate = c.getLong(...);
Date javaDate = new Date(sqlDate);
例:
LocalDate ld = LocalDate.of( 2017 , Month.JANUARY , 23 ) ; // Or `LocalDate.parse`, or `LocalDate.now()`.
String sql = "DELETE * FROM tbl WHERE col >= '" + ld.toString() + "' ;" ;
请记住,SQLite was never meant to be a heavy-duty database,只是从文本写入文件的一步。因此,如果您需要复杂的日期时间支持,则应切换到更复杂的数据库。
正如您在问题中提到的那样,SQLite缺少正确的数据类型。对于存储日期时间类型,the documentation suggests three routes:(a)ISO 8601字符串,(b)表示朱利安日数的实数(我不建议这样),以及(c)存储自第一时刻的历元参考以来的秒数的整数在UTC中的1970年,如Answer by Abakumov所示(尽管你不应该使用那里显示的Date
类)。
您似乎正在跟踪仅限日期的值,而不是一天中的某个时间。所以我会使用ISO 8601文本:YYYY-MM-DD。
在解析/生成日期时间值时,Java中的java.time类型默认使用标准的ISO 8601格式。 Java中仅限日期的类是LocalDate
,缺少时间和缺少时区。
ZoneId z = ZoneId.of( "Africa/Tunis" ) ;
LocalDate today = LocalDate.now( z ) ;
指定日期。
LocalDate ld = LocalDate.parse( "2017-09-05" ) ; // Standard ISO 8601 format for input: YYYY-MM-DD.
标准ISO 8601格式的优点是字母顺序也恰好按时间顺序排列。
因此,您可以使用大于/小于逻辑来进行基于文本的比较。
String sql = "DELETE * FROM tbl WHERE col >= '" + ld.toString() + "' ;" ;
与其他两种方法相比的另一大优势:
java.time框架内置于Java 8及更高版本中。这些类取代了麻烦的旧legacy日期时间类,如java.util.Date
,Calendar
和SimpleDateFormat
。
现在在Joda-Time的maintenance mode项目建议迁移到java.time班。
要了解更多信息,请参阅Oracle Tutorial。并搜索Stack Overflow以获取许多示例和解释。规格是JSR 310。
您可以直接与数据库交换java.time对象。使用符合JDBC driver或更高版本的JDBC 4.2。不需要字符串,不需要java.sql.*
类。
从哪里获取java.time类?