如何比较 sqlite TIMESTAMP 值
Posted
技术标签:
【中文标题】如何比较 sqlite TIMESTAMP 值【英文标题】:How to compare sqlite TIMESTAMP values 【发布时间】:2011-02-25 05:22:05 【问题描述】:我有一个 Sqlite 数据库,我想在其中选择 TIMESTAMP 列中的值在某个日期之前的行。我认为这很简单,但我无法完成。我试过这个:
SELECT * FROM logged_event WHERE logged_event.CREATED_AT < '2010-05-28 16:20:55'
以及它的各种变体,例如日期函数。我已经阅读了http://sqlite.org/lang_datefunc.html 和http://www.sqlite.org/datatypes.html,我希望该列是数字类型,并且将在 unix 时间戳值上进行比较。显然不是。有谁能帮忙吗?如果这很重要,我会在 Sqlite Expert Personal 中进行尝试。
编辑:
这里是类型表说明:
CREATE TABLE [logged_event]
(
[id] INTEGER NOT NULL PRIMARY KEY,
[created_at] TIMESTAMP,
[name] VARCHAR(64),
[data] VARCHAR(512)
);
以及测试数据:
INSERT INTO table VALUES(1,'2010-05-28T15:36:56+0200','test','test');
INSERT INTO table VALUES(2,'2010-05-28T16:20:49+0200','test','test');
INSERT INTO table VALUES(3,'2010-05-28T16:20:51+0200','test','test');
INSERT INTO table VALUES(4,'2010-05-28T16:20:52+0200','test','test');
INSERT INTO table VALUES(5,'2010-05-28T16:20:53+0200','test','test');
INSERT INTO table VALUES(6,'2010-05-28T16:20:55+0200','test','test');
INSERT INTO table VALUES(7,'2010-05-28T16:20:57+0200','test','test');
【问题讨论】:
你运行的是什么版本的 SQLite? 3.x.x 文档没有定义名为 TIMESTAMP 的列在类型关联中被强制转换为什么。 sqlite.org/datatype3.html Sqlite 3. 因为不在有限文本类型(TEXT、BLOB 等)中的所有内容都是数字的,根据文档,我假设 TIMESTAMP 将是数字类型。值得注意的是,我是通过 Propel ORM 映射器创建这个表的,它是一个自动生成的表,所以我不能轻易切换到另一种类型。我想如果我能让这个专栏表现得像 DATETIME,我就成功了。 【参考方案1】:问题在于您向表中插入数据的方式:+0200
语法与 SQLite's time formats 中的任何一个都不匹配:
-
YYYY-MM-DD
YYYY-MM-DD HH:MM
YYYY-MM-DD HH:MM:SS
YYYY-MM-DD HH:MM:SS.SSS
YYYY-MM-DDTHH:MM
YYYY-MM-DDTHH:MM:SS
YYYY-MM-DDTHH:MM:SS.SSS
HH:MM
HH:MM:SS
HH:MM:SS.SSS
现在
DDDDDDDDDD
将其更改为使用 SS.SSS 格式可以正常工作:
sqlite> CREATE TABLE Foo (created_at TIMESTAMP);
sqlite> INSERT INTO Foo VALUES('2010-05-28T15:36:56+0200');
sqlite> SELECT * FROM Foo WHERE foo.created_at < '2010-05-28 16:20:55';
sqlite> SELECT * FROM Foo WHERE DATETIME(foo.created_at) < '2010-05-28 16:20:55';
sqlite> INSERT INTO Foo VALUES('2010-05-28T15:36:56.200');
sqlite> SELECT * FROM Foo WHERE DATETIME(foo.created_at) < '2010-05-28 16:20:55';
2010-05-28T15:36:56.200
如果您在插入时绝对无法更改格式,您可能不得不回退到做一些“聪明”的事情并修改实际的字符串(即用.
替换+
等。 )。
(原答案)
您尚未描述CREATED_AT
列中包含哪些类型的数据。如果它确实是一个日期时间,它将正确地与一个字符串进行比较:
sqlite> SELECT DATETIME('now');
2010-05-28 16:33:10
sqlite> SELECT DATETIME('now') < '2011-01-01 00:00:00';
1
如果存储为unix时间戳,则需要调用DATETIME
函数,第二个参数为'unixepoch'
与字符串进行比较:
sqlite> SELECT DATETIME(0, 'unixepoch');
1970-01-01 00:00:00
sqlite> SELECT DATETIME(0, 'unixepoch') < '2010-01-01 00:00:00';
1
sqlite> SELECT DATETIME(0, 'unixepoch') == DATETIME('1970-01-01 00:00:00');
1
如果这些都不能解决您的问题(即使他们解决了!),您应该始终发布一些数据,以便其他人可以重现您的问题。您甚至应该随意提出仍然重现问题的原始数据的子集。
【讨论】:
是的,我也在手册中看到了这些示例。我想要做的是 SELECT * from table WHERE column 谢谢,确实是时区说明符做到了。 Sqlite Expert 未显示该部分加剧了这种情况 - 它仅在我执行命令行 SELECT 以在此处发布测试数据时出现。在我的程序中破解了一个解决方案,以省略时区部分。【参考方案2】:SQLite 对日期/时间类型的支持非常有限。您可能必须使用自己的方法来维护时间信息。至少,我就是这样做的。
您可以使用 SQLite create_function() API 定义自己的存储函数进行比较。
【讨论】:
请注意,我所涉及的问题涉及添加时间段,但不是比较。我认为马克的回答在这种情况下可能会更好。【参考方案3】:据我所知,包含时区说明符是完全合理的;见文本“格式 2 到 10 可以……”在http://www.sqlite.org/lang_datefunc.html 但是,问题在于只有日期函数将时间戳解释为日期。因此,对于实际比较,您需要通过日期函数传递时间戳或存储字符串比较有效的内容。 一种方法是对应用程序进行编码,以便对插入的每个值和 select 语句中的每个文字值调用 datetime。 但是,在许多应用程序中,不包括现有答案所建议的时区可能更容易。
【讨论】:
以上是关于如何比较 sqlite TIMESTAMP 值的主要内容,如果未能解决你的问题,请参考以下文章
如何将现有的 sqlite 表迁移到具有 VARCHAR、TIMESTAMP 等数据类型的 ROOM Db?