如何比较 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 值的主要内容,如果未能解决你的问题,请参考以下文章

BigQuery 比较 DATE 和 TIMESTAMP

如何将现有的 sqlite 表迁移到具有 VARCHAR、TIMESTAMP 等数据类型的 ROOM Db?

关于sqlite3 中的timestamp类型

java怎么比较timestamp

将 Gps 作为后台服务运行并将接收到的当前位置数据与 Sqlite 中的值进行比较?

SQLite - current_timestamp 没有返回正确的时间?