【问题标题】:When to use VARCHAR and DATE/DATETIME何时使用 VARCHAR 和 DATE/DATETIME
【发布时间】:2011-06-13 03:22:49
【问题描述】:

我们在 Freenode 上进行了这个编程讨论,当我尝试使用 VARCHAR(255) 以这种格式存储日期变量时出现了这个问题:D/MM/YYYY。所以问题是为什么使用 VARCHAR 来存储日期如此糟糕。优点如下:

  1. 它的编码速度更快。以前我使用 DATE,但日期格式真的很痛苦。
  2. 使用字符串比使用日期更耗电?谁在乎,我们生活在 Ghz 时代。
  3. 这在道德上不正确(lolwut?)这是其他用户告诉我的...

那么您希望使用什么来存储日期? SQL VARCHAR 还是 SQL DATE?

【问题讨论】:

  • 显然,SQL 是第一种具有时间数据类型的语言(在此之前,每个人都使用文本来表示日期,而 Y2K 问题从未真正实现过,是吗?)这会侮辱 SQL 的设计者,至少其中一个是我在 Facebook 上的朋友,在适用时不要使用它们。
  • 好问题!我查看了答案。我已经使用了所有的建议。我不购买“始终使用日期类型列”的答案。使用 VARCHAR 列是有正当理由的。事实上,如果空间不是问题,使用数据类型的组合来存储日期时间值,您可能会找到最佳答案。

标签: sql date


【解决方案1】:

两个原因:

  • 按日期排序结果
  • 对日期格式更改不敏感

让我们以一组如下所示的记录为例:

5/12/1999 | Frank N Stein
1/22/2005 | Drake U. La
10/4/1962 | Goul Friend

如果我们按照您的方式存储数据,但按日期排序,SQL 将响应如下所示的结果集:

1/22/2005 | Drake U. La
10/4/1962 | Goul Friend
5/12/1999 | Frank N. Stein

如果我们将日期存储为 DATETIME,SQL 将按如下方式正确响应:

10/4/1962 | Goul Friend
5/12/1999 | Frank N. Stein
1/22/2005 | Drake U. La

此外,如果您需要以不同的格式显示日期,例如 YYYY-MM-DD,那么您需要转换所有数据或处理混合内容。当它存储为 SQL DATE 时,您必须在代码中进行转换,并且很可能有一个地方可以更改格式以显示所有日期 - 免费。

【讨论】:

  • 在下面查看我对 ISO 8601 的回答。
  • 这绝对不是一个原因。使用适当的日期格式,例如yyyy/MM/dd HH:mm:ss.SSS,这些值绝对是可排序的。我真正喜欢在数据库中使用字符串作为日期的原因是它们易于阅读,无论您在哪个时区阅读它们。我只是确保我将 UTC 日期时间以字符串形式放置,然后不管在哪里那个数据库在世界上,我知道那个时候是什么时候。显示实际日期时间值(而不是看起来像它们的字符串)的数据库工具喜欢将值转换为您的本地时间,这并不总是有帮助。
  • @Dale,不要误以为数据总是以相同的日期格式插入。我曾在许多已经使用了十多年的系统上工作过。有人会有改变某些东西的好主意,他们会假设数据库中的格式实际上是日期时间类型......因为这是正确的做法。
  • @Berin 谢谢。 :-) 我同意,但是添加具有不同日期格式的数据将是一个错误,而不是一个好主意,除非花时间将所有现有数据更新为新格式,并调整所有依赖于的现有逻辑旧格式,同时。
  • 啊,您没有任何要求来支持其他语言环境中的用户、计算日期之间的时间跨度或任何其他与日期有关的常见事情吗?就像一个非常基本的在正确的时区为用户显示时间戳。如果您正在构建玩具或概念验证,请做您想做的事。但是,如果您正在构建将在全球范围内使用的东西,那么请使用可以帮助您做到这一点的工具。
【解决方案2】:

为什么不用锤子把螺丝钉进去?

因为它不是适合这项工作的工具。

VARCHAR 版本的一些缺点:

  • 您无法轻松地在 VARCHAR 版本中添加/减去天数。
  • 很难仅提取月/年。
  • 没有什么能阻止您将非日期数据放入数据库的 VARCHAR 列中。
  • VARCHAR 版本是特定于文化的。
  • 您不能轻松地对日期进行排序。
  • 如果您想稍后更改格式,则很难。
  • 这是非常规的,这将使其他开发人员更难理解。
  • 在许多环境中,使用 VARCHAR 将使用更多存储空间。这对于少量数据可能无关紧要,但在具有数百万行数据的商业环境中,这可能会产生很大的不同。

当然,在您的爱好项目中,您可以随心所欲。在专业环境中,我会坚持使用正确的工具来完成工作。

【讨论】:

  • @Dercsár:确实。在某些情况下,将日期放入 VARCAR 也很有用。但一般不推荐。
  • @Matt:我父亲(他本人来自伯明翰)有时使用“Brummie 螺丝刀”这个词而不是“锤子”。我猜锤子司机的习惯已经传播到南方了? :-)
  • 您在工作中使用正确的工具是对的。除此之外,没有那么多 - 在我看来。
