Switching from sqloledb to odbc driver 13 for SQL Server - sql-server

I want to use Always Encrypted feature introduce in SQL Server 2016 SP1. In order to do that, I need to use the new ODBC Driver 13.1 for SQL Server instead the current one sqloledb.
It seems it is breaking my application, for example, when XML is returned. Here, it is said that:
In order to take advantage of new features introduced in SQL Server
2005 such as multiple active result sets (MARS), query notifications,
user-defined types (UDTs), or the new xml data type, existing
applications that use ActiveX Data Objects (ADO) should use the SQL
Server Native Client OLE DB provider as their data access provider.
So, that's this mean that I need to rewrite code, where XML is used?
I know that, Microsoft undeprecated the deprecated sqloledb driver, but its first version coming in March 2018 will not support Always Encrypted - so, I do not want to wait.

Classic ADO has no notion of the SQL Server XML type. The legacy SQLOLEDB provider and legacy SQL Server ODBC driver return type adLongVarWChar (203) for XML so it's a string on the client side.
The newer SQL Server Native Client OLE DB provider returns type 141 for XML to ADO but there's no matching ADO DataTypeEnum (https://learn.microsoft.com/en-us/sql/ado/reference/ado-api/datatypeenum). The provider will return XML data as adLongVarWChar when the DataTypeCompatibility=80 connection string keyword is specified for ADO compatibility.
Unfortunately, there is no equivalent DataTypeCompatibility connection string keyword for ODBC drivers. The newer ODBC drivers return XML data as ADO type adLongVarBinary (205) when accessed via the MSDASQL provider classic ADO uses for ODBC drivers. So the XML will need to either be cast to/from nvarchar(MAX) in SQL queries or the adLongVarBinary value converted on the client side.
I can't say if the yet unreleased Microsoft OLE DB Driver for SQL Server will provide relief by supporting the DataTypeCompatibility keyword but I hope it does, similarly to Native Client. Hopefully, we'll know more details soon. I doubt ADO will be beefed up to support the newer SQL types natively since it's hardly been touched in the last 15 years but I've been wrong before.

I would not use the ODBC driver; it has a number of "wontfix" bugs.
Instead you should use the currently supported MSOLEDB driver: Microsoft OLE DB Driver for SQL Server
And you will have to include in your ConnectionString:
DataTypeCompatibility=80
for the reason's Dan said.

Related

Unreadable value returned in VBA/ADO from SQL Server 2019

