mssql-python 有什麼新內容

每個 mssql-python 驅動程式版本都會引入新功能、效能提升及錯誤修正。 以下章節將詳細介紹每個版本。

MSSQL-Python 1.12.0

發行日期:2026年7月

Enhancements

獨立的 mssql-python-odbc 配套套件

執行時需要的 ODBC 驅動二進位 mssql-python 檔現在也以獨立的、僅資料的伴隨套件形式發佈: mssql-python-odbc (匯入名稱 mssql_python_odbc,目前釘選為版本 18.6.2)。 mssql-python 套件會在 install_requires 中宣告 mssql-python-odbc==18.6.2,因此 pip install mssql-python 會自動一併安裝配套套件。 不需要變更程式碼。

原生載入器在外部 mssql_python_odbc 套件存在時,會優先使用它;若不存在,則會退回使用仍隨附於 mssql-python wheel 套件中的 ODBC 二進位檔。 備用方案則安全,採用 Python 全域直譯器鎖(GIL),並適用於基於 musl 的 Linux 發行版如 Alpine。

這種分割讓你可以獨立於 Python 程式碼釘選或更新驅動二進位檔,讓再分配器的輪子隨時間縮小mssql-python,並避免捆綁 ODBC 檔案產生重複擁有權的問題。

這很重要

這讓船隻分開且不會有破壞性變化。 在未來的重大版本(v2.0.0)中,可能會移除捆綁的 libs/ 樹狀結構,屆時 mssql-python-odbc 將成為硬性執行時需求。

錯誤修正

cursor.bulkcopy() 現在會使用父連線的連線逾時設定

批量複製操作會透過 mssql_py_core 原生擴充功能開啟獨立連線。 過去,這項操作一律使用寫死的 15 秒連線逾時設定,且無法透過 Python 覆寫。 如果你在父連線connect(..., timeout=<seconds>)設定連線逾時(), bulkcopy() 就會將該值轉發到內部連線。 將其設為 timeout=0 可保留 不覆寫 的行為,並維持內部預設的 15 秒值。 在呼叫 bulkcopy() 時,游標的逾時設定會套用於此作業,因此後續對父連線所做的變更不會影響進行中的大量複製作業。

以下範例使用 AdventureWorks 範例資料庫中的 Production.Culture查閱資料表。 根據你的環境調整 連接字串 和資料庫名稱:

import mssql_python
from datetime import datetime

# The 60-second timeout applies to both the initial connection and
# the internal connection that bulkcopy() opens.
conn = mssql_python.connect(
    "Server=<server>;"
    "Database=AdventureWorks2022;"
    "Encrypt=yes",
    timeout=60,
)
conn.autocommit = True
cursor = conn.cursor()

# Bulk-copy two rows into Production.Culture (CultureID, Name, ModifiedDate).
now = datetime.now()
rows = [
    ("xx", "Demo culture 1", now),
    ("yy", "Demo culture 2", now),
]
result = cursor.bulkcopy("Production.Culture", rows)
print(f"Copied {result['rows_copied']} rows")

# Remove the demo rows so the sample is re-runnable.
cursor.execute("DELETE FROM Production.Culture WHERE CultureID IN ('xx','yy')")

cursor.bulkcopy() 支援 CLR 使用者自訂型別欄位

先前,對於任何使用通用語言執行階段(CLR)使用者定義型別的目的地資料行,cursor.bulkcopy() 都會因 Protocol Error: Unsupported TDS type for bulk copy: 0xF0 而失敗,包括內建的 geographygeometryhierarchyid 型別,以及任何自訂、已註冊於組件中的 CLR UDT。 原生 mssql_py_core 傳輸路徑沒有可處理 UDT 類型權杖(0xF0)的處理常式,並且在寫入資料行中繼資料時、尚未傳送任何資料列之前就發生錯誤。 CLR UDT 欄位現在在線路傳輸時會對應為 varbinary(max),而提供的位元組會以 UDT 的 IBinarySerialize 承載資料形式進行串流傳輸,這與 pyodbcpython-tds 載入 UDT 欄位的方式一致。 SQL Server 在插入時實現 UDT。 透過 mssql_py_core 從 0.1.6 升級到 0.1.7 提供。

