dbFailOnError SQL 仅时间值的服务器日期时间错误

dbFailOnError SQL Server datetime bug for time-only values

我在 SQL 服务器中有一个链接的 table,带有一个日期时间列,我在其中存储了一个仅时间值*。如果我在没有 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 在后端强制执行更有效的更新,但我真正关心的是时间值本身。

在第一个示例中,Access 正确地将日期时间设置为 12/30/1899(MS Access 的魔法 "zero" 日)。在第二种情况下,这不会发生。最终结果是第一个示例 "works" 而第二个示例没有。

我的意思是,如果我在数据表视图中查看 HearingTime 字段,Access 会将第一个字段显示为:

9:00:00 AM

第二个显示为(截至撰写本文时,9/3/16 是今天的日期):

9/3/2016 9:00:00 AM

我不得不假设这是 Microsoft 的一个错误。还是我在这里遗漏了什么?除了报告错误并希望微软有一天修复它之外,我还有更好的选择吗?


*是的,我知道 SQL 服务器中有一个 time 数据类型。它与 MS Access 日期时间类型不兼容,因此在链接 table.

的 MS Access 中它对我没什么用处

这是个好问题,我可以重现。

这似乎是 ODBC 驱动程序中的一个错误,因为您展示的行为是 SQL 服务器的行为,ODBC 驱动程序应该补偿它,就像您在第一个示例中通过提供完整日期所做的那样- 在 Access 中读回时将正确翻译的时间字符串。

除了在您读回数据时将 TimeValue 应用于日期时间值之外,我看不出有什么其他解决方法。但是,这将停止使用您的时间字段的索引。

并且 SQL 服务器的数据类型 Time 不能用于很多事情,因为 ODBC 驱动程序将这些作为文本读取。

我能够使用带有 Access SQL Date/Time 文字的查询重现您的问题。两者

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

导致 [HearingTime] 值具有当前日期 (2016-09-03),而不是 "zero" 日期。

但是,将完整的 date/time 作为 字符串 传递似乎可行

Dim cdb As DAO.Database
Set cdb = CurrentDb
cdb.Execute "UPDATE dbo_Appeals SET HearingTime='1899-12-30 12:00:00'", dbFailOnError

(省略字符串值中的日期部分会导致 SQL 服务器 DATETIME "zero" 日期为 1900-01-01 的 [HearingTime] 值。)

而且,更好的是,带有 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