To monitor SQL Server jobs in a VBA app, I run the sp_get_composite_job_info stored procedure from the msdb database using ADO. I check the current_execution_step field once I have the results in a ADODB.Recordset. This has worked fine with SQL Server 2012 for years.
We just migrated to SQL Server 2019 and now the same code which still works on SQL Server 2012 is returning an unreadable value for the current_execution_step field.
Instead of "4 (Step Name)", I get a bunch of rectangles and squares.
If I run the same call to sp_get_composite_job_info in SSMS, I can read the current_execution_step field just fine on both servers. It's only when I try to read that field in VBA/ADO that it's gibberish.
What's worse, I can read other fields from that same recordset just fine. It's only this one field (which just happens to be the only field I need to read) that is unreadable.
The driver I'm using in VBA is ODBC Driver 17 for SQL Server. But again, I use the same driver for both servers, and only 2019 has this issue.
What could be causing this?
The SQL Server 2012 version of sp_get_composite_job_info (undocumented as #RBarryYoung mentioned) returns current_execution_step as nvarchar(128) whereas SQL Server 2019 returns nvarchar(MAX).
ADO is unaware of SQL Server datatypes introduced after SQL Server 2000. Try installing the latest MSOLEDBSQL OLE DB driver (ADO is natively OLE DB) and specifying the DataTypeCompatibility=80 in the connection string.
Fortunately, the answer was as simple as going back to OLE and switching the Provider to SQLNCLI11 instead of SQLOLEDB. Since SQLNCLI11 is omnipresent, I don't have to hunt down all of the machines that might use these apps and install MSOLEDBSQL on them.

Why is ODBC Driver 17 for SQL Server converting strings to dates automatically and how can I stop this?

I'm moving an app that was previously running on windows 10 to a docker container with python3.6 linux base image. One of the necessary changes was changing the driver used in sql connection string from "SQL Server" to ODBC Driver 17 for SQL Server, because I have to use unixodbc-dev. I installed msodbcsql17 and mssql-tools via my Dockerfile, and I execute a query via an sqlalchemy engine that retrieves values from a column of sql type "date". With the SQL Server driver, these dates get converted to strings (which is what the code expects), but with ODBC Driver 17 for SQL Server, they are returned as dates. I'm using pyodbc==4.0.25 and SQLAlchemy==1.3.5.
The legacy "SQL Server" ODBC driver hasn't been enhanced since SQL Server 2000, long before the newer date data type (and other temporal types) was introduced with SQL Server 2008. The driver will return unrecognized types as strings instead of the native type.
If the native type is a breaking change for the app code, the correct solution is to use proper types in app code and the newer driver. About all you can do is use the legacy driver in the interim.

Does Microsoft OLE DB Provider for SQL Server support TLS 1.2

Our client recently upgraded from TLS 1.0 to TLS 1.2 and after this our software cannot connect with SQL server. It uses OLE DB provider for connecting to SQL server.
Below is the error which is returned from SQL server-
[DBNETLIB][ConnectionOpen SECDoClientHandshake()]SSL Security error
SQL State: 08001
SQL Error Number: 18
Could not find any useful information related to whether Microsoft OLE DB Provider for SQL Server support TLS 1.2 or not.
One of the links I found seems to suggest that it is not supported.
https://forums.iis.net/t/1233674.aspx?connecing+SQL+server+DB+issue+after+installingTLS1+2+in+SQL+srver+with+classic+asp+application+
Hence, wanted to check on stackoverflow in case anyone has any information on this.
The SQLOLEDB provider and the SQL Server ODBC driver that ship with Windows are legacy components provided only for backwards compatibility. These have been deprecated since SQL 2005.
According to this blog post by the MSSQL Tiger Team:
SQLOLEDB will not receive support for TLS 1.2. You will need to switch
your driver to one of the supported drivers listed in
https://support.microsoft.com/en-us/kb/3135244
You should be able to install SQL Server Native Client 2012 and use that OLE DB provider with only a connection string change (change Provider=SQLOLEDB to Provider=SQLNCLI11). Of course, once should test to avoid surprises. For example, I recall someone experiencing behavior differences with the SQL Server Native Client provider and ADO classic when server API cursors were used, although the commonly used firehose cursors were fine. 
EDIT
The new OLE DB driver, MSOLEDBSQL, has been released. This new driver includes the support for the latest TLS 1.2 standards and is backwards compatible with SQL Server Native Client 11 (SQLNCLI11). See the Microsoft SQLNCLi team blog announcement. Change the connection string to Provider=MSOLEDBSQL after installation.
EDIT #2
Time continues to march on. The SQL Server Native Client OLE DB driver is now deprecated in favor of MSOLEDBSQL. End of support for the final 2012 SNAC version is July 12, 2012.
Furthermore, as David called out in his answer, Microsoft recently added support for TLS 1.2 MDAC components in Windows 10 Build 17763.1554:
Adds support for the Transport Layer Security (TLS) 1.1 and 1.2
protocols when connecting to SQL Server using the data providers in
Microsoft Data Access Components (MDAC)
No enhancements (e.g. support for post-SQL 2000 data types) were added, though.
In summary, newer SQL Server client drivers provides more control over the specific driver and version without a direct OS patch level dependency. Modern drivers like MSOLEDBSQL and ODBC Driver n for SQL Server are continuously improved to support latest SQL Server features and security standards.
EDIT#3
SQLOLEDB and the SQL Server ODBC driver (part of MDAC, shipped and serviced with Windows) has support for TLS 1.2 with October 20, 2020 build, version 17763.1554. This applies to Windows 10 and Windows Server 2019 or later.
This may not be a solution for you, since it's a future fix your client may not be able to wait for, but apparently Microsoft is undeprecating the OLEDB Driver, with a new release supporting TLS 1.2 out Q1 2018: https://blogs.msdn.microsoft.com/sqlnativeclient/2017/10/06/announcing-the-new-release-of-ole-db-driver-for-sql-server/
The new Microsoft OLE DB Driver for SQL Server, or msoledbsql, will
also introduce multi-subnet failover capabilities in this first
upcoming release, and keeps up with latest TLS 1.2 standards.
Also, this first upcoming release will be a stand-alone install
package that is out-of-band with SQL Server lifecycle. This also means
the driver will not be packaged in the SNAC library, nor coupled with
any other driver.
TLS 1.2 Support has been added to sqloledb in Windows. See KB4580390.
This includes support both ODBC and OleDB providers in MDAC:
Adds support for the Transport Layer Security (TLS) 1.1 and 1.2
protocols when connecting to SQL Server using the data providers in
Microsoft Data Access Components (MDAC)
You can verify that MDAC has been updated by checking the Windows build number, anything 17763.1554 or later has this fix. MDAC has not been distributed outside of OS patches for many years.
The build is visible in winver or in Powershell with [environment]::OSVersion.Version.Build
Following changes on my end fixed the issue after TLS1.2 upgrade on Azure cloud -
change Provider=SQLOLEDB to Provider=SQLNCLI11
update ADODB version to Microsoft ActiveX Data Objects 6.0 Library
The use of "Microsoft OLEDB Driver for SQL Server" is what worked for us but I can also confirm Native Driver 11 also tests OK.
Here was our scenario: after we disabled TLS 1.0 and 1.1 and enabled TLS 1.2, Crystal Reports using the "Microsoft OLEDB Provider for SQL Server" would no longer connect. Instead you get a user/pw prompt that fails with even with valid credentials. In our case we were running Crystal Reports from within an ASP.NET v4.5.2 application that has the Crystal 13 Viewer embedded in. Users pick from a list of reports and run them and they run without a prompt with TLS 1.0 enabled.
To fix this, we had to open the report in the designer and convert it report from using the "Microsoft OLEDB Provider for SQL Server" to using the "Microsoft OLEDB Driver for SQL Server".
If you don't see the driver in your list here's the OLEDB Driver for SQL Server: https://learn.microsoft.com/en-us/sql/connect/oledb/download-oledb-driver-for-sql-server?view=sql-server-ver15
Credit to Dan Guzman who mentioned the existence of the "driver" in a somewhat buried comment and an update above.
This might not directly answer the question, but it is still related to sql server connection with TLS 1.2 error.
I'm maintaining an old ASP Classic website which broke with following error.
Microsoft OLE DB Provider for SQL Server error '80004005'
[DBNETLIB][ConnectionOpen (SECDoClientHandshake()).]SSL Security error.
Changing Provider from SQLOLEDB to SQL Server Native Client 11.0 or any higher version which is available fixed the error.
Thus, changing connection string from
constr = "Provider=SQLOLEDB;Data Source=..."
to
constr = "Provider=SQL Server Native Client 11.0;Data Source=...."
might work too

FreeTDS and SQL Server 2008?

I'm getting this when trying to connect to SQL Server 2008 using Moodle:
4004: Unicode data in a Unicode-only collation or ntext data cannot
be sent to clients using DB-Library (such as ISQL) or ODBC version 3.7
or earlier.
I changed the version to 8.0 in the ini file, but no luck. Any ideas?
From the Moodle doc:
The SQL Server complaining that it doesn't support pure Unicode via
TDS or older versions of ODBC. Microsoft has deprecated DB-Library a
long ago, in favor of ODBC, OLE DB, or SQL Native Client. Many new
features of SQL 2005 aren't accessible via DB-Library so if you need
them, you could have to switch away from tools based on TDS and
DB-Library :(
My config file was messed up. I was not using version 8.0 of TDS. I have explicitly set it to use 8.0. Since I fixed that, everything works fine.

SQL Server: Native client vs. ODBC?

What is the difference between SQL Server Native Client connection and ODBC connection? What are the pros and cons of these two?
Huh? ODBC is officially dead? Someone might want to let Microsoft know that:
Microsoft is Aligning with ODBC for Native Relational Data Access
From the above link:
ODBC is the de-facto industry standard for native relational data access...
and
The commercial release of Microsoft SQL Server, codename 'Denali' will be the last release to support OLE DB.
and finally,
"We encourage you to adopt ODBC in the development of your new and future versions of your application. You don’t need to change your existing applications using OLE DB, as they will continue to be supported on Denali throughout its lifecycle. While this gives you a large window of opportunity for changing your applications before the deprecation goes into effect, you may want to consider migrating those applications to ODBC as a part of your future roadmap. Microsoft is fully committed to making this transition as smooth and easy as possible.""
(emphasis added)
ODBC is useful for times when the underlying database might change but you don't want your code to (assuming the SQL stays the same across technologies). You could connect to an Oracle database one day and switch out to a SQL server database the next. The disadvantage is that you don't get the optimizations that having specific drivers affords you. The SQL Server Native client driver has been proven to be much faster than just using a standard ODBC driver.
What is the difference between SQL Server Native Client connection and ODBC connection?
ODBC is a standardized API.
ODBC drivers are shared libraries that use native protocols (like SQL Server shared memory, or SQL Server TCP/IP) to implement the ODBC interface.
In other words, ODBC is an abstraction that enables code to work against multiple database technologies.
It's similar to Java's JDBC, or Python's DB-API, or GO's database/sql, except ODBC drivers use C functions. Also, they are more frequently installed at a system level.
ODBC has the usual pros and cons of any abstraction.
Pros: Makes code more flexible/portable.
Cons: Adds performance overhead and has fewer features.
It sounds like you know that you will use SQL Server and will always use SQL Server.
In that case, I'd use a native client library if it's available.
SQL Server Native Client is a single dynamic-link library (DLL) containing both the SQL OLE DB provider and SQL ODBC driver for Windows.
SNAC 11 is a single dynamic-link library (DLL) containing both the SQL
OLE DB provider and SQL ODBC driver for Windows. It contains run-time
support for applications using native-code APIs (ODBC, OLE DB and ADO)
to connect to Microsoft SQL Server 2005, 2008, 2008 R2, and SQL Server
2012. A separate SQL ODBC-only driver is available for Linux.
https://blogs.msdn.microsoft.com/sqlreleaseservices/snac-lifecycle-explained/

Resources