Access和SQL Server以不同方式计算日期

时间:2013-05-07 14:56:36

标签: sql sql-server tsql date ms-access

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

如果我将其转换回Access中的日期,我会得到2012/12/04 - 这是正确的 [使用格式(41247;“一般日期”)或格式(格式(“41247”,“短日期”),“短日期”)]

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

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

2 个答案:

答案 0 :(得分:6)

所以当我从excel文件导入数据时遇到了这个问题。

有两个原因,你有2天的差异

原因1 在您的SQL Server Jan 1中,1900年是第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天。

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

希望它有所帮助。

修改

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

答案 1 :(得分:2)

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

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

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

  • 将该号码转换为SQL Server日期时间值

...并保证日期匹配。

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

修改

关于来自@roughnex的非常有用的答案,虽然从访问日期编号中减去2以获取SQL Server日期编号可能非常诱人(除非它是< = 58,在这种情况下你只需减去1),这不是一个好主意。有关原因的说明,请参阅以下博客条目

Bug Psychology - Eric Lippert

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