以下範例會將來自 HumanResources.Employee 的 org-chart 資料行(這是 hierarchyid 資料行,屬於 SQL Server 內建 CLR UDT 之一)封存到新的資料表中。 在實際工作流程中,UDT 位元組可能來自另一個 SQL Server 執行個體、序列化檔案,或你的 CLR 類型的 IBinarySerialize.Write() 輸出;此範例透過 CAST(... AS varbinary(max)) 從現有欄位讀取這些位元組,因此整個範例可自成一體。 大量複製包含 OrganizationNode 為 NULL 的資料列:

import mssql_python

conn = mssql_python.connect(
    "Server=<server>;"
    "Database=AdventureWorks2022;"
    "Encrypt=yes",
)
conn.autocommit = True  # bulkcopy uses a separate connection; the destination must be visible
cursor = conn.cursor()

cursor.execute(
    "IF OBJECT_ID('dbo.EmployeeOrgArchive','U') IS NOT NULL "
    "DROP TABLE dbo.EmployeeOrgArchive;"
    "CREATE TABLE dbo.EmployeeOrgArchive (BusinessEntityID int, OrganizationNode hierarchyid);"
)

# Casting a hierarchyid column to varbinary(max) yields the UDT's
# serialized IBinarySerialize payload.
cursor.execute(
    "SELECT BusinessEntityID, CAST(OrganizationNode AS varbinary(max)) "
    "FROM HumanResources.Employee;"
)
rows = cursor.fetchall()

# Stream the (id, bytes) tuples into the destination's hierarchyid column.
result = cursor.bulkcopy("dbo.EmployeeOrgArchive", rows)
print(f"Copied {result['rows_copied']} rows")

cursor.execute("DROP TABLE dbo.EmployeeOrgArchive")

對於自訂且已在組件中註冊的 CLR UDT,請使用目標資料表中的該型別,並提供由該型別的 IBinarySerialize.Write() 方法所產生的位元組資料。

MSSQL-Python 1.11.0

發行日期:2026年7月

Enhancements

改進的上下文管理器語意

with connection: 現在會在正常結束時正確提交事務,並在發生例外時回滾,使其更符合 Python 風格,且行為更可預測。

import mssql_python

# On clean exit, transaction commits
with mssql_python.connect(connection_string) as conn:
    cursor = conn.cursor()
    cursor.execute("INSERT INTO MyTable (Name) VALUES ('Alice')")
    # Automatically committed on exit

# On exception, transaction rolls back
try:
    with mssql_python.connect(connection_string) as conn:
        cursor = conn.cursor()
        cursor.execute("INSERT INTO MyTable (Name) VALUES ('Bob')")
        raise ValueError("Oops!")
except ValueError:
    pass
# Changes rolled back on exit

錯誤修正

  • 修正了 ODBC 拆解路徑(conn.close()cursor.close())中的 GIL 死結,以及在 SSH 隧道與程序內轉發器設定中,SQLDescribeParamNone-值參數所引發的 GIL 死結。
  • 暫存表格和表格變數中的固定 BINARY 參數與 VARBINARY NULL 參數。 當自動型別解析失敗時,驅動程式會發出帶有明確cursor.setinputsizes()指引的 Python 警告。
  • 修正了 import mssql_python 在 Apple Silicon 上進行全新安裝時失敗的問題(1.8.0 版中的回歸問題)。 隨附的 ODBC dylib 相依項目現已針對 arm64x86_64 兩種架構重寫。
  • 修正了 Rust 核心中一個 GIL 死結,導致在使用 Authentication=ActiveDirectoryServicePrincipal. 進行驗證時,會凍結批量複製操作。

