日期应该存储为日期时间还是 SQL 中的 int?
Posted
技术标签:
【中文标题】日期应该存储为日期时间还是 SQL 中的 int?【英文标题】:Should Dates be Stored as a Datetime or as an int in SQL? 【发布时间】:2009-03-31 17:28:20 【问题描述】:我在日期时间 (0000-00-00 00:00:00) 中存储我在论坛中发帖的所有日期。 我看到 phpBB、punBB 和所有流行的论坛都将日期存储在 int 中?
什么更好?
【问题讨论】:
【参考方案1】:如果您将日期存储为 INT,那么每个连接到您的数据库的应用程序或工具都必须知道如何将该 INT 转换为有意义的东西。我建议坚持使用适合数据的数据类型,除非您的特定 RDBMS 对特定数据类型存在严重缺陷。
还有一个需要考虑的问题...如果您将它们存储为 INT,那么您还将无法访问许多特定于日期的函数,并且必须自己编写它们。例如,返回特定日期的日期名称(星期一、星期二等)。
【讨论】:
您可以随时向其他应用程序提供视图可以正确转换 INT 日期 也许吧,但由于日期往往相当普遍,因此会产生大量视图和额外维护,只是为了支持一些对我来说没有明确意义的东西。 @mike:以语言专有的 int 格式存储日期并提供代表真正本机类型的视图有什么意义?如果有的话,将它们存储为 DateTimes 并提供一个以专有 int 格式表示日期的视图会更合理。 这个建议的问题是你可能使用了几种语言、dbms 产品和其他工具,它们都有不兼容的日期时间转换,并最终在它们之间编写映射库(虽然大多数都有可用的整数转换 - 参见 mysql 的 UNIX_TIMESTAMP() 函数。【参考方案2】:我不确定是否有“更好”的答案。但我会推荐日期时间,因为如果你将它们存储为 int,你可能会遇到Year 2038 issue.
【讨论】:
不要忘记 10000 年的问题:在这一点上,所述格式的日期不再具有词法可比性 ;-) 哈哈!如果我的软件在 7991 年后还能运行,人类就完蛋了。【参考方案3】:我对所有时间字段都使用 DATETIME(并且,使用 MySQL,我总是,总是避免使用 TIMESTAMP)。不过,我使用的一个技巧是将列设置为 NULL DEFAULT NULL。这样,对于我认为日期为空或空白的情况,我无需担心或检查“0000-00-00 00:00:00”;我只检查IS NULL
。
我能想到过去人们可能考虑将 INT 用于他们的日期列的唯一原因是因为有一次,MySQL 在内部将 DATETIME(以及 DATE 和 TIME)实现为字符串。在这种情况下,DATETIME 字段将比 INT 字段大得多,因此如果空间是一个问题,我可以看到正在做出该决定。如今,情况已不再如此(我会说 MySQL 4.x 及更高版本),没有充分的理由不再选择 DATETIME。
【讨论】:
【参考方案4】:此外,前纪元日期也存在问题。在 INT 中保留成员出生日期之类的信息很困难,因为有些成员可能出生在 1970 年 1 月 1 日之前。
【讨论】:
【参考方案5】:如今,大多数 DBMS 都允许您对真实的日期时间字段进行更时髦的查询。使用可用于日期操作和查询的函数,很难证明使用整数是合理的。
我想大多数 BB 系统都使用 INT,因为它们更容易在多个数据库引擎中实现,如果您只关心日期部分而不是时间部分,那么您可能会从 INT 中获得稍微更好的性能,而不是到日期时间(通常是 8 字节浮点数)。
就我个人而言,我更喜欢将日期存储在日期时间字段中,因为我几乎从不从一个数据库平台迁移到另一个数据库平台,例如,向数据库询问每个月的最后一个星期五是有好处的。
【讨论】:
【参考方案6】:最佳答案是“视情况而定”。如果没有其他信息,我会说 datetime 更好。我认为这些论坛的实现是未能识别更好、更成熟的数据类型。你必须想出一个很好的理由来解释为什么你想要整数超过日期。也许他们有,我只是不知道。
【讨论】:
【参考方案7】:在内部,日期时间是一个整数,从某个纪元开始的秒数或毫秒数,通常是 1970 年 1 月 1 日午夜的 linux 纪元。
但它允许您使用各种美妙的日期函数来添加、减去和分解时间间隔,这是您无法使用 int 完成的(无需自己重写所有这些函数)。
因此,通过使用日期/日期时间而不是 int,您不会失去任何东西,并且会像其他人回答的那样获得很多。
【讨论】:
【参考方案8】:我使用将日期存储为 int 的数据仓库,例如20090331 格式。然后有一个表格专门用于将该 int 转换为任何与日期相关的信息,包括日期时间表示。这提供了很大的灵活性,让我们可以添加额外的信息,例如季度编号、假期指定等。如果您需要除整数日期之外的任何内容,只需加入日期表即可。
select MyTable.Stuff,DimDate.AsDateTime,DimDate.BusinessQuarter,DimDate.IsHoliday from MyTable
inner join DimDate on MyTable.DateKey = DimDate.DateKey
【讨论】:
这不是一个整数。是的,但是它允许非法值,例如 20090332。而且它不容易映射,因为您必须跳过这些非法值才能将其映射到日期。这意味着您必须继续维护您的翻译/查找表。 是的,维护查找表很痛苦。但是您可以使用外键约束将整数限制为表中已有的值。您还可以定义 NextDay 和 PreviousDay 列,甚至是像 NextWorkDay 这样的复杂概念。【参考方案9】:SQL 2008 引入了“日期”数据类型,它小于完整的“日期时间”字段,如果您不需要时间部分(如果您正在考虑使用 INT,听起来您不需要反正不需要)。
详情请见this article。
【讨论】:
【参考方案10】:我想跟进 tpdi 的回答,并描述我多次以两种方式完成的经历。
当使用整数时,它是按照 tpdi 所描述的约定完成的——在 1970 年左右的某个时间点过去的给定秒数。
当许多生产软件至少部分用 C 编写时,这种模式是(UNIX 风格的)标准,并且为映射和日期计算提供了合理数量的函数。
上面没有过多讨论的一个问题是,按小时、分钟和秒进行的插值并不是所有语言和 DBMS 库都能很好地处理。基于整数的日期可以更好地处理此问题,而无需担心舍入错误 - 至少只要您不需要小于 1 秒的分辨率。不需要处理 0 之前的日期也很有帮助,尽管它可以在处理负整数时没有太多麻烦。
最后的好处可能是大多数语言/DBMS 都具有处理这种约定的功能,这使得使用多种语言和 DBMS 产品变得更加容易,并且兼容性问题更少。
在某些合理的情况下,它就像@tpdi 所描述的那样;但它也可以完全颠覆 - 如果它们适合您的上下文,您可能会通过处理整数日期时间的库失去精度和跨语言兼容性。
【讨论】:
【参考方案11】:我会使用 Datetime,除非有 other dates 和可能的 times 可以更好地存储为 int。
【讨论】:
【参考方案12】:仅供参考,如果您使用 int/timestamp,那么您仍然可以获得您的 RDBMS 可以为日期/时间提供的所有功能。例如,在 MySQL 中,FROM_UNIXTIME(timestamp)
采用整数时间戳并返回 DATETIME
,然后您可以随意使用。
对于冗长的讨论,没有比 Drupal 项目的优秀人员更好的了:http://groups.drupal.org/node/731
希望这会有所帮助。
【讨论】:
这不是真的:尝试表示 1970 年之前的日期。你不能以上是关于日期应该存储为日期时间还是 SQL 中的 int?的主要内容,如果未能解决你的问题,请参考以下文章