当前位置:首页 > 热点

pythonsqlserver源码

用 Python 连 SQL Server,十个人里至少六个踩过驱动坑。我见过最惨的一个案例:团队花了三天排查数据写入失败,最后发现是 pymssql 在 Linux 下跟 FreeTDS 版本对不上。这不是代码逻辑问题,是环境问题。所以聊 Python 操作 SQL Server 的源码,绕不开驱动选型这件事。

目前主流方案就三个:pyodbc、pymssql、sqlalchemy 配合前两者之一。pyodbc 走 ODBC 协议,Windows 上基本开箱即用,Linux 需要装 msodbcsql 驱动包。pymssql 直接跟 FreeTDS 打交道,不依赖微软的 ODBC 驱动,部署轻量一些,但坑也更野。

先看 pyodbc 的连接代码:

import pyodbc conn = pyodbc.connect( "DRIVER={ ODBC Driver 18 for SQL Server};" "SERVER=192.168.1.100,1433;" "DATABASE=TestDB;" "UID=sa;" "PWD=YourPassword;" "TrustServerCertificate=yes;" ) cursor = conn.cursor() cursor.execute("SELECT TOP 10 * FROM Orders") for row in cursor.fetchall(): print(row) 

这段代码本身没什么好说的,重点在连接字符串。ODBC Driver 18 默认强制加密,如果你的 SQL Server 没配证书,不加 TrustServerCertificate=yes 就直接报 SSL 错误。我遇到过有人把驱动版本写成 17 但机器上只装了 18,报错信息是"Data source name not found",跟加密完全无关,但新手很容易往网络方向去查。

pymssql 的写法更简洁:

import pymssql conn = pymssql.connect( server='192.168.1.100', port=1433, user='sa', password='YourPassword', database='TestDB', charset='utf8' ) cursor = conn.cursor(as_dict=True) cursor.execute("SELECT TOP 10 * FROM Orders") for row in cursor.fetchall(): print(row['OrderID'], row['Amount']) 

as_dict=True 这个参数很实用,返回的 row 是字典而不是元组,取值不用记字段顺序。但 pymssql 在 Python 3.11 之后有过一段时间兼容性问题,源码里对 C 扩展的编译依赖比较重,pip install 失败是常事。Windows 上如果有对应的 wheel 包还好,Linux 上经常要自己编译 FreeTDS,折腾程度不低。

再往上走一层就是 sqlalchemy。很多人觉得用 ORM 就"高级"了,其实底层还是调 pyodbc 或 pymssql。sqlalchemy 的价值在于连接池管理和跨数据库方言统一。连接字符串长这样:

from sqlalchemy import create_engine engine = create_engine( "mssql+pyodbc://sa:YourPassword@192.168.1.100:1433/TestDB" "?driver=ODBC+Driver+18+for+SQL+Server" "&TrustServerCertificate=yes", pool_size=10, max_overflow=20 ) 

这里有个细节:连接字符串里的密码如果包含 @ 或 # 这类特殊字符,必须做 URL 编码,否则解析直接出错。我见过密码里带 @ 的,sqlalchemy 把 @ 后面的内容当成了主机地址,报错信息指向一个不存在的主机名,排查起来很费时间。

连接池配置也值得说。默认 pool_size 是 5,对小型应用够用。但 SQL Server 的默认最大连接数是 0(不限制),实际瓶颈往往在应用侧。如果并发请求多,连接池太小会导致请求排队,表现出来就是接口响应时间忽高忽低。max_overflow 设成 pool_size 的两倍左右比较合理,但别设太大,连接数暴涨会把数据库拖垮。

字符编码是另一个高频问题。SQL Server 的 nvarchar 字段存中文没问题,但如果用 pymssql 且 charset 设成了 latin1,读出来的中文就是乱码。pyodbc 在这方面省心一些,ODBC 驱动自己处理编码转换,一般不用额外配置。

批量插入的性能差异也很大。逐条 INSERT 一万条数据,pyodbc 大概要几十秒。executemany 能快不少,但真正快的是 fast_executemany=True 这个参数:

cursor.fast_executemany = True cursor.executemany("INSERT INTO Orders VALUES (?, ?)", data_list) 

这个参数在 pyodbc 4.x 之后才有,原理是走 TDS 协议的批量绑定,减少网络往返。实测一万条插入从 40 秒降到 2 秒左右。pymssql 没有对应的一键开关,得手动拼 BULK INSERT 或者用 executemany 凑合。

选哪个?Windows 环境、团队不想折腾驱动,pyodbc 加 ODBC Driver 18 是最稳的组合。Linux 容器部署、追求轻量,pymssql 可以试试,但做好踩编译坑的准备。需要连接池和 ORM 抽象,sqlalchemy 加 pyodbc 是生产环境最常见的搭配。没有银弹,看你的部署环境和团队熟悉程度来定。

分享到: