在将DateTime存储到SQL Server中时,毫秒数发生变化。

38

我生成了一个日期时间,方式如下:

DateTime myDateTime = DateTime.Now;

我使用Entity Framework将其存储在数据库中(在DateTime类型的列中),然后使用OData(WCF数据服务)检索它。

当值变为09:30:03.0196095时,它被存入数据库;

当值变为09:30:03.0200000是,它从数据库中取出。

这个操作的结果使得它在保存之前被视为19毫秒,而在重新加载之后被视为20毫秒。

因此,当我在代码中稍后进行比较时,它会失败,即使它们应该相等。

SQL Server是否没有与.NET一样高的精度?还是实体框架或OData弄错了什么?

我将只截断毫秒部分(我并不需要它们)。但我想知道这是为什么。


你是如何进行比较的? - ChrisBint
1
这是一个不同的精度。请看旁边的相关问题。 - Anthony Pegram
1
你使用的是哪个版本的SQL Server?如果是2008,那么datetime2具有更高的精度。 - Martin Smith
2
仅仅截取毫秒可能不够。你可能需要将 09:30:03.999999 四舍五入为 09:30:04.000000 - Joel Rondeau
每当我在本地程序外传播 .net DateTime 时,我都会假设它只精确到几百毫秒。我的理由是 UTC 时间需要考虑闰秒,而 .net DateTime 不需要。通常我会在数据库中使用 smalldatetime,并在将其发送到数据库之前将我的 datetime 四舍五入到最近的分钟。要进行 datetime 中点四舍五入,请参见 -> https://dev59.com/V3M_5IYBdhLWcg3wZSTX - aj.toulan
显示剩余3条评论
4个回答

48

这取决于您使用的SQL服务器版本。

日期时间字段的分辨率为3个小数位:例如:2011-06-06 23:59:59.997,仅准确到3.33毫秒。

在您的情况下,09:30:03.0196095被四舍五入为存储时的09:30:03.020

从SQL 2008开始,添加了其他数据类型以提供更多细节,例如datetime2,它具有最高达7位小数并且精度高达100纳秒。

有关更多信息,请参见以下内容:

http://karaszi.com/the-ultimate-guide-to-the-datetime-datatypes

我认为,如果毫秒不重要,则最好在将其存储到SQL服务器之前将其舍入到秒。


23
这是由于SQL datetime 类型的精度。根据 MSDN 的说法:

日期时间值会四舍五入为 .000、.003 或 .007 秒的增量

查看 这个 MSDN 页面 上的日期时间分数秒精度的舍入部分,您将了解如何进行舍入。
正如其他人所指出的那样,您可以使用 datetime2 代替 datetime 来获得更好的精度:
  • datetime 时间范围为 00:00:00 到 23:59:59.997
  • datetime2 时间范围为 00:00:00 到 23:59:59.9999999

为什么datetime2对我来说仍然以相同的方式舍入毫秒小数? - RobPio

13

对于那些无法在SQL中使用DateTime2的人(例如像我一样使用由另一个系统生成的表格,更改这个表格只为解决这个问题会非常昂贵),有一种简单的代码修改方法可以帮助你进行四舍五入。

引用System.Data并导入System.Data.SqlTypes命名空间。然后,您可以使用SqlDateTime结构为您进行转换:

DateTime someDate = new SqlDateTime(DateTime.Now).Value;

这将把该值转换为SQL ticks,再转换回.NET ticks,包括精度的损失。 :)

需要提醒的是,这将会丢失原始DateTime结构体的Kind信息(例如UtcLocal)。此转换也不仅仅是简单的四舍五入,它包括tick计算、MaxTime更改等完整的转换。因此,如果您依赖于DateTime中的特定指示器,则可能会丢失它们,请谨慎使用。


3

在SQL Server中,DateTime的精度为毫秒(.fff)。因此,0.0196会四舍五入为0.020。如果您可以使用datetime2,则可以获得更高的精度。


唉,OData不支持DateTime2。因此我无法使用它。 - Vaccano

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接