Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SQL native client data type compatibility - incompatible with SQLOLEDB

We have ran into a problem with our legacy application when switching to use SQL Native Client (SQLNCLI) as the provider for ADO.

Our original connection string was:

Provider=SQLOLEDB; Server=host; Database=bob; Integrated Security=SSPI;

we changed this to:

Provider=SQLNCLI11; Server=host; Database=bob; Integrated Security=SSPI; DataTypeCompatibility=80;

What we've found is that when calling a stored procedure, using a parameter of adDBTimeStamp, Native Client appears to treat the timestamp as a smalldatetime, rather than a datetime. This is causing us problems as we use 31 Dec 9999 as a "top-end" date in some comparisons, and Native Client fails with an "Invalid date format" error where SQLOLEDB had no issues.

Now it looks like we may just be able to change from adDBTimeStamp to adDate as the datatype when creating the parameter, however I was wondering if there was something we were missing in the connection string before we go ahead and make the code change.

VBScript code to reproduce below. For the avoidance of doubt, date format is UK (dd/mm/yyyy) before someone suggests we should be using 12/31/9999 :-) But also to confirm, the CDate doesn't fail.

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

Winding the datetime back to 2078 (within the date range of smalldatetime) makes the error go away.

As mentioned, if a non-code-change fix can be found, that's what we'd prefer, before we go and have to change adDBTimeStamp to adDate. I'd have expected DataTypeCompatiblity=80 to behave as SQLOLEDB; unfortantly my Google-fu has failed when finding out exactly what type mapping SQLNCLI uses.

like image 623
Chris J Avatar asked Sep 10 '15 21:09

Chris J


People also ask

Is SQL Server Native Client backward compatibility?

For example, Microsoft ODBC Driver 17 for SQL Server is supported with SQL Server 2019, and must be used when connecting to a SQL Server 2019 instance from ArcGIS. Though both SQL Server Native Client and ODBC drivers are often backward compatible to older releases, they are not necessarily forward compatible.

What is provider Sqloledb?

The Microsoft OLE DB Provider for SQL Server, SQLOLEDB, allows ADO to access Microsoft SQL Server. Important. The Microsoft OLE DB Provider for SQL Server (SQLOLEDB) remains deprecated and it is not recommended to use it for new development work.

What is SQL Server Native Client used for?

SQL Server Native Client can be used to create new applications or enhance existing applications that need to take advantage of features introduced in SQL Server 2005 (9. x), such as multiple active result sets (MARS), user-defined data types (UDT), query notifications, snapshot isolation, and XML data type support.

Is sqlncli11 deprecated?

SNAC / SQLNCLI(?) This provider shipped with SQL Server 2005 (9. x) through SQL Server 2017. This provider was deprecated in 2011 and is therefore not recommended for developping new applications.


1 Answers

A solution may have finally been found: via the MSDN page Data Type Support for OLE DB Date and Time Improvements, there is this snippet towards the end:

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.

In testing, it appears this need to set the scale applies to parameters to SELECT and commands as well as to CreateTable. Therefore if we change the script above to:

Set param = db.CreateParameter("@screenDate", 135, 1, 20, CDate("31/12/9999"))
param.NumericScale = 3
db.Parameters.Append param

...then the error goes away and the stored procedure is executed. We're in the early stages of testing, however welcome feedback from others if this has caused issues.

like image 182
Chris J Avatar answered Sep 22 '22 04:09

Chris J