Microsoft Python SQL Server ドライバー - mssql-python

mssql-pythonMicrosoftのSQL Server、Azure SQL Database、Azure SQL Managed Instance、およびMicrosoft FabricのSQLデータベース向けのPythonドライバーです。 Direct Database Connectivity(DDBC)を使っているので、外部ドライバーマネージャーをインストールせずに接続できます。 このドライバーはPython 3.10以降をサポートし、Python Database API Specification 2.0に準拠しつつ、日常開発のためにPythonに優しい改善を加えています。

出発点を選択する

Azure SQLの運用ベースライン

このサンプルを本番向けAzure SQL接続の出発点として活用してください。 環境から設定を読み込み、マネージドIDで認証し、Tabular Data Stream(TDS)8.0暗号化を有効にします。 また、ログインおよび文ごとのクエリタイムアウトを設定し、一時的な失敗を指数関数的にバックオフ(接続エラー時は新しい接続、デッドロックなどのクエリエラー時には同じ接続)を用いて再試行し、結果をログ化し、コンテキストマネージャーによるリソース解放に依存します。

接続文字列内のConnectRetryCountおよびConnectRetryIntervalキーワードにより、SQL Server のアイドル接続の回復性が有効になります。つまり、ドライバーは切断されたアイドル接続を透過的に再接続します。 これは、このサンプルのアプリケーションレベルの再試行とは異なります。リトライは、デッドロックやクエリタイムアウトなどの一時的なエラーで失敗した クエリ を再試行します。 この二つは補完的なものなので、両方保持してください。

import logging
import os
import time

import mssql_python

logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s %(levelname)s %(name)s %(message)s",
)
logger = logging.getLogger("app")

# Transient errors that require a fresh connection to recover.
CONNECT_RETRY_ERRORS = frozenset({
    "Timeout expired",
    "Connection timeout expired",
    "Client unable to establish connection",
    "Communication link failure",
    "Connection failure during transaction",
})

# Transient errors that leave the connection usable, such as a deadlock victim
# or a query timeout, so retry on the same connection.
QUERY_RETRY_ERRORS = frozenset({
    "Serialization failure",
    "Timeout expired",
})


def connect_with_retry(conn_str: str, max_attempts: int = 3, login_timeout_s: int = 5) -> mssql_python.Connection:
    """Open a connection, retrying transient failures with exponential backoff."""
    for attempt in range(1, max_attempts + 1):
        try:
            conn = mssql_python.connect(
                conn_str,
                attrs_before={mssql_python.SQL_ATTR_LOGIN_TIMEOUT: login_timeout_s},
            )
            logger.info("connected on attempt %d/%d", attempt, max_attempts)
            return conn
        except mssql_python.OperationalError as exc:
            if exc.driver_error not in CONNECT_RETRY_ERRORS or attempt == max_attempts:
                logger.error("connect failed on attempt %d/%d: %s", attempt, max_attempts, exc.driver_error)
                raise
            delay = 2 ** (attempt - 1)  # 1s, 2s, 4s
            logger.warning(
                "connect attempt %d/%d hit transient error %r; retrying in %ds",
                attempt, max_attempts, exc.driver_error, delay,
            )
            time.sleep(delay)


def execute_with_retry(
    conn: mssql_python.Connection,
    sql: str,
    *params,
    max_attempts: int = 3,
    query_timeout_s: int = 10,
) -> mssql_python.Cursor:
    """Run sql on an open connection and return the ready-to-fetch cursor.

    Retries errors that leave the connection usable so callers don't wrap each
    query in its own function. Pass query values as parameters. Retry only
    idempotent statements; wrap writes in an explicit transaction.
    """
    for attempt in range(1, max_attempts + 1):
        cursor = mssql_python.Cursor(conn, timeout=query_timeout_s)
        try:
            cursor.execute(sql, *params)
            if attempt > 1:
                logger.info("query succeeded on attempt %d/%d", attempt, max_attempts)
            return cursor
        except mssql_python.OperationalError as exc:
            cursor.close()
            if exc.driver_error not in QUERY_RETRY_ERRORS or attempt == max_attempts:
                logger.error("query failed on attempt %d/%d: %s", attempt, max_attempts, exc.driver_error)
                raise
            delay = 2 ** (attempt - 1)  # 1s, 2s, 4s
            logger.warning(
                "query attempt %d/%d hit transient error %r; retrying in %ds",
                attempt, max_attempts, exc.driver_error, delay,
            )
            time.sleep(delay)
    raise RuntimeError("unreachable: the retry loop exits by return or raise")


