Blog Post

SQL Server Blog
2 MIN READ

mssql-python v1.12.0: Standalone ODBC package, bulk copy fixes

DavidLevy's avatar
DavidLevy
Icon for Microsoft rankMicrosoft
Jul 24, 2026

We're pleased to announce the 12th release of the Microsoft Python Driver for SQL Server since GA: v1.12.0.

Want to try it?

pip install --upgrade mssql-python

What's new

Standalone mssql-python-odbc package for ODBC driver binaries

You may remember that we ran out of space to publish on PyPi a few releases ago. To prevent that from happening again, the ODBC driver binaries that mssql-python needs at runtime are now also published as a separate, pure-data companion package: mssql-python-odbc (import name mssql_python_odbc, currently pinned to 18.6.2).

mssql-python declares mssql-python-odbc==18.6.2 in install_requires, so pip install mssql-python transparently pulls the driver package alongside it. At import time, the native loader prefers the external mssql_python_odbc package when it is present, and falls back to the ODBC driver binaries still bundled inside the mssql-python wheel when it is not. Existing installations keep working with no code changes. The fallback is GIL-safe and Alpine/musl-safe.

Who benefits

  • Users who want to keep driver binaries pinned or updated independently of the Python driver code.
  • Redistributors who want a slimmer mssql-python wheel over time.
  • Anyone who has hit duplicate-ownership issues from bundled ODBC files.

Bug fixes

Bulk copy now honors the connection timeout

cursor.bulkcopy() opens a separate connection through mssql_py_core, which previously defaulted to a hardcoded 15-second connect timeout with no way to override it from Python.

The cursor's query timeout (set via connect(timeout=X)) is now forwarded into mssql_py_core's connect_timeout when it is set. timeout=0 is preserved as "no override" and leaves mssql_py_core on its 15-second default. The cursor's timeout snapshot at the time of the bulkcopy() call is what is used, so later changes to the parent connection do not affect an in-flight bulk copy.

import mssql_python

# Give bulk copy 60 seconds to establish the second connection.
conn = mssql_python.connect(conn_str, timeout=60)
cursor = conn.cursor()
cursor.bulkcopy(rows, table="dbo.MyTable")

Who benefits

  • Applications that call bulkcopy() against slow, throttled, or high-latency SQL Server endpoints (VPN, cross-region)
  • Applications that need to fail fast with a shorter timeout.

Bulk copy into custom CLR UDT columns

cursor.bulkcopy() into a column whose type is a custom, assembly-registered CLR UDT (any UDT other than the built-in geography, geometry, or hierarchyid) previously failed with:

Protocol Error: Unsupported TDS type for bulk copy: 0xF0

The native core had no handler for the UDT (0xF0) type token when writing COLMETADATA. The Rust core now maps UDT columns to varbinary(max) on the wire and streams the supplied bytes as the UDT's serialized form (its IBinarySerialize payload), matching how pyodbc and python-tds load UDT columns. SQL Server materializes the UDT on insert.

More information

PyPI: https://pypi.org/project/mssql-python/1.12.0/

Release notes: https://github.com/microsoft/mssql-python/releases

README: https://github.com/microsoft/mssql-python#microsoft-python-driver-for-sql-server

Get involved

Bug reports, feature requests, and PRs are welcome on GitHub: https://github.com/microsoft/mssql-python

Published Jul 24, 2026
Version 1.0
No CommentsBe the first to comment