3

我们有一些通用工具,除其他外,可以保存和显示日期。它将保存为数字,例如 41247。

如果我将其转换回 Access 中的日期,我会得到 2012/12/04 - 这是正确的。
[使用 Format(41247;"General Date") 或 Format(Format("41247", "Short Date"), "Short Date")]

如果我将该数字转换回 SQL Server 中的日期,我会得到 2012/12/06 - 不正确。我正在使用 CONVERT(datetime, CONVERT(real, 41247))

为什么会有差异,我可以在 SQL 中使用什么来修复它?

4

2 回答 2

6

因此,当我从 excel 文件中导入数据时,我遇到了这个问题。

您有 2 天的差价有两个原因

原因 1 在您的 SQL Server 中,1900 年 1 月 1 日是第 0 天,而在访问中是第 1 天。

(我没有使用 Access,但如果您在 Excel 中输入日期 1900-01-01 并将单元格格式化为数字,您将得到 1)。

原因 2 1900 年不是闰年。SQL Server 知道,但 Access 不知道。它认为 1900 年 2 月 29 日存在。

在你的 SQL Server 中运行它

SELECT DATEDIFF(dd, 0, '1900-01-01')
SELECT DATEDIFF(dd, 0, '1900-02-28')
SELECT DATEDIFF(dd, 0, '1900-03-01')

输出将是

0
58 
59

但是当你尝试运行时

SELECT DATEDIFF(dd, 0, '1900-02-29')

你会得到一个错误

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

由于这 2 个原因,您可以多获得 2 天的访问权限。

因此,对于 2012/12/04,Access 返回 41247,而 SQL Server 将为您提供 41245。

希望它有所帮助。

编辑

看看 Eric Lippert 的评论,他提到了他和 Joel Spolsky 的 2 篇非常有趣的博客文章。

于 2013-05-07T15:28:51.800 回答
2

绝对不能保证两个不同的数据库引擎将使用相同的内部数字格式存储日期。因此,期望...是不合理的。

  • 获取访问日期/时间值,

  • 将其转换为等效的 Access 数字,然后

  • 将该数字转换为 SQL Server 日期时间值

...并保证日期匹配。

如果您需要在数据库环境之间传递日期时间值,则需要以两者通用的格式传递它们,例如明确的字符串。(如果我遇到这个问题,我会倾向于尝试 XML 使用的日期/时间格式。)

编辑

关于@roughnex 提供的非常丰富的答案,虽然从访问日期数中减去 2 以获得 SQL Server 日期数可能非常诱人(除非它是 <=58,在这种情况下您只需减去 1),即这不是一个好主意。有关原因的解释,请参阅以下博客条目

Bug 心理学 - Eric Lippert

像这样的捷径可能会导致看似奇怪的行为,这会极大地增加开发人员(以及用户)日后的磨损。

于 2013-05-07T15:11:11.100 回答