我想在数据库中使用 Long 数据类型来表示日期(从纪元开始以毫秒为单位)。原因是使用 jdbc 驱动程序和 Oracle 引擎存储日期非常复杂。如果您在 preparedStatement 中提交了错误的数据类型,它会将时间戳转换为日期(反之亦然),从而破坏您的索引,从而在最坏的情况下导致全表扫描。 细节记不清了,但我知道有细节要记住。我不想记住细节。似乎只存储尽可能长的日期(自纪元以来的毫秒数)在这里就可以正常工作,我没有什么可记住的。
请注意,我觉得时区只是表象。它不应该首先存储。大多数公司都有只使用 UTC 的政策,但再次强调,这只是需要了解的更多信息。让我们只存储自纪元以来的毫秒数,并在显示时向用户显示格式化为他们特定时区的毫秒数。
编辑: 似乎数百万美元的错误和浪费的生产力/困惑围绕着时区和日期格式,以及疯狂的 jdbc 驱动程序日期转换/转换。让我们一劳永逸地摆脱它。
我现在意识到反对按照我的建议做的另一个原因是我们可能想节省数据库空间。在那种情况下,自纪元以来我们可以有十秒甚至简单的“秒”。无论您希望节省空间的程度如何。
最佳答案
您可以使用整数或其他一些适当的类型来表示数据库中的日期/时间值。然而,它确实引入了几个问题:
所有使用数据库表的当前和 future (!!!) 应用程序(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 类型,您会遇到很多其他问题;见上文。
关于java - 在数据库中,为什么我们不能只使用 "Long"整数作为日期(自纪元以来的毫秒数),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3273692/