MacOS X上python连接SQL Server

这是一个记录。虽然微软的文档已经非常完善和友好了,但是涉及到一些软件版本等相关问题,配置并不畅通。

安装

本地环境是macOS Big Sur 11.4版本,使用的是Python 3.8.2版本。

zzx@localhost % python3
Python 3.8.2 (default, Apr  8 2021, 23:19:18)
[Clang 12.0.5 (clang-1205.0.22.9)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>>

需要安装pyodbc、unixodbc、msodbcsql17、mssql-tools等工具(详细参考):

pip3 install pyodbc
brew install unixodbc

测试脚本

主要参考微软文档:Proof of concept connecting to SQL using pyodbc。测试连接脚本如下:

import pyodbc
# Some other example server values are
# server = 'localhost\sqlexpress' # for a named instance
# server = 'myserver,port' # to specify an alternate port
server = 'x.x.x.x'
# server = 'tcp:x.x.x.x,1433'
database = 'xxx'
username = 'xxx'
password = 'xxx'
cnxn = pyodbc.connect('DRIVER={ODBC Driver 17 for SQL Server};SERVER='+server+';DATABASE='+database+';UID='+username+';PWD='+ password)
cursor = cnxn.cursor()

#Sample select query
cursor.execute("SELECT @@version;")
row = cursor.fetchone()
while row:
    print(row[0])
    row = cursor.fetchone()

一下子就跑通了? 有经验的开发者都知道,那当然不能这么顺利,是吧。首先,遇到如下报错:

Traceback (most recent call last):
  File "mssqlremotessh.py", line 10, in <module>
    cnxn = pyodbc.connect('DRIVER={ODBC Driver 17 for SQL Server};SERVER='+server+';DATABASE='+database+';UID='+username+';PWD='+ password)
pyodbc.OperationalError: ('08001', '[08001] [Microsoft][ODBC Driver 17 for SQL Server]Client unable to establish connection (0) (SQLDriverConnect)')

是哪个环节的问题?

老实说,这个报错真的很不友好,无法看出来是什么地方的问题。首先,根据Github上一个issue建议首先通过isql命令(应该是unixODBC的工具)尝试连接一下SQL Server,果然有了新的发现:

# 注意:下面命令的IP和密码都被修改了
isql -v -k 'Driver={ODBC Driver 17 for SQL Server};Server=tcp:18.336.80.202,1433;Database=9zcloud;Uid=zzx;Pwd=********;'


[08001][Microsoft][ODBC Driver 17 for SQL Server]SSL Provider: [OpenSSL library could not be loaded, make sure OpenSSL 1.0 or 1.1 is installed]
[08001][Microsoft][ODBC Driver 17 for SQL Server]Client unable to establish connection
[ISQL]ERROR: Could not SQLDriverConnect

解决openssl版本依赖问题

看起来似乎是ODBC依赖OpenSSL 1.0或者1.1,而查看了本地默认安装的应该是v3版本,查看如下:

$ cd /usr/local/Cellar/ && ls
$ cd openssl@3/3.0.1/bin
$ ./openssl version
$ OpenSSL 3.0.1 14 Dec 2021 (Library: OpenSSL 3.0.1 14 Dec 2021)

自此,已经找到了问题的症结(也可能是问题的症结之一,是吧):似乎是ODBC只认这两个版本的openssl,沿着此线索搜索,发现,这个问题在Github的 issue 59@microsoft/homebrew-mssql-release 中讨论得比较多,而且,在下面的回答中也有一些办法可以尝试解决:在系统中,额外在安装openssl 1.1,并把链接库目录的软连接从3.0版本更换到1.1版本。(这么做,还是有点担心其他的软件运行有问题的,但是先这么做吧,把问题解决了),详细回答参考如下:

具体的操作如下:

zzx@localhost ~ % ls -lah /usr/local/opt/openssl
lrwxr-xr-x  1 zzx  admin    25B 12 28 10:21 /usr/local/opt/openssl -> ../Cellar/openssl@3/3.0.1

unlink /usr/local/opt/openssl

# 这里要注意,你所安装的openssl版本和目录可能和以上截图中是不同的,所以要根据实际情况进行连接,例如我这里是1.1.1m版本,而不是截图中的1.1.1l版本。
ln -s /usr/local/Cellar/openssl@1.1/1.1.1m /usr/local/opt/openssl

Finnally,it works!!

zzx@localhost ~ % ln -s /usr/local/Cellar/openssl@1.1/1.1.1m /usr/local/opt/openssl
zzx@localhost ~ % isql -v -k 'Driver={ODBC Driver 17 for SQL Server};Server=tcp:19.36.80.2,1433;Database=9zcloud;Uid=zzx;Pwd=******;'
+---------------------------------------+
| Connected!                            |
|                                       |
| sql-statement                         |
| help [tablename]                      |
| quit                                  |
|                                       |
+---------------------------------------+
SQL> select * from dbo.t_1;
+------------+---------------------------------+-----------+
| id         | nick                            | birthday  |
+------------+---------------------------------+-----------+
| 1          |                                 |           |
| 2          | zzx                             |           |
| 3          | yzs                             | 2008-09-23|
+------------+---------------------------------+-----------+

在回头去运行,最前面的示例脚本,也可以正常连接SQL Server,至此,剧终。所以,回头来看,今天的解决问题的堆栈如下:

  • unixODBC关于openssl版本兼容性的问题
  • 安装unixODBC & mssql-tools
  • 尝试python连接SQL Server
  • 尝试通过ssh tunnel连接SQL Server

相关阅读

  • 更多关于什么是unixODBC,什么事isql,可以参考:unixODBC
  • Install the Microsoft ODBC driver for SQL Server (macOS):参考

Leave a Reply

Your email address will not be published. Required fields are marked *