DATETIME值在SQLite中如何工作?


110

我正在创建Android应用,并且需要保存创建记录的日期/时间。SQLite文档说,但是,“ SQLite没有为存储日期和/或时间预留存储类”,并且“能够将日期和时间存储为TEXT,REAL或INTEGER值”。

是否出于技术原因使用一种类型而不是另一种类型?而且,单列可以行与行之间的三种格式中的任何一种存储日期吗?

我稍后需要比较日期。例如,在我的应用程序中,我将显示在日期A到日期B之间创建的所有记录。我担心没有真实的DATETIME列会导致比较困难。


Answers:


83

SQlite没有特定的日期时间类型。您可以使用TEXTREALINTEGER类型,无论适合您的需要。

直接来自DOCS

SQLite没有为存储日期和/或时间预留存储类。相反,SQLite内置的日期和时间函数可以将日期和时间存储为TEXT,REAL或INTEGER值:

  • 文本为ISO8601字符串(“ YYYY-MM-DD HH:MM:SS.SSS”)。
  • 实际为儒略日数,根据公历前的公历,公元前4714年11月24日格林威治中午以来的天数。
  • INTEGER as Unix Time,自1970-01-01 00:00:00 UTC以来的秒数。

应用程序可以选择以任何一种格式存储日期和时间,并使用内置的日期和时间功能在格式之间自由转换。

SQLite内置的日期和时间函数可以在此处找到


11
重要说明-所有存储日期的方法都使用可以通过标准=,<,>和BETWEEN运算符进行比较的格式。
拉里·卢斯蒂格

2
“ SQLite没有预留用于存储日期和/或时间的存储类”-除非它确实具有DATE和DATETIME类型,这些类型在文档中从未提及
Slabko

12
@Slabko没有。SQLite允许任何内容(包括DATETIME)作为列的声明类型。基于此,它为该列提供了与存储类的相似性(甚至在文档中提供了有关DATETIME的工作方式的示例)。这种亲和力更像是一个提示,因为该列的每个条目实际上可以具有不同的存储类。存储类仍然比某个类型弱一步,并且可以由多种类型支持。因此,可以使用DATETIME。不,它实际上不支持将其作为类型或存储类。是的,文档中实际上包含单词“ DATETIME”。
贾斯珀(Jasper)

20

SQLite没有为存储日期和/或时间预留存储类。相反,SQLite内置的日期和时间函数可以将日期和时间存储为TEXT,REAL或INTEGER值:

文本为ISO8601字符串(“ YYYY-MM-DD HH:MM:SS.SSS”)。实际为儒略日数,根据公历前的公历,公元前4714年11月24日格林威治中午以来的天数。INTEGER as Unix Time,自1970-01-01 00:00:00 UTC以来的秒数。应用程序可以选择以任何一种格式存储日期和时间,并使用内置的日期和时间功能在格式之间自由转换。

话虽如此,我将使用INTEGER并存储自Unix纪元(1970年1月1日00:00:00 UTC)以来的秒数。


1
我也喜欢这个。无论如何,标准的与日期/时间相关的类在内部都由long支持,并且比较long很容易。
Karakuri

1
@dtmilano为什么在这里更喜欢INTEGER而不是String?
IgorGanapolsky 2014年

1
在此示例中,INTEGER仅使用8个字节,TEXT使用23个字节。目前尚不清楚如何选择存储数据的类型。这是否意味着如果我创建一个INTEGER类型的列,这些函数将自动存储为Unix Time?
rayzinnz's

2
REAL也使用8个字节。到2286年末,纪元秒将是10位数字,并且由于IEEE双重支持15-17位有效数字,因此比毫秒分辨率更好。RSQLite似乎正在转换POSIXct为数字时代,所以对我来说效果很好。
r2evans '16

@ r2evans我不确定您在说什么。如果我想存储自纪元以来的毫秒数,该怎么办?
迈克尔

14

SQLite的强大功能之一是允许您选择存储类型。三种不同可能性的优点/缺点:

  • ISO8601字符串

    • 字符串比较给出有效结果
    • 存储小数秒,最多三位十进制数字
    • 需要更多的存储空间
    • 使用数据库浏览器时,您将直接看到其值
    • 需要解析其他用途
    • “默认current_timestamp”列修饰符将使用此格式存储
  • 实数

    • 关于分数秒的高精度
    • 最长的时间范围
  • 整数

    • 最小的存储空间
    • 快速操作
    • 时间范围短
    • 可能在2038年出现问题

如果您需要比较不同的类型或导出到外部应用程序,则可以根据需要随意使用SQLite 自己的日期时间转换函数


1
为什么会有2038问题?INTEGER似乎支持64位存储。
关博申

1
据我所知,@ guanboshen唯一担心2038的原因是对主机平台的支持。SQLite文档声称在参考实现中使用C localtime_r()sqlite.org/lang_datefunc.html#caveats_and_bugs),localtime()如果主机平台具有32位,则可能容易受到2038攻击time_t。就是说,由于SQLite声称通过将外部日期映射到安全范围内的预转换中来防止这种可能性(请参阅同一链接),所以我认为除非是在深奥的情况下,否则这不太可能成为问题。
Zoë的火花

@ZoëSparks谢谢您的澄清。
关博申

7

对于几乎所有的日期和时间问题,我都喜欢简化,非常非常简单...以整数形式存储的秒数。

在数据库,平面文件等中,始终将整数作为整数来支持。您可以做一点数学运算,然后将其转换为另一种类型,然后可以随时格式化日期。

这样做,您不必担心[偶然在这里插入当前喜欢的数据库]被[未来喜欢的数据库]替换了,巧合的是没有使用您今天选择的日期格式。

这只是数学上的一点点开销(例如,方法-需要两秒钟,如果需要,我将发布要点),并简化了以后有关日期/时间的许多操作。


7

将其存储在type字段中long。看到Date.getTime()new Date(long)


我该如何比较?您能给我查询的
例子吗?

查看Joda Time中的代码比较(joda-time.sourceforge.net),并在SQL中使用简单的长比较(例如,数值比较)。
语法

从a和b之间创建的表中选择*;
koem 2013年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.