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

时间:2019-06-25 08:35:08

标签: sql-server datetime sql-server-2017

有人可以解释一下我,为什么会出现错误

  

将varchar数据类型转换为datetime数据类型   值超出范围。

当我在SQL Server 2017上执行以下代码时。我仅在.999毫秒内收到错误

APP_PLATFORM := android-9
APP_STL := gnustl_static
APP_ABI := all

#APP_OPTIM := debug
APP_OPTIM := release

ifeq ($(APP_OPTIM),debug)
  APP_CPPFLAGS := -O0 -g $(APP_CPPFLAGS)
else
  APP_CPPFLAGS := -O2 -DNDEBUG -g $(APP_CPPFLAGS)
endif

结果:

  

将varchar数据类型转换为datetime数据类型   值超出范围。

然后我尝试:

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

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

然后我尝试:

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

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

4 个答案:

答案 0 :(得分:3)

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

因此,如果四舍五入,则在998处将舍入到997。在999处,它将舍入到1月1日10000,这超出范围。 (sql-server中datetime的精度为3.33ms)

答案 1 :(得分:1)

有时候(我是说总是?)阅读documentation有很大帮助。

它说明:

  

日期范围:1753年1月1日至9999年12月31日

     

时间范围:00:00:00至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存储为{strong>超出范围

10000-01-01 00:00:00.000

答案 2 :(得分:1)

datetime仅精确到1/300秒,因此它只显示精确到0.00000,.003和.007秒的时间(最后是2秒的三分之二四舍五入为小数点后3位。

对于您的值'9999-12-31 23:59:59.999',SQL Server无法存储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)

答案 3 :(得分:0)

根据documentation,四舍五入的秒数如下所示:

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

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

如果您想了解日期时间在SQL Server中的存储方式,建议您阅读本文:https://www.red-gate.com/simple-talk/sql/t-sql-programming/how-to-get-sql-server-dates-and-times-horribly-wrong/