为什么日期时间转换超出范围 999 毫秒?

Why do I get datetime conversion out of range for 999 milliseconds?

谁能解释一下为什么我会收到错误

The conversion of a varchar data type to a datetime data type resulted in an out-of-range value.

当我在 SQL Server 2017 上执行以下代码时。我只收到 0.999 毫秒的错误

SELECT CAST('9999-12-31 23:59:59.999' AS DATETIME)

结果:

The conversion of a varchar data type to a datetime data type resulted in an out-of-range value.

然后我尝试了:

SELECT CAST('9999-12-31 23:59:59.998' AS DATETIME)

结果:9999-12-31 23:59:59.997

然后我尝试了:

SELECT CAST('9999-12-31 23:59:59.997' AS DATETIME)

结果:9999-12-31 23:59:59.997

根据文档,日期时间范围介于 1753 年 1 月 1 日和 9999 年 12 月 31 日之间。同样仍然基于文档,时间范围介于 00 到 23:59:997 之间。

因此,如果您进行舍入,在 998 时它会向下舍入到 997。在 999 时它应该向上舍入到超出范围的 1 月 1 日 10000。 (sql-server中datetime的精度为3.33ms)

有时(我的意思是总是吗?)阅读 documentation 有很大帮助。

它指出:

Date range : January 1, 1753, through December 31, 9999

Time range : 00:00:00 through 23:59:59.997

关于23:59:59.998的有效时间,即使有效范围达到997毫秒,在documentation

中仍然有说明

23:59:59.99523:59:59.998 的时间存储为 23:59:59.997

时间 23:59:59.999 存储为 00:00:00.000 +1 天

然后,9999-12-31 23:59:59.999 存储为 10000-01-01 00:00:00.000超出范围

根据 documentation,百秒四舍五入:

  • 999 -> 000 四舍五入(这会导致你的错误)
  • 998、997、996、995 -> 997
  • 992、993、994 -> 993
  • 991, 990 -> 990

这是因为日期时间数据类型不够精确,无法存储这些值。如果您需要更高的精度,可以使用 datetime2。

如果您想了解日期时间是如何存储在 SQL 服务器中的,我推荐这篇文章:https://www.red-gate.com/simple-talk/sql/t-sql-programming/how-to-get-sql-server-dates-and-times-horribly-wrong/

datetime 仅精确到 1/300 秒,因此它仅显示精确到 .000、.003 和 .007 秒的时间(最后一个是三分之二秒四舍五入到小数点后三位)。

对于您的值 '9999-12-31 23:59:59.999' SQL 服务器无法存储 0.009,因此它四舍五入到最接近的值,在本例中为下一秒,使日期 '10000-12-31 00:00:00.000',它不能存储在任何日期和时间数据类型中。

当您有 .998 时,最接近的舍入值是 .997,因此不会发生错误。

如果您使用 datetime2,您也不会收到错误,因为它可以精确到秒的 1/10000000:SELECT CAST('9999-12-31 23:59:59.999' AS datetime)