def main() -> None:
    # Read configuration from the environment; never hard-code secrets.
    server = os.environ["SQL_SERVER"]      # for example, myserver.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;"
    )
    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:
        # Context managers close the cursor and connection automatically.
        with connect_with_retry(conn_str) as conn:
            with execute_with_retry(conn, query) as cursor:
                for business_entity_id, first_name, last_name in cursor.fetchall():
                    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準拠:標準 connectcursorexecutefetch* インターフェースに加え、Pythonic拡張機能も利用できます。
  • 直接データベース接続(DDBC):外部ドライバーマネージャーは不要。 mssql-pythonをインストールしれば接続の準備が整います。
  • Microsoft Entra ID認証:管理型アイデンティティやサービスプリンシパルを含む認証モードの組み込みサポート。
  • SQL ServerおよびWindows 認証:対応プラットフォーム上でのSQLログイン、Kerberos、Windowsシングルサインオン(SSO)。
  • バルクコピー:TDSプロトコルをネイティブサポートし、大規模なデータ負荷向けの 高性能バルクインサート
  • ネイティブのデータ型サポート: JSON、XML、空間、スパースカラム、datetimeoffset、10進数/マネー と精密な処理が可能です。
  • Apache Arrow統合: pandas、Polars、DuckDBとの高速なデータ交換を実現するゼロコピーの結果セット
  • 非同期パターン: asyncioベースのアプリケーションやThreadPoolExecutorのFastAPIの回避策でドライバーを使用してください。 積分パターンについては 非同期パターン を参照してください。
  • TLSはデフォルトで: TLS暗号化および証明書検証 はデフォルトでオン(ODBCドライバー18経由)。 Encrypt=strict を設定すると、TDS 8.0 の暗号化を利用できます。

概要

[アーティクル] 説明
Installation mssql-pythonをインストールしてPython環境を確認してください。
クイックスタート:mssql-pythonと接続しましょう ローカルまたはテスト用のSQL Serverインスタンスに接続し、最初のクエリを実行してください。
クイックスタート:Jupyter Notebookから接続 mssql-pythonをノートブック内で使い、インタラクティブなデータ探索をしましょう。
クイックスタート:一括コピー 大量データセットをSQL ServerにまとめコピーAPIで移動させます。
クイックスタート:ラピッドプロトタイピング 小さなスクリプトや概念実証を素早く作りましょう。
クイックスタート:繰り返し展開 SQLと連携するPythonアプリケーションをパッケージ化、設定、出荷しましょう。
Apache Arrow クイックスタート 分析ワークフロー用のApache Arrowテーブルとしてクエリ結果を取得すること。

設定と認証

[アーティクル] 説明
接続文字列 接続文字列の構文、よく使われるキーワード、そして例。
接続文字列をプログラム的に構築する 設定や秘密から安全に接続文字列を構成してください。
接続管理 接続をきれいに開けて、再利用し、閉じてください。
接続プール プールの調整、寿命、再利用パターン。
暗号化と証明書 TLS暗号化モード、証明書検証、TDS 8.0。
Microsoft Entra 認証 管理されたアイデンティティ、サービスプリンシパル、インタラクティブ、デバイスコードフローを備えたAzure SQLのパスワードレス認証。
セキュリティのベスト プラクティス パラメーター化、シークレット管理、最小特権、暗号化。
可用性グループ Always Onの可用性グループや読み取り専用レプリカに接続してください。

データの操作

