Pyodbc timeout while connecting to SQL Server on Linux - python

During connection (not query execution), following problem with timeout occurs:
('HYT00', '[HYT00] [Microsoft][ODBC Driver 17 for SQL Server]Login timeout expired (0) (SQLDriverConnect)')
Code:
import pyodbc
import pandas as pd
cnxn = pyodbc.connect('DRIVER={ODBC Driver 17 for SQL Server};SERVER='+server+';DATABASE='+database+';UID='+username+';PWD='+ password)
cursor = cnxn.cursor()
DF = pd.read_sql_query(query, cnxn)
This problem doesn't exist on Windows. In both cases I am using Forticlient VPN. Other networking works fine. Current configuration: Ubuntu 20.04 current patch, Windows 10 current patch. Driver was installed with official Microsoft's instruction:
https://learn.microsoft.com/en-us/sql/connect/odbc/linux-mac/installing-the-microsoft-odbc-driver-for-sql-server?view=sql-server-ver15

Related

OperationalError when trying to connect to SQL Server database using pyodbc

I'm trying to connect to a SQL server database using pyodbc in Python 3. But I get an error when I'm trying to establish the connection.
I do something like this:
import pyodbc
conn = pyodbc.connect('Driver={ODBC Driver 18 for SQL Server};Server=192.168.2.250;Database=DB;UID=username;PWD=password;')
And I get this:
OperationalError: ('08001', '[08001] [Microsoft][ODBC Driver 18 for SQL Server]SSL Provider: [error:1425F102:SSL routines:ssl_choose_client_version:unsupported protocol][error:140B40C7:SSL routines:SSL_do_handshake:peer did not return a certificate] (-1) (SQLDriverConnect)')
Does anybody know how to solve this? The database is not my own, so I hope there is a solution that doesn't require changing any settings there.
I'm running Ubuntu within the Windows Subsystem for Linux.
There is a breaking change in ODBC Driver 18 for SQL Server
Similar to the HTTP to HTTPS default changes made in web browsers a few years back (and the security reasons for them), we are changing the default value of the Encrypt connection option from no to yes/mandatory.
ODBC Driver 18.0 for SQL Server Released
So this
conn = pyodbc.connect('Driver={ODBC Driver 18 for SQL Server};Server=192.168.2.250;Database=DB;UID=username;PWD=password;')
is the same as
conn = pyodbc.connect('Driver={ODBC Driver 18 for SQL Server};Server=192.168.2.250;Database=DB;UID=username;PWD=password;Encrypt=yes')
If you don't want an encrypted connection you must opt out:
conn = pyodbc.connect('Driver={ODBC Driver 18 for SQL Server};Server=192.168.2.250;Database=DB;UID=username;PWD=password;Encrypt=no')
We also changed the behavior of TrustServerCertificate to not be tied to the Encrypt setting
So if your server is using a self-signed certificate, you also must opt out of certificate validation. so
conn = pyodbc.connect('Driver={ODBC Driver 18 for SQL Server};Server=192.168.2.250;Database=DB;UID=username;PWD=password;Encrypt=no;TrustServerCertificate=yes')
I ended up taking my script out of WSL. Running the same command (with David's additions or ODBC Driver 17 for SQL Server instead of 18) under Windows works without issues in my case.

[Microsoft][ODBC Driver 17 for SQL Server]Login timeout expired (0) (SQLDriverConnect)')

I am unable to make a connection to the SQL server from Unix using python.
I will not be able to replace the driver from ODBC Driver 17 for SQL Server to ODBC Driver 13 for SQL Server as explained in Pyodbc: Login Timeout Error due to other dependencies.
Can somebody please suggest an alternative?
CODE:
import sqlalchemy as sa
from urllib import parse as db_parse
from sqlalchemy import event
params = db_parse.quote_plus(r"DRIVER={ODBC Driver 17 for SQL Server};SERVER='server,port';DATABASE=DB_NAME;username=USER_ID;password=PWD;Trusted_Connection=yes")
engine = sa.create_engine('mssql+pyodbc:///?odbc_connect={}'.format(params))
connection = engine.connect()
ERROR:
sqlalchemy.exc.OperationalError: (pyodbc.OperationalError) ('HYT00', '[HYT00] [Microsoft][ODBC Driver 17 for SQL Server]Login timeout expired (0) (SQLDriverConnect)') (Background on this error at: http://sqlalche.me/e/e3q8)
My connection string looks different:
"DRIVER={ODBC Driver 17 for SQL Server};SERVER=myserver;DATABASE=mydb;UID=myuser;PWD=mypassword"
leeds to
import pyodbc
connection = pyodbc.connect("DRIVER={ODBC Driver 17 for SQL Server};SERVER=myserver;DATABASE=mydb;UID=myuser;PWD=mypassword", autocommit=True)
Instead of UID you are using username, etc. All words starting with 'my' have to be replaced with the actual db, user and password. You should also remove the Trusted_Connection=True;part as Panagiotis Kanavos pointed out in the comment. This says you are using your windows-user to authenticate (which is obviously not available on linux).

('IM004', "[IM004] [Microsoft][ODBC Driver Manager] Driver's SQLAllocHandle on SQL_HANDLE_ENV failed (0) (SQLDriverConnect)") error

Searched around, but all the other replies seem to be about Oracle, so I decided to create a new post.
I'm currently trying to connect Python to my SQL Server database using the code provided by Microsoft and the pyodbc library. Code as follows.
import pyodbc
server = 'server.database.windows.net'
database = 'testing'
username = 'user'
password = 'password'
cnxn = pyodbc.connect('DRIVER={ODBC Driver 17 for SQL
Server};SERVER='+server+';DATABASE='+database+';UID='+username+';PWD='+
password)
cursor = cnxn.cursor()
This error message comes out.
Exception has occurred: Error
('IM004', "[IM004] [Microsoft][ODBC Driver Manager] Driver's SQLAllocHandle
on SQL_HANDLE_ENV failed (0) (SQLDriverConnect)")
What should I change?
I had the same issue on Windows after upgrading an 'old' SQL Server 2017 client to the last one.
Repairing 'Microsoft ODBC Driver 17 for SQL Server' fixed the problem for me.

Connecting to SQL Server named instance from Linux using pyodbc

I'm currently trying to connect to a SQL Server (that I don't have visibility into, but have credentials for) using PyODBC. The code that I have works on my Windows desktop, but does not work when moved onto my RedHat Linux machine. I need it on Linux in support of a project.
Here's what I have:
server = 'tcp:myserver\inst1'
database = 'mydatabase'
username = 'myusername'
password = 'mypassword'
cnxn = pyodbc.connect('DRIVER={ODBC Driver 13 for SQL Server};SERVER=' + server + ';DATABASE=' + database + ';UID=' + username + ';PWD=' + password)
And here is the error I'm getting:
pyodbc.OperationalError: ('HYT00', u'[HYT00] [unixODBC][Microsoft][ODBC Driver 13 for SQL Server]Login timeout expired (0) (SQLDriverConnect)')
The one difference between the Windows version and Linux version is the driver portion. Windows uses '{SQL Server}' while the Linux version uses '{ODBC Driver 13 for SQL Server}'.
In my /etc/odbcinst.ini file, I have the following information:
[ODBC Driver 13 for SQL Server]
Description=Microsoft ODBC Driver 13 for SQL Server
Driver=/opt/microsoft/msodbcsql/lib64/libmsodbcsql-13.1.so.9.1
UsageCount=1
Anyone have any suggestions?
Unlike the Windows versions of Microsoft's ODBC Drivers for SQL Server, the Linux versions of those drivers are unable to resolve SQL Server instance names. So on a Windows client we can use the following (provided that the SQL Browser service is running on the server)
cnxn = pyodbc.connect(
"Driver=ODBC Driver 17 for SQL Server;"
r"Server=myserver\SQLEXPRESS;"
# and so on
)
but that won't work on Linux. However we can use the sqlserverport module (which I maintain) to retrieve the port number from the SQL Browser service:
import pyodbc
import sqlserverport
servername = "myserver"
serverspec = f"{servername},{sqlserverport.lookup(servername, 'SQLEXPRESS')}"
conn = pyodbc.connect(
"Driver=ODBC Driver 17 for SQL Server;"
f"Server={serverspec};"
# and so on
Use the driver path instead of the driver name. In your example take the full /opt/microsoft/msodbcsql/lib64/libmsodbcsql-13.1.so.9.1
use IP address and port number instead of name/instancename.
execute this query to have the real port number:
SELECT DISTINCT local_net_address, local_tcp_port FROM sys.dm_exec_connections
and then datasrc=N'192.168.1.112,61423'

Error while connecting to the Sql Server with pyodbc

I'm trying to fetch data from SQL database with pyodbc with the code given below.The connection works rarely, most of the time it gives the error,
OperationalError: ('HYT00', '[HYT00] [Microsoft][ODBC SQL Server
Driver]Login timeout expired (0) (SQLDriverConnect)')
import numpy as np
import pyodbc as odbc
conn_string = ('DRIVER={SQL Server};SERVER=test;DATABASE=DEV;UID=me;PWD=whatever;')
cnxn = odbc.connect(conn_string)
cursor = cnxn.cursor()
cursor.execute("Select * from PurchaseOrders")
rows = cursor.fetchall()
ID = [i[1] for i in rows]
ID_array = np.fromiter(ID, dtype= np.int32)
I have tried setting the timeout to zero and DRIVER={ODBC Driver 11 for SQL Server} as I'm using SQL Server 2014. None of these works.
There was a problem with DNS. I used the IP address of the server instead, works fine now.

Categories