MSSQL-Python 1.10.0

發行日期:2026年6月

Enhancements

ActiveDirectoryServicePrincipal 對批量複製的支援

cursor.bulkcopy() 現已支援 Authentication=ActiveDirectoryServicePrincipal,允許使用服務主體憑證進行批量插入。

import mssql_python

conn = mssql_python.connect(
    "Server=<server>.database.windows.net;"
    "Database=<database>;"
    "Authentication=ActiveDirectoryServicePrincipal;"
    "UID=<application-client-id>;"
    "PWD=<client-secret>;"
    "Encrypt=yes"
)
cursor = conn.cursor()
cursor.execute("CREATE TABLE ##SpDemo (ID INT, Value FLOAT)")
conn.commit()

result = cursor.bulkcopy("##SpDemo", [(1, 1.5), (2, 2.5)])
print(f"Copied {result['rows_copied']} rows")

錯誤修正

  • 修正了 Arrow 擷取路徑中的非 ASCII VARCHARCHAR 資料。
  • 已修正執行大量載入作業時的連線逾時問題。

MSSQL-Python 1.9.0

發行日期:2026年6月

Enhancements

批量複製中的列物件

cursor.bulkcopy() 現在可以直接接受取指的 Row 物件,而不需要手動進行元組轉換。

import mssql_python

conn = mssql_python.connect(connection_string)
cursor = conn.cursor()

# Fetch rows from source table
cursor.execute("SELECT ProductID, Name, ListPrice FROM Production.Product")
rows = cursor.fetchall()

# Pass fetched Row objects directly to bulkcopy
cursor.execute("CREATE TABLE ##RowBulkDemo (ProductID INT, Name NVARCHAR(50), ListPrice MONEY)")
conn.commit()
result = cursor.bulkcopy("##RowBulkDemo", rows)
print(f"Copied {result['rows_copied']} rows")

錯誤修正

  • 固定輪圈包裝,因此 simdutf 始終靜態連結。
  • 修正了 DECIMAL 中的大型executemany()插入內容。
  • 修正了 NULL 參數的錯誤型別備援。
  • 修正了例外在 pickle 與 unpickle 往返處理中的問題。
  • 已修正 nextset(),使其可在各個結果集之間保留 PRINT 訊息。
  • 修正了 Row 的執行時資料備援路徑中對 executemany() 的處理。
  • 修正了靜態分析工具對 fetch 方法的型別檢查。

MSSQL-Python 1.8.0

發行日期:2026年5月

Enhancements

ActiveDirectoryMSI 對批量複製的支援

cursor.bulkcopy() 現支援 Authentication=ActiveDirectoryMSI 系統指派與使用者指派的管理身份。

import mssql_python

# System-assigned managed identity
conn = mssql_python.connect(
    "Server=<server>.database.windows.net;"
    "Database=<database>;"
    "Authentication=ActiveDirectoryMSI;"
    "Encrypt=yes"
)
cursor = conn.cursor()
cursor.execute("CREATE TABLE ##MsiDemo (ID INT, Name NVARCHAR(50))")
conn.commit()

result = cursor.bulkcopy("##MsiDemo", [(1, "Alice"), (2, "Bob")])
print(f"Copied {result['rows_copied']} rows")

列字串鍵索引

例如,除了位置索引和屬性存取外,你現在還可以透過欄位名稱 row["col"]存取列值。

import mssql_python

conn = mssql_python.connect(connection_string)
cursor = conn.cursor()

cursor.execute("SELECT ProductID, Name, ListPrice FROM Production.Product WHERE ProductID = 1")
row = cursor.fetchone()

# Access by column name (new in 1.8.0)
print(row["ProductID"]) # Access by key
print(row["Name"])

# Still supports positional indexing
print(row[0])           # Positional access