【解决方案3】:

DATE/DATETIMEVARCHAR 之间,我每次都会选择DATE/DATETIME。但是还有一个被忽视的第三个选项。将其存储为无符号整数!

我决定在我的上一个项目中使用INTEGER unsigned,我对做出这个选择而不是将其存储为DATE/DATETIME 感到非常满意。因为我在客户端和服务器之间传递日期,所以它是我使用的理想类型。不必将其存储为DATE 并且每次选择时都必须转换回来,我只需选择它并根据我的需要使用它。如果您想选择日期作为“人类可读”的日期,您可以使用FROM_UNIXTIME() 函数。

同样一个整数占用 4 个字节,而 DATETIME 占用 8 个字节。节省 50% 的存储空间。

Berin 提出的排序问题也是用整数作为日期的存储来解决的。

【讨论】:

  • 请注意,日期时间数据类型是一个整数(实际上是两个):最左边是自纪元以来的天数,最右边是自一天开始以来的毫秒滴答数( 00:00:00.000)。 SQL Server 日历的纪元(日历中的零点)是 1 January 1900 00:00:00.000 —这就是为什么convert(datetime,'') 会产生 1900 年 1 月 1 日的日期时间值。
【解决方案4】:

当您拥有超过 2-3 百万行的数据库时,您就会知道为什么使用 DATETIME 比使用 VARCHAR 更好:)

简单的答案是,使用数据库 - 处理能力不再是问题。只是数据库大小是因为 HDD 的寻道时间。

如果以随机顺序(通常是这种情况)读取现代硬盘,基本上每秒可以读取大约 100 条记录,因此您必须尽一切可能最小化数据库大小,因为:

  • HDD 的磁头不必“移动”这么多
  • 您将在 RAM 中放入更多数据

最后,总是 HDD 的寻道时间会杀死你。例如。在磁盘上完成一些包含许多行的简单 GROUP BY 查询可能需要几个小时,而在 RAM 中完成则需要几秒钟 => 因为查找时间。

对于 VARCHAR,您不能进行任何搜索。如果您非常讨厌 SQL 处理日期的方式,只需在 32 位整数字段中使用 unix 时间戳。您将(基本上)拥有使用 SQL DATE 字段的所有优势,您只需使用您选择的编程语言而不是 SQL 函数来操作和格式化日期。

【讨论】:

  • 当然,如果您将其存储在 32 位整数字段中,您还需要注意 Year 2038 problem
  • 感谢您的时代创意,操纵日期让我发疯:)
【解决方案5】:

我会投票支持使用日期/日期时间类型,只是为了简单/一致。

如果你将其存储为字符串,请将其存储为ISO 8601 格式:

除其他外,ISO 8601 日期/时间字符串 (A) 可正确整理,(B) 易于阅读,(C) 与语言环境无关,并且 (D) 可轻松转换为其他格式。 ISO 8601 字符串提供了 ISO 简介

以下陈述:

  • 日期
  • 一天中的时间
  • 协调世界时 (UTC)
  • 与 UTC 有偏移的本地时间
  • 日期和时间
  • 时间间隔
  • 重复的时间间隔

表示可以采用以下两种格式之一:基本格式 具有最少字符数和扩展格式 添加字符以增强人类可读性。例如, 2003 年 1 月的第三个可以表示为 20030103 或 2003-01-03。

[和]

与许多本地使用的产品相比,具有以下优势 表示:

  • 系统易于读写
  • 易于比较和分类
  • 语言无关
  • 较大的单位写在较小的单位前面
  • 对于大多数表示法来说,符号都很短且长度恒定

最后一件事:如果您需要做的只是存储日期,那么将其存储在 char(8) 列中的 ISO 8601 短格式 YYYYMMDD 所占用的存储空间不会超过日期时间值(而且您不需要担心一天的最后一个滴答声和下一天的第一个滴答声之间的 3 毫秒间隔。但这是另一个讨论的问题。如果你把它分成 3 列 - YYYY char(4), MM char(2), DD char(2) 你会用完相同的存储量,并获得更多索引选项。更好的是,将字段存储为 yyyy 的缩写(4 个字节),并为 MM 和 DD 分别存储一个 tinyint ——现在您的日期减少到 6 个字节。当然,将日期组件分解为其组成部分的缺点是转换为正确的日期/时间数据类型很复杂。

【讨论】:

  • 多么棒的答案!仅供参考,出于上述原因,我不止一次选择在数据库表中使用 VARCHAR。 (我还使用了日期类型的列,以及存储 UNIX 纪元时间 (?) 值的数字列)这一切都取决于问题。当我确实使用 VARCHAR 列时,我总是将时间存储在 UTC 中,因此在查看值时永远不会有任何混淆,并且总是直接转换为 Date 类型的对象。
猜你喜欢
  • 1970-01-01
  • 2018-05-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多