在 SQL Server 2008 R2 和 SQL Server Compact 4 中存储日期/时间数据的最佳方式

Posted

技术标签:

【中文标题】在 SQL Server 2008 R2 和 SQL Server Compact 4 中存储日期/时间数据的最佳方式【英文标题】:Best way to store date/time data in SQL Server 2008 R2 and SQL Server Compact 4 【发布时间】:2013-06-27 12:29:46 【问题描述】:

我们正在 C# 4 中开发一个使用 SQL Server 2008 R2 作为后端的应用程序。在极少数情况下,SQL Server Compact 4 也用于断开连接的客户端。我们想知道将日期/时间数据存储到这些数据库中的最佳方式是什么,以便:

    包含不同时间偏移(来自不同时区)的数据可以很好地共存。这意味着要进行排序和比较。 SQL Server 2008 R2 和 SQL Server Compact 4 中的数据可以无缝来回传输;这是一个次要要求,不应损害所选设计。

我们主要关心的是保留每个记录事件的本地时间,但不会失去比较和排序从不同时区生成的事件的能力,因此具有不同的时间偏移。

我们已经考虑了datetimeoffset 数据类型,因为它存储了时间偏移并且因为它很好地映射到.NET 的DateTimeOffset。但是,SQL Server Compact 4 不支持它。另一种方法是从数据库中删除偏移信息并使用简单的datetime 数据类型,以便数据库中的每条数据都被规范化,并且 Compact 的问题更少。但是,这会带来一个问题,即在用户看到数据之前,需要在检索时以某种方式重建偏移信息。

所以我的问题是,考虑到我们需要处理不同的时区,以及在 2008 R2 和 Compact 之间实现互操作性,是否有任何关于如何在 SQL Server 中存储日期/时间值的最佳实践或指南4 尽可能简单?

谢谢。

【问题讨论】:

请注意,datetimeoffset 并不真正存储时区 - 它存储偏移量。这并不能告诉您它是在哪个时区观察到的,即 10 分钟后的当地时间,当偏移量可能发生变化时。这些值意味着什么?只是瞬间?从根本上说,您需要保留原始偏移量,还是只对发生某事的那一刻感兴趣? @JonSkeet:你是对的;我必须承认我没有这样看。我们有兴趣知道事件的本地时间,但还需要能够将每个事件的时间与可能在不同地点生成的其他事件进行比较,因此在不同的时区(因此具有不同的偏移量) )。 好的 - 如果您确实需要当地时间,那么您需要以一种或另一种方式存储偏移量。接下来,您需要考虑是否需要能够在本地时间查询此数据 - 例如,您可以将 DateTime 值存储在 UTC 中,并将偏移量存储在单独的列中......使全球订购变得容易,但在本地搜索相对困难...... @JonSkeet:我们宁愿优化本地时间而不是全局比较/排序。也许将 DateTime 存储在 local 时间,并将偏移量存储为单独的列?或者,DateTimeOffset?有关 SQL Server 的 DateTimeOffset 工作情况以及与 .NET 集成的任何指南/最佳实践? 使用 SqlServerCE 是我建议不要使用 DateTimeOffset 的原因。但是,是的,您可以使用本地 DateTime 和偏移量来 subtract 来获取 UTC。 【参考方案1】:

听起来相关点是:

您的传入数据非常适合DateTimeOffset 您只关心特定时间的偏移量,因此您不需要真实时区。 (偏移量不是时区。) 您确实关心原始偏移量 - 您不能将所有内容标准化为 UTC 并完全忽略偏移量。 您想查询本地时间。

听起来DateTimeOffset 在这种情况下基本上是最合适的类型。您应该确保团队中的每个人都清楚这意味着什么 - 偏移量是最初接收数据时的偏移量。如果您想在 不同 时区中显示该时刻,您实际上需要返回 UTC,并找出该显示时区中的偏移量。很容易对这种事情感到困惑:)

如果您需要完全保真地维护 SqlServerCE 中的数据,您可能需要一个 DateTime 字段,然后是一个单独的偏移量字段(例如,以分钟为单位,或者如果 SqlServerCE 支持,则作为 TimeSpan)。

【讨论】:

谢谢;这对我来说很有意义。我们需要找到绕过 SQL Server CE 的方法,但这没什么大不了的。【参考方案2】:

在服务器上使用DateTimeOffset 可能是对的。您可能还想阅读我在 DateTime vs DateTimeOffset 上的回答。

在您使用 SQLCE 的客户端上,使用 UTC 值存储 DateTime。向服务器发送数据时,可以使用客户端的本地时区来确定UTC值对应的DateTimeOffset

如果用户可能会更改他们的时区,那么您可能还需要将时区的 ID 存储在客户端数据库中。但是你只会在转换过程中使用它。除非您可能正在服务器或其他客户端上编辑这些值,否则无需将其发送到服务器。

不要尝试将客户端的时间存储在客户端的本地时间中。你会遇到歧义。例如,当夏令时倒退时,您不希望同一本地时间出现两个不同的可能 UTC 时间。

【讨论】:

感谢您对客户的好建议。我现在正在查看您的其他答案。【参考方案3】:

为什么不使用 datetime 并始终将值存储为 UTC 值,然后您可以在需要时将其格式化为最终用户(显示)时区。

【讨论】:

好吧,我宁愿避免复制后端已经实现的东西。 SQL Server 和 .NET 显然使用 DateTimeOffset 数据类型为您管理时区。如果有明显的好处,我只会按照您的建议恢复手动管理它们。 好吧,SQLCE 只支持日期时间,因此唯一的其他选择是将日期时间值存储在 nchar(34) 列中,使用以下格式:dto.ToString("yyyy-MM-dd HH:mm :ss.fffffff zzz", System.Globalization.CultureInfo.InvariantCulture) ;-) 毫无疑问,SQLCE 不支持 datetimeoffset 这一事实是采用全面的日期时间解决方案并将偏移量存储在您建议的其他位置的一个很好的理由。但我想探索更多选项,并对每个选项的优缺点有一些见解。

以上是关于在 SQL Server 2008 R2 和 SQL Server Compact 4 中存储日期/时间数据的最佳方式的主要内容,如果未能解决你的问题,请参考以下文章

sql server 2012 r2怎么设置新用户

使用 Powershell 从 SQL Server 2008 R2 导出到固定宽度的文本文件

sqlserver2008R2连接数据库异常,异常内容如下

SQL SERVER 2008R2 执行大脚本文件时,提示“内存不足”的解决办法

SQL Server2008和SQL Server2008R2的区别,高手速进

数据库SQL server 2008 R2和SQL server 2008 能一起安装吗?为啥安装完只剩SQL server 2008 R2一个了?