# And attribute access
print(row.Name)         # Attribute access

隨附的 ODBC 驅動程式升級

隨附的 Microsoft ODBC SQL Server 驅動程式更新至 18.6.2.1。

錯誤修正

  • 修正基於代幣認證中延遲連接屬性壽命的問題。
  • 修正了認證路徑中重複的 連接字串 解析。
  • 序列輸入的固定 executemany() 型別註解。

MSSQL-Python 1.7.1

發行日期:2026年5月

Enhancements

擴大輪圈覆蓋範圍與性能提升

此版本新增了相容於 RHEL 8 的 wheel 套件,恢復了 macOS Python 3.10 的 universal2 wheel 套件,並透過 simdutf 改善了 UTF-16 的處理,同時最佳化了 execute() 熱路徑。

效能影響:由於熱路徑優化 execute() ,批次執行吞吐量在典型工作負載上提升了約 15%。

錯誤修正

  • 已修正登入失敗問題,使其引發 mssql_python DB-API 例外,而非 RuntimeError
  • 擴展 GIL 釋放,涵蓋阻塞 ODBC 執行、取指、交易及連線屬性呼叫。
  • 已修正小數值變號時的 executemany() 錯誤。
  • 修正了跨平台不一致的 CP1252 VARCHAR 解碼問題。
  • 修正了 cursor.bulkcopy()NVARCHAR(MAX) 欄位中空字串導致的 VARCHAR(MAX) 失敗問題。

Note

1.7.0 版本因出版問題而被撤回。 使用版本 1.7.1 或更新版本。

MSSQL-Python 1.6.0

發行日期:2026年4月

Enhancements

基於語法分析器的連線字串清理

此強化確保密碼欄位及括號值中特殊字元的正確解析。

import mssql_python

# Complex passwords with special characters now parse correctly
conn = mssql_python.connect(
    "Server=<server>.database.windows.net;"
    "Database=<database>;"
    "UID=user@contoso;"
    "PWD={p@ssw0rd;with{braces}};"  # Braced values now handled correctly
    "Encrypt=yes"
)

連線字串清理已從以正則表達式為基礎的邏輯,改為以剖析器為基礎的處理方式,以正確處理 ODBC 連線字串語法。

錯誤修正

  • 已修正在 ODBC 連線與中斷連線的阻塞作業期間釋放 GIL 的問題。
  • 修正了與 setinputsizes()SQL_DECIMAL 提示相關的 SQL_NUMERIC 當機問題。
  • 修正了 ODBC 目錄方法的錯誤 fetchone() 行為。
  • 修正了使用 reset_cursor=False 時發生的無效游標狀態錯誤。
  • 修正了以映射為基礎的參數序列的 executemany() 型別提示。
  • 新增 `setup_logging(log_file_path=...)` 的路徑遍歷防護機制。

MSSQL-Python 1.5.0

發行日期:2026年4月

新功能

Apache Arrow 擷取支援

三種新的游標方法透過 Arrow C 資料介面提供高效能的欄位資料檢索:

  • cursor.arrow() 會傳回完整的 pyarrow.Table
  • cursor.arrow_batch() 返回一個 pyarrow.RecordBatch
  • cursor.arrow_reader() 會回傳用於串流的 pyarrow.RecordBatchReader

此實作在關鍵路徑中略過建立 Python 物件,以提升效能。 完整文件請參閱 Apache Arrow 整合

sql_variant 類型支援

驅動程式現在會在擷取時偵測 sql_variant 欄位,解析其底層基本型別,並回傳型別正確的 Python 值,而非原始位元組。

Note

sql_variant 欄位採用串流擷取路徑,與固定型欄位相比,可能會對效能造成些微影響。

原生 UUID 支援

新的 native_uuid 設定可控制 UNIQUEIDENTIFIER 欄位是以 uuid.UUID 物件(預設)傳回,還是以與 pyodbc 相容的大寫字串傳回。 在模組層級或依各個連線進行設定:

