为什么此转换为 DATETIME2 包含额外的粒度?

Why does this cast to DATETIME2 contain extra granularity?

我正在尝试将以下 DATETIME 转换为 DATETIME2:

DECLARE @x DATETIME = '2021-12-10 19:58:41.333'
SELECT CAST(@x AS DATETIME2)

结果是2021-12-10 19:58:41.3333333。为什么 cast 添加 0.0003333s?

这实际上是由于DATETIME的粒度。您会注意到 datetime 中的毫秒只有 3 个可能值:0,333 或 667。这是因为它的粒度是三分之一秒。当转换为 datetime2 时,这会扩展小数位以正确表示分数。

与某些人理解的相反,datetime 并不精确到 1/1000 秒,而是精确到 1/300 秒。这就是为什么 datetime 的最后一位总是 037,因为它们分别代表第 0/300、1/300 和 2/300一秒(3/300 又是 0)。

然而,对于 datetime2,数据类型的精度可以为 0 - 70 表示精确到 1 秒,7 表示 100 纳秒或 1/10 微秒。

当您将 datetime 转换为 datetime2 时,datetime 仅精确到 1/300 秒这一事实反映在转换值中(请注意,对于较旧的SQL 服务器的版本这不是真的),因此将以新的准确度显示 1/300。

让我们取你的值 2021-12-10 19:58:41.333。这里的 .333 是无限的,更多的是 .3333333333~。这是因为您不能用 10 进制数准确表示 1/3(或 1/300)。然后,您将 (CAST) 您的值转换为 datetime2。您省略了精度,因此默认精度为 7。这给你 2021-12-10T19:58:41.3333333,因为现在显示的 1/300 精度高达 7(请注意,上面的精度为 100 纳秒, 而不是 100/3 纳秒) .

如果你有像 2021-12-10 19:58:41.357 这样的时间并将其转换为 datetime2(4) 你会得到 2021-12-10 19:58:41.3567。如果您随后将其转换为 datetime2(7),您将得到 2021-12-10 19:58:41.3567000,因为在将其转换为 datetime2(4).[=44= 时,“1/300th-ness”精度丢失了]

如前所述,在旧版本的 SQL 服务器 (2014 or prior) 中,上述情况并非如此。在这些旧版本中,datetime2021-12-10 19:58:41.333 转换为 datetime2(7)2021-12-10 19:58:41.3330000 的准确度较低。如果您使用的是旧版本并依赖于此行为,则需要明确 convert/cast 您的 datetime 值到 datetime2(3) 以避免可能的破坏性更改。