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, <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:
        # 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準拠:標準 connect、 cursor、 execute、 fetch* インターフェースに加え、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の可用性グループや読み取り専用レプリカに接続してください。

データの操作

[アーティクル] 説明
クエリの実行 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処理 三値論理、センチネル、パンダの相互運用性。
バイナリ データ varbinary、image、および大きなオブジェクトのストリーミング。
カスタムタイプコンバーター カスタムタイプ用のレジスタ入出力コンバータ。
一括コピー作業 一括コピー API による高スループットの挿入。
JSONデータ FOR JSONやOPENJSONを使用して、JSONの保存、クエリの実行、分解を行えます。
XMLデータ xmlデータ型、XPath、XQueryを扱いましょう。
空間データ geometry と geography の Python の型。
スパース列 広いテーブルにはスパース カラムとカラム セットを使います。
スキーマ検出 データベース、テーブル、カラム、インデックスを点検してください。

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

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

デプロイと運用

[アーティクル] 説明
コンテナーとローカル開発 SQLに接続するPythonアプリケーション用にDockerコンテナ、devcontainer、CIパイプラインを設定しましょう。
パフォーマンスチューニング プールの調整、Batch サイズ、準備済みのステートメント、一括コピー。
Troubleshooting 症状やエラーメッセージで指針を見つけましょう。
設置と接続のトラブルシューティング インストール、接続、コンテナ、CIの問題を解決します。
クエリ、データ、操作のトラブルシューティング クエリ、データ型、パフォーマンス、トランザクション、大量コピーの問題を解決します。
モジュール構成 モジュールレベルの設定、ログフック、機能フラグなどがあります。

mssql-pythonに移行する

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

機能をリクエストする

機能をリクエストするには、mssql-pythonのGitHubリポジトリでイシューを開いてください。