SQL 本机客户端数据类型兼容性 - 与 SQLOLEDB 不兼容
SQL native client data type compatibility - incompatible with SQLOLEDB
我们 运行 在切换到使用 SQL Native Client (SQLNCLI) 作为 ADO 的提供程序时,遗留应用程序出现问题。
我们原来的连接字符串是:
Provider=SQLOLEDB; Server=host; Database=bob; Integrated Security=SSPI;
我们将其更改为:
Provider=SQLNCLI11; Server=host; Database=bob; Integrated Security=SSPI; DataTypeCompatibility=80;
我们发现,当使用 adDBTimeStamp 参数调用存储过程时,Native Client 似乎将时间戳视为 smalldatetime,而不是 datetime。这给我们带来了问题,因为我们在某些比较中使用 9999 年 12 月 31 日作为 "top-end" 日期,并且 Native Client 失败并出现 "Invalid date format" 错误,其中 SQLOLEDB 没有问题。
现在看起来我们可以在创建参数时将数据类型从 adDBTimeStamp 更改为 adDate,但是我想知道在我们继续创建之前我们是否在连接字符串中遗漏了什么代码更改。
下面要重现的 VBScript 代码。为避免疑义,在有人建议我们应该使用 12/31/9999 之前,日期格式是 UK (dd/mm/yyyy) :-) 但也要确认,CDate 不会失败。
Set db = CreateObject("ADODB.Command")
' If Provider=SQLOLEDB then there is no error.
db.ActiveConnection = "Provider=SQLNCLI11; Server=host; Database=bob; Integrated Security=SSPI; DataTypeCompatibility=80;"
db.CommandText = "usp_FetchData"
db.CommandType = &H0004
' 135 is adDBTimeStamp
db.Parameters.Append db.CreateParameter("@screenDate", 135, 1, 20, CDate("31/12/9999"))
Set rs = CreateOBject("ADODB.RecordSet")
' Then this line fails with "Invalid date format" from SQLNCLI
rs.Open db
WScript.Echo rs.RecordCount
将日期时间调回 2078(在日期 运行ge of smalldatetime 内)会使错误消失。
如前所述,如果可以找到非代码更改修复程序,那么在我们必须将 adDBTimeStamp 更改为 adDate 之前,这就是我们所希望的。我希望 DataTypeCompatiblity=80 表现得像 SQLOLEDB;不幸的是,我的 Google-fu 在找出 SQLNCLI 使用的确切类型映射时失败了。
可能终于找到了解决方案:通过 MSDN 页面 Data Type Support for OLE DB Date and Time Improvements,最后有这个片段:
Data Type Mapping in ITableDefinition::CreateTable
The following type mapping is used with DBCOLUMNDESC structures used
by ITableDefinition::CreateTable:
[...table of conversions...]
When an application specifies DBTYPE_DBTIMESTAMP in wType, it can
override the mapping to datetime2 by supplying a type name in
pwszTypeName. If datetime is specified, bScale must be 3. If
smalldatetime is specified, bScale must be 0. If bScale is not
consistent with wType and pwszTypeName,DB_E_BADSCALE is returned.
在测试中,似乎需要将比例设置应用于 SELECT 的参数和命令以及 CreateTable。因此,如果我们将上面的脚本更改为:
Set param = db.CreateParameter("@screenDate", 135, 1, 20, CDate("31/12/9999"))
param.NumericScale = 3
db.Parameters.Append param
...然后错误消失并执行存储过程。我们正处于测试的早期阶段,但是如果这导致了问题,欢迎来自其他人的反馈。
我们 运行 在切换到使用 SQL Native Client (SQLNCLI) 作为 ADO 的提供程序时,遗留应用程序出现问题。
我们原来的连接字符串是:
Provider=SQLOLEDB; Server=host; Database=bob; Integrated Security=SSPI;
我们将其更改为:
Provider=SQLNCLI11; Server=host; Database=bob; Integrated Security=SSPI; DataTypeCompatibility=80;
我们发现,当使用 adDBTimeStamp 参数调用存储过程时,Native Client 似乎将时间戳视为 smalldatetime,而不是 datetime。这给我们带来了问题,因为我们在某些比较中使用 9999 年 12 月 31 日作为 "top-end" 日期,并且 Native Client 失败并出现 "Invalid date format" 错误,其中 SQLOLEDB 没有问题。
现在看起来我们可以在创建参数时将数据类型从 adDBTimeStamp 更改为 adDate,但是我想知道在我们继续创建之前我们是否在连接字符串中遗漏了什么代码更改。
下面要重现的 VBScript 代码。为避免疑义,在有人建议我们应该使用 12/31/9999 之前,日期格式是 UK (dd/mm/yyyy) :-) 但也要确认,CDate 不会失败。
Set db = CreateObject("ADODB.Command")
' If Provider=SQLOLEDB then there is no error.
db.ActiveConnection = "Provider=SQLNCLI11; Server=host; Database=bob; Integrated Security=SSPI; DataTypeCompatibility=80;"
db.CommandText = "usp_FetchData"
db.CommandType = &H0004
' 135 is adDBTimeStamp
db.Parameters.Append db.CreateParameter("@screenDate", 135, 1, 20, CDate("31/12/9999"))
Set rs = CreateOBject("ADODB.RecordSet")
' Then this line fails with "Invalid date format" from SQLNCLI
rs.Open db
WScript.Echo rs.RecordCount
将日期时间调回 2078(在日期 运行ge of smalldatetime 内)会使错误消失。
如前所述,如果可以找到非代码更改修复程序,那么在我们必须将 adDBTimeStamp 更改为 adDate 之前,这就是我们所希望的。我希望 DataTypeCompatiblity=80 表现得像 SQLOLEDB;不幸的是,我的 Google-fu 在找出 SQLNCLI 使用的确切类型映射时失败了。
可能终于找到了解决方案:通过 MSDN 页面 Data Type Support for OLE DB Date and Time Improvements,最后有这个片段:
Data Type Mapping in ITableDefinition::CreateTable
The following type mapping is used with DBCOLUMNDESC structures used by ITableDefinition::CreateTable:
[...table of conversions...]
When an application specifies DBTYPE_DBTIMESTAMP in wType, it can override the mapping to datetime2 by supplying a type name in pwszTypeName. If datetime is specified, bScale must be 3. If smalldatetime is specified, bScale must be 0. If bScale is not consistent with wType and pwszTypeName,DB_E_BADSCALE is returned.
在测试中,似乎需要将比例设置应用于 SELECT 的参数和命令以及 CreateTable。因此,如果我们将上面的脚本更改为:
Set param = db.CreateParameter("@screenDate", 135, 1, 20, CDate("31/12/9999"))
param.NumericScale = 3
db.Parameters.Append param
...然后错误消失并执行存储过程。我们正处于测试的早期阶段,但是如果这导致了问题,欢迎来自其他人的反馈。