[アーティクル] 説明
クエリの実行 executeexecutemany、複数ステートメント バッチ、および結果セット。
データの取得 fetchonefetchmanyfetchall、そしてストリーミングパターン。
パラメーター化されたクエリ パラメータを安全にバインドしてSQLインジェクションを防ぎましょう。
ストアド プロシージャ プロシージャの呼び出し、出力パラメータの読み取り、結果セットの処理。
カーソル管理 カーソルの寿命、スクロール、そして配列サイズの調整。
行オブジェクト インデックス、名前、またはマッピングで行にアクセスできます。
トランザクション管理 コミット、ロールバック、セーブポイント、そしてアイソレーションレベル。
ページネーション 大きな結果セットに対するキーセットおよびオフセットページングパターン。
エラー処理 mssql_python.ErrorDatabaseError、SQL Server誤差構造。
再試行ロジック 過渡的な誤差を検出し、指数的なバックオフで再試行します。

SQL Serverのデータ型と機能

[アーティクル] 説明
データ型のマッピング SQL ServerからPythonへのテーブルと変換ルール。
デートタイムハンドリング datetimedatetime2datetimeoffset、そしてタイムゾーンの考慮事項。
十進法と貨幣の種類 正確な数値タイプと decimal.Decimal 精度。
文字列およびUnicodeデータ varcharnvarchar、コレーション、コードページ。
NULL処理 三値論理、センチネル、パンダの相互運用性。
バイナリ データ varbinaryimage、および大きなオブジェクトのストリーミング。
カスタムタイプコンバーター カスタムタイプ用のレジスタ入出力コンバータ。
一括コピー作業 一括コピー API による高スループットの挿入。
JSONデータ FOR JSONOPENJSONを使用して、JSONの保存、クエリの実行、分解を行えます。
XMLデータ xmlデータ型、XPath、XQueryを扱いましょう。
空間データ geometrygeography の Python の型。
スパース列 広いテーブルにはスパースカラムとカラムセットを使います。
スキーマ検出 データベース、テーブル、カラム、インデックスを点検してください。

Pythonツールやフレームワークとの統合

[アーティクル] 説明
Apache Arrow との統合 ゼロコピー分析のためにArrowテーブルで結果を取得しましょう。
パンダス統合 クエリ結果をDataFrameに読み込み、書き戻します。
極子積分 列形式のワークロードにはPolarsをmssql-pythonと組み合わせて使います。
DuckDB統合 ローカルのDuckDBテーブルと並べてSQL Serverデータをクエリします。
FastAPI統合 mssql-pythonをFastAPIサービスに接続します。
Flask 連携 Flaskアプリケーションではmssql-pythonを使いましょう。
非同期パターン mssql-pythonと asyncio およびスレッドプールを組み合わせましょう。
データアクセスと分析パターン SQLデータに対するカーソルアクセス、Arrow抽出、pandas、Polars、DuckDBでの分析向けに、最適な読み取りパスを選択してください。
データのロードと移動パターン 行挿入、一括コピー、 MERGE アップサート、DataFrameの読み込み、CSV取り込みのために適切な書き込みパスを選択してください。

デプロイと運用

[アーティクル] 説明
コンテナーとローカル開発 SQLに接続するPythonアプリケーション用にDockerコンテナ、devcontainer、CIパイプラインを設定しましょう。
パフォーマンスチューニング プールの調整、準備された声明、バッチサイズ、そして一括コピー。
Troubleshooting よくあるエラー、ログ、証明書の診断。
モジュール構成 モジュールレベルの設定、ログフック、機能フラグなどがあります。

mssql-pythonに移行する

[アーティクル] 説明
pyodbcからの移行 pyodbcのAPIや接続文字列をmssql-pythonにマッピングします。
pymssqlからの移行 pymssqlをmssql-pythonに置き換えつつ、動作は保持してください。
SQLiteからの移行 ローカルのSQLiteワークロードをSQL ServerまたはAzure SQLに移してください。
PostgreSQL からの移行 Python開発者がPostgreSQLからSQL Serverに移行するためのワンストップガイド、mssql-python。

Reference

[アーティクル] 説明
サポート ライフサイクル PythonおよびSQL Serverのバージョンをサポートし、更新のタイミングも改善しました。
新着情報 バージョン履歴とリリースのハイライト。