# Module-level default
settings = mssql_python.get_settings()
settings.native_uuid = True  # default

# Per-connection override
conn = mssql_python.connect(connection_string, native_uuid=False)

更多資訊請參見 模組配置

Row 類別 公開匯出

Row該類別現在在頂層匯出用於型別註解:

from mssql_python import Row

錯誤修正

  • 修正了在加括號的識別碼、字串常值和註解中將 ? 誤判為偵測目標的問題。
  • 已修正 VARBINARY 欄位的 NULL 參數繫結問題(不再引發隱含轉換錯誤)。
  • 修正了 datetime.timeTIME(1) 欄位中的 TIME(7) 值在往返轉換時會遺失微秒的問題。
  • 已修正 Arrow 擷取路徑,使其能正確包含 TIME 欄位的小數秒。
  • 已修正使用 Microsoft Entra ID 驗證方法時的大量複製問題(過時的認證欄位不再導致驗證錯誤)。
  • 在模組層級快取 Azure Identity 認證實例,以提升驗證效能。

MSSQL-Python 1.4.0

上映日期:2025年3月

新功能

批量複製支援

高效能大量資料載入現已可透過 cursor.bulkcopy() 使用:

import mssql_python

conn = mssql_python.connect(connection_string)
cursor = conn.cursor()

cursor.execute("CREATE TABLE ##BulkDemo (ID INT, Name NVARCHAR(50), Price DECIMAL(10,2))")
conn.commit()

data = [
    (1, "Item 1", 10.50),
    (2, "Item 2", 20.75),
    # ... potentially millions of rows
]

result = cursor.bulkcopy("##BulkDemo", data)
print(f"Copied {result['rows_copied']} rows")

此方法接受用於 batch_sizetimeoutcolumn_mappingskeep_identitycheck_constraintstable_lockkeep_nullsfire_triggersuse_internal_transaction 的選項。

完整文件請參閱 「批量副本 」。

Improvements

  • 針對大型結果集的效能優化。
  • 減少批次作業中的記憶體使用。
  • 大量複製失敗時的增強型錯誤訊息。

MSSQL-Python 1.3.0

發行日期:2025年1月

新功能

設定類別

透過新 Settings 類別配置模組範圍的行為:

import mssql_python

settings = mssql_python.get_settings()
settings.lowercase = True       # Lowercase column names in cursor.description

詳情請參見 模組配置

Improvements

  • 改善 Azure SQL 故障轉移期間的連線逾時處理。
  • 提升與 Python 3.13 的相容性。

MSSQL-Python 1.2.0

發行日期:2024年11月

新功能

結構發現方法

用於資料庫元資料探索的新游標方法:

cursor = conn.cursor()

# List all tables
cursor.tables(schema="dbo")

# Get column information
cursor.columns(table="Product", schema="Production")

# Get primary keys
cursor.primaryKeys(table="Product", schema="Production")

# Get foreign key relationships
cursor.foreignKeys(table="SalesOrderDetail", schema="Sales")

# Get stored procedures
cursor.procedures(schema="dbo")

# Get index statistics
cursor.statistics(table="Product", schema="Production")

# Get type information
cursor.getTypeInfo()

完整文件請參閱 結構發現

Improvements

  • 針對重複的結構描述查詢提供增強的中繼資料快取。
  • 結果中計算欄位 columns() 的處理更佳。

MSSQL-Python 1.1.0

上映日期:2024年9月

新功能

客製化輸出轉換器

註冊自訂函式,以便在擷取時轉換欄位值:

import mssql_python
from decimal import Decimal

conn = mssql_python.connect(connection_string)

# Convert decimals to float (converter receives Decimal)
def decimal_to_float(value):
    if value is None:
        return None
    return float(value)  # value is already a Decimal object

