mssql-python是Microsoft为SQL Server、Azure SQL 数据库、Azure SQL 托管实例和Microsoft Fabric中的SQL数据库开发的Python驱动程序。 它使用直接数据库连接(DDBC),所以你可以在不安装外部驱动管理器的情况下连接。 该驱动支持 Python 3.10 及更新版本,并符合 Python 数据库 API 规范 2.0,同时为日常开发增加了对 Python 友好的改进。
选择起点
- 要连接SQL Server、Azure SQL 数据库或Microsoft Fabric中的SQL数据库并运行第一个查询,请从Quickstart开始:连接mssql-python驱动。
- 要创建本地 SQL Server 容器,请从容器和本地开发开始。
- 要通过无密码认证连接 Azure SQL,首先使用 Microsoft Entra 认证和连接字符串。
- 要以交互方式探索数据,请从 通过 Jupyter Notebook 连接 或 快速原型设计 开始。
- 要高效移动大量数据,请参阅 批量复制操作 或 批量复制快速入门。
- 要从其他驱动迁移,可以选择 从 pyodbc 迁移、从 pymssql 迁移、从 SQLite 迁移,或从 PostgreSQL 迁移。
Azure SQL的生产基线
本示例连接了带有托管标识和表数据流(TDS)8.0加密的Azure SQL。 它会读取环境变量中的连接设置,并设置独立的登录和查询超时。 每次重试都会重新调用 connect() ,而不是重用失败的连接对象。 上下文管理器在每次尝试后释放连接和光标。
仅将此辅助程序用于可安全重复执行的幂等读取查询。 不要用它来重放单个写入操作或部分完成的交易。
连接字符串中的 ConnectRetryCount 和 ConnectRetryInterval 关键字可启用 SQL Server 的空闲连接复原能力:驱动程序会透明地重新连接已断开的空闲连接。 这与本示例中的应用级重试不同,后者是重试因暂时错误(如死锁或查询超时)失败的 查询 。 两者互补,所以两者都保留。
即使诊断中省略了错误编号,Azure 错误检查仍与标准的英文错误 40501 消息匹配。 它还会在存在时检查 ddbc_error 的已知数字。 匹配是尽力而为:本地化或格式不同的消息可能无法匹配。 更多信息请参见 瞬态连接错误。
import logging
import os
import re
import time
import mssql_python
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s %(levelname)s %(name)s %(message)s",
)
logger = logging.getLogger("app")
TRANSIENT_DRIVER_ERRORS = frozenset({
"Timeout expired",
"Connection timeout expired",
"Client unable to establish connection",
"Communication link failure",
"Connection failure during transaction",
"Serialization failure",
"Statement completion unknown",
})
AZURE_THROTTLING_ERRORS = frozenset({
40197, 40501, 40540, 40613, 40680, 49918, 49919, 49920, 10928, 10929,
})
_ERROR_NUMBER_RE = re.compile(r"\b(?:Error|Msg)\s+(\d+)\b")
_AZURE_40501_MESSAGE = "The service is currently busy. Retry the request after 10 seconds."
def is_azure_throttling(error: BaseException) -> bool:
"""Best-effort detection of Azure SQL throttling in ProgrammingError text."""
if not isinstance(error, mssql_python.ProgrammingError):
return False
ddbc_text = getattr(error, "ddbc_error", "") or ""
return (
_AZURE_40501_MESSAGE in ddbc_text
or any(int(m) in AZURE_THROTTLING_ERRORS for m in _ERROR_NUMBER_RE.findall(ddbc_text))
)
def query_with_retry(
conn_str: str,
sql: str,
*params,
max_attempts: int = 3,
login_timeout_s: int = 5,
query_timeout_s: int = 10,
) -> list:
"""Fetch an idempotent read query, reconnecting before each retry."""
for attempt in range(1, max_attempts + 1):
try:
with mssql_python.connect(conn_str, timeout=login_timeout_s) as conn:
conn.timeout = query_timeout_s
with conn.cursor() as cursor:
cursor.execute(sql, *params)
rows = cursor.fetchall()
logger.info("query succeeded on attempt %d/%d", attempt, max_attempts)
return rows
except mssql_python.Error as exc:
azure_throttling = is_azure_throttling(exc)
transient = (
isinstance(exc, mssql_python.OperationalError)
and exc.driver_error in TRANSIENT_DRIVER_ERRORS
)
if not (transient or azure_throttling) or attempt == max_attempts:
logger.error("query failed on attempt %d/%d: %s", attempt, max_attempts, exc.driver_error)
raise
delay = (10 if azure_throttling else 1) * (2 ** (attempt - 1))
logger.warning(
"query attempt %d/%d hit transient error %r; retrying in %ds",
attempt, max_attempts, exc.driver_error, delay,
)
time.sleep(delay)
raise ValueError("max_attempts must be at least 1")
def main() -> None:
# Read configuration from the environment; never hard-code secrets.
server = os.environ["SQL_SERVER"] # for example, <server>.database.windows.net
database = os.environ["SQL_DATABASE"] # for example, AdventureWorks
client_id = os.getenv("AZURE_CLIENT_ID") # set for a user-assigned managed identity
# Authenticate with the workload's managed identity over TDS 8.0 encryption.
# ConnectRetryCount/ConnectRetryInterval transparently reconnect a dropped
# idle connection; they don't replay a failed query.
conn_str = (
f"Server={server};"
f"Database={database};"
"Authentication=ActiveDirectoryMsi;"
"Encrypt=strict;"
"ConnectRetryCount=3;"
"ConnectRetryInterval=10;"
# Parallel dials to all resolved IPs; safe on single-IP targets.
"MultiSubnetFailover=Yes;"
)
if client_id:
conn_str += f"UID={client_id};"
query = """
SELECT TOP 10
p.BusinessEntityID,
p.FirstName,
p.LastName
FROM Person.Person AS p
ORDER BY p.BusinessEntityID;
"""
try:
rows = query_with_retry(conn_str, query)
for business_entity_id, first_name, last_name in rows:
print(f"{business_entity_id}\t{first_name}\t{last_name}")
except mssql_python.Error:
logger.exception("query failed")
raise
if __name__ == "__main__":
main()
关于本示例中每个问题的更深入指导,请参见 Microsoft Entra 认证、连接池、加密与证书、重试逻辑和错误处理。
主要功能
-
PEP 249 合规性:标准
connect、cursor、execute和fetch*接口,以及 Python 扩展。 -
直接数据库连接(DDBC):无需外部驱动程序管理器。 安装完
mssql-python毕,你就可以连接了。 - Microsoft Entra ID 身份验证:内置对身份验证模式的支持,包括托管标识和服务主体。
- SQL Server 和 Windows 身份验证:支持平台上的 SQL 登录、Kerberos 和 Windows 单点登录(SSO)。
- 批量复制:支持原生 TDS 协议的高性能批量插入,适用于大规模数据加载。
- 原生数据类型支持: JSON、XML、空间、稀疏列、datetimeoffset、十进制/货币 ,并能精确处理。
- Apache Arrow 集成:零拷贝结果集,可与 pandas、Polars 和 DuckDB 进行快速数据交换。
-
异步模式:通过 ThreadPoolExecutor 变通方案,可将该驱动程序用于基于
asyncio的应用程序和 FastAPI。 关于积分模式,请参见 异步模式 。 -
默认 TLS:使用任一 本地 ODBC 提供商时,默认启用 TLS 加密和证书验证。 当你设置
Encrypt=strict时,可以使用 TDS 8.0 加密。
开始
| 文章 | 描述 |
|---|---|
| 安装 | 安装mssql-python并验证你的Python环境。 |
| 快速入门:连接mssql-python | 连接到本地或测试的 SQL Server 实例,运行你的第一个查询。 |
| 快速入门:从Jupyter Notebook连接 | 在笔记本中使用 mssql-python 进行交互式数据探索。 |
| 快速入门:批量复制 | 将大型数据集通过批量复制API迁移到SQL Server。 |
| 快速入门:快速原型制作 | 快速构建小型脚本和概念验证。 |
| 快速启动:可重复部署 | 打包、配置并发布与SQL通信的Python应用程序。 |
| Apache Arrow 快速入门 | 将查询结果导出为Apache Arrow表格,用于分析工作流。 |
配置和认证
| 文章 | 描述 |
|---|---|
| mssql-odbc 提供程序(预览版) | 选择预览原生提供商,查看支持的功能和已知问题。 |
| 连接字符串 | 连接字符串语法、常用关键词和示例。 |
| 程序化构建连接字符串 | 根据配置和机密安全地构建连接字符串。 |
| 连接管理 | 干净利落地打开、重复使用和关闭连接。 |
| 连接池 | 泳池调校、寿命和重复利用模式。 |
| 加密与证书 | TLS加密模式、证书验证和TDS 8.0。 |
| Microsoft Entra 身份验证 | 无密码认证适用于Azure SQL,包含管理身份、服务主体、交互式和设备代码流程。 |
| 安全最佳做法 | 参数化、机密管理、最低特权和加密。 |
| 可用性组 | 连接到 Always On 可用性组和只读副本。 |
处理数据
| 文章 | 描述 |
|---|---|
| 执行查询 |
execute、executemany、多语句批处理和结果集。 |
| 获取数据 |
fetchone、fetchmany、fetchall和流式模式。 |
| 参数化查询 | 安全绑定参数以防止SQL注入。 |
| 存储过程 | 调用过程,读取输出参数,处理结果集。 |
| 光标管理 | 光标寿命、滚动和数组大小调优。 |
| 行对象 | 通过索引、名称或映射形式访问行。 |
| 事务管理 | 提交、回滚、保存点和隔离级别。 |
| 分页 | 针对大型结果集的键集分页和偏移分页模式。 |
| 错误处理 |
mssql_python.Error、DatabaseError以及 SQL Server 错误结构。 |
| 重试逻辑 | 检测瞬态错误,并用指数回馈重试。 |
SQL Server 数据类型与特性
| 文章 | 描述 |
|---|---|
| 数据类型映射 | SQL Server 到 Python 类型的表格和转换规则。 |
| 日期时间处理 |
datetime、datetime2、datetimeoffset以及时区注意事项。 |
| 十进制和货币类型 | 精确数值类型和 decimal.Decimal 精度。 |
| 字符串和Unicode数据 |
varchar、 nvarchar、排序和代码页。 |
| NULL 处理 | 三值逻辑、哨兵和 pandas 互操作。 |
| 二进制数据 |
varbinary、image以及大型对象流式传输。 |
| 定制类型转换器 | 为自定义类型注册输入/输出转换器。 |
| 批量复制操作 | 使用批量复制 API 进行高吞吐量插入。 |
| JSON 数据 | 使用 FOR JSON 和 OPENJSON 存储、查询和分解 JSON。 |
| XML数据 | 使用 xml 数据类型、XPath 和 XQuery。 |
| 空间数据 |
geometry以及geography来自 Python 的类型。 |
| 稀疏列 | 宽表的稀疏列和列集。 |
| 架构发现 | 检查数据库、表格、列和索引。 |
与 Python 工具和框架集成
| 文章 | 描述 |
|---|---|
| Apache Arrow 集成 | 将结果作为箭头表获取,用于零拷贝分析。 |
| Pandas 集成 | 将查询结果加载到DataFrame中并写回。 |
| Polars 集成 | 使用 Polars 配合 mssql-python 处理列式工作负载。 |
| DuckDB 集成 | 同时查询 SQL Server 数据和本地 DuckDB 表。 |
| FastAPI 集成 | 把 mssql-python 接入 FastAPI 服务。 |
| 测试和部署FastAPI应用程序 | 配置 FastAPI 服务的池化、错误、认证、测试和部署设置。 |
| Flask 集成 | 在Flask应用中使用mssql-python。 |
| 异步模式 | 将mssql-python与 asyncio 线程池结合起来。 |
| 数据访问与分析模式 | 为光标访问、箭头提取、pandas、Polars 和对 SQL 数据的 DuckDB 分析选择正确的读取路径。 |
| 数据加载与移动模式 | 选择正确的写入路径,用于逐行插入、批量复制、MERGE upsert 操作、DataFrame 加载和导入 CSV 数据。 |
部署和操作
| 文章 | 描述 |
|---|---|
| 容器和本地开发 | 为连接SQL的Python应用设置Docker容器、开发容器和CI流水线。 |
| 性能优化 | 池优化、预处理语句、批大小和批量复制。 |
| Troubleshooting | 通过症状或错误信息查找指导。 |
| 安装与连接故障排除 | 解决安装、连接、容器和持续集成问题。 |
| 查询、数据与操作故障排除 | 解决查询、数据类型、性能、事务和批量复制问题。 |
| 模块配置 | 模块级设置、日志钩子和功能标志。 |
迁移到 mssql-python
| 文章 | 描述 |
|---|---|
| 从 pyodbc 迁移 | 将 pyodbc API 和连接字符串映射到 mssql-python。 |
| 从 pymssql 迁移 | 用mssql-python替换pymssql,同时保留行为。 |
| 从 SQLite 迁移 | 将本地SQLite工作负载迁移到SQL Server或Azure SQL。 |
| 从 PostgreSQL 迁移 | Python 开发者使用 mssql-python 从 PostgreSQL 迁移到 SQL Server 的一站式指南 |
请求功能
要请求功能,请在 mssql-python GitHub 仓库中打开一个问题。