7

我想在数据库中使用 Long 数据类型来表示日期(自纪元以来的毫秒)。原因是使用 jdbc 驱动程序和 Oracle 引擎存储日期非常复杂。如果您在preparedStatement 中提交了错误的数据类型,它会将时间戳转换为日期(反之亦然),从而破坏您的索引,从而在最坏的情况下导致全表扫描。我不记得细节,但我知道有细节要记住。我不想记住细节。似乎只要存储日期(自纪元以来的毫秒)就可以在这里工作得很好,我没有什么可记住的。

请注意,我觉得时区只是表象。它不应该首先被存储。大多数公司都有只使用 UTC 的政策,但同样,这只是需要了解的更多信息。让我们都只存储自纪元以来的毫秒数,并在显示时向用户显示格式化为他们特定时区的毫秒。

编辑:似乎数百万美元的错误和浪费的生产力/混乱围绕时区和日期格式,以及疯狂的 jdbc 驱动程序日期转换/转换。让我们一劳永逸地消除它。

我现在意识到反对做我建议的另一个原因是我们可能想节省数据库中的空间。在这种情况下,我们可以从纪元开始有十秒甚至简单的“秒”。无论您想节省多少空间。

4

7 回答 7

2

我一直这样做。这种做法一再受到口头批评。我为这种做法辩护,因为我的系统(例如)在 DST 更改(二级航空公司预订系统)中幸存下来,而其他执行 DST 边界、国际或亚利桑那州航班持续时间计算的系统惨遭失败。日期算术(不一定是日历算术)变得容易得多。

在几乎所有主要的编程/网络语言中转换为显示都是微不足道的。事实上,整数 unix 纪元日期可以直接推送到网页,并允许 JavaScript 转换为本地时间,避免中间转换。

唯一不能正常工作的地方是日历算术:将 1 个月添加到1 月31 日。

于 2011-02-07T18:56:11.163 回答
2

可以使用整数或其他适当的类型来表示数据库中的日期/时间值。但是它确实引入了几个问题:

  • 所有使用数据库表的当前和未来 (!!!) 应用程序(Java 或其他)都需要在数据库整数和日期/时间值之间进行转换。

  • 如果您的 SQL 查询、SQL 存储过程或 SQL 触发器涉及相关列,它们可能需要进行转换。这使它们更加复杂/难以正确处理。此外,额外的复杂性可能会导致查询引擎回退到执行查询的较慢方式……因为查询优化器不了解您在做什么。

  • 使用整数表示日期将使人们更难对涉及日期列的表执行临时 SQL 查询。

编辑

是否通过将日期表示为整数来节省空间是特定于数据库的。IIRC,Oracle 将日期/时间值存储为原始整数。而且我希望任何体面的 RDBMS 都会这样做......无论是存储空间还是查询效率。

将日期/时间值存储为整数并不能解决时区问题。这是一个从根本上复杂的问题。

  • 在某些情况下,您希望日期或日期/时间表示绝对时间点。
  • 在其他情况下,您希望它表示相对于发生某些事件的地理位置/时区的时间点。
  • 在其他情况下,您希望表示相对于系统或用户位置的时间。

然后是粒度问题。(为了清楚起见,使用 ISO 日期语法)“1999”与“1999-01-01”或“1999-01-01T00:00:00”的含义相同吗?那么亚秒级精度呢?

关键是没有简单的 SQL 日期/时间(或整数)表示可以处理所有这些。我们看到的错误/问题/困难的根本原因是程序员在他们的实现中走捷径并且(更重要的是)他们的思维马虎。

编辑 2

由于各种数据库及其各自的 JDBC 驱动程序处理日期文字和关于时区的假设的方式不同,仍然存在许多问题。我不是 JDBC 和 SQL 标准方面的专家,但根本问题似乎是:

  • 数据库供应商尚未完全实现(例如)SQL-92 中指定的日期时间类型。
  • SQL 标准没有为日期时间文字指定单一语法,但允许数据库供应商特定的语法。
  • SQL 标准允许默认时区,没有任何标准方法来指定(甚至找出)它的默认值。更多供应商特定的解决方案。
  • JDBC 规范没有为应用程序提供获取或设置默认时区或选择日期时间文字语法的方法。

所有这些都为 Java 开发人员带来了一堆可移植性和配置问题。但是,我认为这并不比我们在 Java / RDBMS 应用程序的其他方面遇到的可移植性和配置问题更糟糕。如果完全抛弃 datetime 类型,你就会陷入一堆其他问题;看上面。

于 2010-07-18T01:21:44.123 回答
1

我能想到的原因是存储 1970 年 1 月 1 日 00:00:00 GMT 之前的日期和时间。

不过我能感觉到你的痛苦。Oracle 日期/日期时间处理在 JDBC 中很痛苦。不同版本的驱动甚至不一致!

我不得不说我在其他 JDBC 驱动程序(其他数据库供应商)中没有发现太多问题......

于 2010-07-17T23:46:19.570 回答
1

现在完全有问题。

除非您需要一些包含对日期列进行一些计算的查询,否则在这种情况下,数据库需要具有它可以理解的日期类型。

你可能不需要那个,所以你可以使用任何你喜欢的表示。

于 2010-07-17T23:48:12.830 回答
1

只需将 UTC 长(大整数)存储,并使 DB 列名表明它持有millis_since_epoch(也可以使用注释,但我不确定所有 DB 的支持注释)。通过这种方式,您可以毫无顾虑地将数据移动到任何数据库,数据可以在创建它的应用程序之外安全地解释(这就是数据库列名称如此重要的原因),并且您可以通过 UI 处理您需要的演示/区域.

于 2012-09-10T21:27:47.933 回答
0

问题是什么?你问有没有可能?这取决于您使用的数据库,但我认为大多数情况下都是可能的。我肯定已经在 Android 应用程序中使用 SQL lite 做到了这一点(如果你不熟悉的话,这些应用程序是用 Java 编写的)。

于 2010-07-17T23:46:31.213 回答
0

不使用日期数据类型的唯一问题是,如果您需要比较日期等操作,您可能必须在应用程序中将 Long 值转换为日期。您可以随心所欲地存储数据,表示层可能会出现更多问题并需要额外的代码。例如,填充日历等组件。

于 2010-07-17T23:51:23.520 回答