我在SQL Server中有一个带日期时间列的链接表,我在其中存储一个仅限时间的值*。如果我在没有dbFailOnError的情况下执行UPDATE查询,它会将该命令转换为SELECT,然后是每次执行一行的单个UPDATE语句:
exec sp_executesql N'UPDATE "dbo"."Appeals" SET "HearingTime"=@P1
WHERE "AppealID" = @P2'
,N'@P1 datetime,@P2 int','1899-12-30 09:00:00',1
...
exec sp_executesql N'UPDATE "dbo"."Appeals" SET "HearingTime"=@P1
WHERE "AppealID" = @P2'
,N'@P1 datetime,@P2 int','1899-12-30 09:00:00',4
如果我执行完全相同的UPDATE查询,但使用dbFailOnError,我会得到以下翻译:
UPDATE "dbo"."Appeals" SET HearingTime={t '09:00:00'}
有趣的是,dbFailOnError在后端强制执行更高效的UPDATE,但我真正关心的是时间值本身。
在第一个示例中,Access正确地将日期时间设置为12/30/1899(MS Access神奇的"零"日(。在第二种情况下,这种情况不会发生。最终的结果是,第一个例子"有效",而第二个则不然。
我的意思是,如果我在数据表视图中查看HearingTime字段,Access会将第一个显示为:
9:00:00 AM
第二个显示为(截至本文撰写之时,9/13/16是今天的日期(:
9/3/2016 9:00:00 AM
我不得不假设这是微软的一个错误。还是我在这里错过了什么?我有比报告错误并希望微软有一天能修复它更好的选择吗?
*是的,我知道SQL Server中存在time
数据类型。它与MS Access日期时间类型不兼容,所以在MS Access链接表中对我来说用处不大。
我能够使用带有Access SQL日期/时间文字的查询来重现您的问题。两个
Dim cdb As DAO.Database
Set cdb = CurrentDb
cdb.Execute "UPDATE dbo_Appeals SET HearingTime=#10:00:00#", dbFailOnError
和
Dim cdb As DAO.Database
Set cdb = CurrentDb
cdb.Execute "UPDATE dbo_Appeals SET HearingTime=#1899-12-30 11:00:00#", dbFailOnError
导致[HearningTime]值为当前日期(2016-09-03(,而不是"零"日期。
然而,将完整的日期/时间作为字符串传递似乎适用于
Dim cdb As DAO.Database
Set cdb = CurrentDb
cdb.Execute "UPDATE dbo_Appeals SET HearingTime='1899-12-30 12:00:00'", dbFailOnError
(省略字符串值中的日期部分会导致[HearningTime]值的SQL Server DATETIME
"零"日期为1900-01-01。(
而且,更好的是,带有DAO.QueryDef
对象的参数化查询似乎也能正确工作
Dim cdb As DAO.Database
Set cdb = CurrentDb
Dim qdf As DAO.QueryDef
Set qdf = cdb.CreateQueryDef("", _
"PARAMETERS prmHearingTime DateTime;" & _
"UPDATE dbo_Appeals SET HearingTime=[prmHearingTime]")
qdf!prmHearingTime = #10:00:00 AM#
qdf.Execute dbFailOnError
这是一个很好的问题,我可以重现它。
这似乎是ODBC驱动程序中的一个错误,因为您演示的行为是SQL Server的行为,ODBC驱动程序应该对此进行补偿,就像您在第一个示例中所做的那样,它提供了完整的日期时间字符串,当在Access中读回时,该字符串将正确转换。
除了在读回数据时将TimeValue应用于日期-时间值之外,我看不出其他解决方法。然而,这将停止使用时间字段的索引。
SQL Server的数据类型Time不能用于许多事情,因为ODBC驱动程序将这些数据作为文本读取。