conn.add_output_converter(mssql_python.SQL_DECIMAL, decimal_to_float)

# Custom money formatting
def format_money(value):
    if value is None:
        return "$0.00"
    return f"${float(value):,.2f}"  # value is already a Decimal object

conn.add_output_converter(mssql_python.SQL_DECIMAL, format_money)

管理方法:

  • add_output_converter(sql_type, converter_func)
  • get_output_converter(sql_type)
  • remove_output_converter(sql_type)
  • clear_output_converters()

完整文件請參閱 「自訂類型轉換器」。

Improvements

  • 型別轉換失敗時的錯誤訊息會更好。
  • 支援返回 None的轉換函數。

MSSQL-Python 1.0.0

發行日期:2024年7月

最初的通用授權釋出

mssql-python 的首個正式發行版本,Microsoft SQL Server 的原生 Python 驅動程式。

核心功能

  • DDBC 架構:直接進行資料庫連接,無需安裝 ODBC 驅動程式。
  • DB-API 2.0 合規性:標準Python資料庫介面。
  • 連線集區:內建連線集區管理功能。
  • Microsoft Entra 認證:完全支援 Azure 身份認證。
  • TLS 加密:具備憑證驗證的安全連線。

連接功能

  • 21 個連接字串關鍵字。
  • 9 種認證模式(SQL、Windows 及 7 種 Microsoft Entra ID 方法)。
  • 自動提交控制。
  • 執行方法:execute()、、 executemany()batch_execute()和 。
  • 連接屬性透過 set_attr()getinfo()
  • 情境管理員支援。

游標功能

  • 標準擷取方法:fetchone()fetchmany()fetchall()
  • 擴展方法: fetchval()skip()
  • 執行方法: execute()executemany()
  • 資料列物件可透過屬性和索引存取。
  • 使用 nextset() 進行多重結果集導覽。

資料類型支援

  • 所有 SQL Server 原生類型。
  • Python↔SQL 型別對應。
  • 用於明確指定型別的 SQL 型別常數(例如 mssql_python.SQL_DECIMAL)。
  • Python 中的 NULL 處理 None

交易支援

  • 手動提交與回滾。
  • 自動提交模式。
  • 隔離層控制。
  • 死鎖偵測與處理。

認證模式

Mode 描述
SQL Server 認證 使用者名稱與密碼
Windows 驗證 Trusted_Connection
ActiveDirectoryDefault DefaultAzureCredential
ActiveDirectoryInteractive 基於瀏覽器的登入
ActiveDirectoryDeviceCode 裝置代碼流程
ActiveDirectoryPassword Microsoft Entra 使用者名稱與密碼(已棄用;使用ROPC系統)
ActiveDirectoryMSI 受管理的識別
ActiveDirectoryServicePrincipal 服務主體
Active Directory 整合式 Windows Kerberos

Upgrade

來自 pyodbc

如需詳細遷移指引,請參見「從 pyodbc 遷移」。

主要差異:

  • 支援 ?(qmark)與 %(name)s(pyformat)兩種參數樣式。 你現有 ? 的查詢無需更改即可運作。
  • 沒有 callproc() 方法。 改用 EXECUTE 語句。
  • 內建連線池。
  • 沒有外部 ODBC 驅動程式依賴。

來自 pymssql

如需詳細遷移指引,請參閱從 pymssql 遷移。

主要差異:

  • %s%d 參數標記取代為 ?%(name)s
  • 請使用連線字串,而非位置引數。
  • 沒有 FreeTDS 依賴。
  • 每個連線有多個並行游標。
  • 具有屬性存取權的列物件替換 as_dict=True

mssql-python 各版本之間

升級驅動程式以獲得新功能和修正。

pip install --upgrade mssql-python

升級生產系統前,請先查看發布說明是否有任何破壞性的變更。

藍圖

關於即將推出的功能與開發路線圖,請參閱 GitHub 倉庫