サーバーへの接続

PHP ドライバーのダウンロード

このガイドを使って接続を開き、PHPが受け取る値を検証し、作業終了後に接続を解放してください。 プログラムはローカルまたはリモートのSQL Serverテストデータベースに対してSQL Server認証を使用します。 パスワードレスの Azure および Fabric 接続には、Azure SQL および Fabric SQL に接続をご利用ください。

SQLSRVはサーバー名と接続オプションの連想配列を受け入れます。 PDO_SQLSRV は PHP データオブジェクト(PDO)を実装し、データソース名(DSN)文字列、個別の認証情報引数、そして複数の PDO 属性を受け入れます。 両者ともMicrosoftのODBCドライバーfor SQL Serverを使用しています。 ある API で機能する接続設定があった場合でも、それによって別の API のオプション名や PHP の型が互換性を持つわけではありません。

接続する前に

  1. 対応するPHPランタイムとMicrosoft ODBCドライバーをインストールし、使用予定のPHP拡張を読み込みます。
  2. アプリケーションを実行するPHPプロセスを確認してください。 php --iniを実行してコマンドライン構成を確認し、php -mを実行してそのロードされた拡張機能をリストしてください。 SQLSRVは sqlsrvが必要です。 PDO_SQLSRV PDO と pdo_sqlsrvが必要です。 Web サーバーは、ターミナルとは異なる php.ini、実行環境、アカウントを使用する場合があります。
  3. サーバーアドレス、データベース名、接続許可付きのアイデンティティを取得してください。 データベースログインがすべてのテーブルに自動的に権限を与えるわけではありません。
  4. ネットワークアクセスと信頼できるサーバー証明書を設定しましょう。 これらのプログラムは暗号化と証明書の検証を明示的に要求します。 証明書に記載されているホスト名で接続し、証明書がカバーしていないIP アドレスに置き換えずにしてください。

これらの変数はPHPプロセスの環境で、シェル、開発ツール、ホスティング設定を使って設定してください。 パスワードファイルをコミットしたり、環境変数を出力したりしないでください。

Variable 価値
SQL_SERVER オプションで tcp: を前に付け、その後に ,<port> を続けたサーバー ホスト名。
SQL_DATABASE あなたのログインでアクセスできる既存のデータベースです。
SQL_USER SQL Server ログインです。
SQL_PASSWORD そのログインのパスワードは、保護された構成を通じて提供されます。

ウェブリクエストのパラメータではなく、信頼できるアプリケーション設定からサーバーやデータベースの設定を読み取ってください。 PDOの例では、それらの設定をDSNに配置しています。 その接続キーワードはアプリケーション管理下に置いてください。

実際のデータベース名、ユーザー名、パスワードを環境変数に保存し、自分で波かっこを追加したり二重にしたりせずにしてください。 両方のPHP拡張は、SQLSRV配列オプションやPDOコンストラクタ引数に対してもODBCスタイルのエスケープを必要とします。つまり、閉じ波括弧を二重にし、値を波括弧で囲むことです。 各プログラムはこれを一度だけ行ってから、これらの値をドライバーに渡します。 外側の括弧は、値の先頭と末尾の中括弧そのものを保持し、データベース名内のセミコロンが PDO DSN 設定を分離しないようにします。 このエスケープは、Transact-SQL(T-SQL)パラメータバインディングとは別です。

SQLSRVで開いて、クエリを実行し、閉じて

このプログラムを connect-sqlsrv.phpとして保存し、php connect-sqlsrv.phpを実行してください。 テーブルを作成したりデータを変更したりせずにT-SQLクエリを実行します。 CharacterSet 文字データとしてUTF-8を選択します。データベースの列の種類や照合順序は変更しません。

<?php
$config = [];
foreach (['SQL_SERVER', 'SQL_DATABASE', 'SQL_USER', 'SQL_PASSWORD'] as $name) {
    $value = getenv($name);
    if ($value === false || $value === '') {
        throw new RuntimeException("Set $name before running this example.");
    }
    $config[$name] = $value;
}
foreach (['SQL_DATABASE', 'SQL_USER', 'SQL_PASSWORD'] as $name) {
    $config[$name] = '{' . str_replace('}', '}}', $config[$name]) . '}';
}

$conn = sqlsrv_connect($config['SQL_SERVER'], [
    'Database' => $config['SQL_DATABASE'],
    'UID' => $config['SQL_USER'],
    'PWD' => $config['SQL_PASSWORD'],
    'Encrypt' => true,
    'TrustServerCertificate' => false,
    'LoginTimeout' => 30,
    'CharacterSet' => 'UTF-8',
]);
if ($conn === false) {
    throw new RuntimeException(print_r(sqlsrv_errors(), true));
}

$stmt = null;
try {
    $sql = "SELECT CAST(42 AS int) AS Value, N'caf' + NCHAR(233) AS Label, "
        . "CAST(NULL AS int) AS Missing";
    $stmt = sqlsrv_query($conn, $sql, [], ['QueryTimeout' => 30]);
    if ($stmt === false) {
        throw new RuntimeException(print_r(sqlsrv_errors(), true));
    }
    $row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC);
    if ($row === false) {
        throw new RuntimeException(print_r(sqlsrv_errors(), true));
    }
    if ($row !== ['Value' => 42, 'Label' => "caf\u{00e9}", 'Missing' => null]) {
        throw new RuntimeException('Unexpected SQLSRV values or PHP types.');
    }
    echo json_encode($row, JSON_THROW_ON_ERROR), PHP_EOL;
} finally {
    if (is_resource($stmt)) {
        sqlsrv_free_stmt($stmt);
    }
    sqlsrv_close($conn);
}

予想される出力:

{"Value":42,"Label":"caf\u00e9","Missing":null}

接続とステートメントはPHP リソースで、sqlsrv_* 関数に渡すハンドルです。 どちらのハンドルを使う前に、必ず false を確認してください。 失敗直後に sqlsrv_errors() を取得してください。なぜなら、後のSQLSRV呼び出しでエラーコレクションを置き換えることができるからです。

SQLSRV_FETCH_ASSOC 列名をキーとする連想配列を返します。 SQLSRV_FETCH_NUMERIC ゼロベースの数値キーを返します。デフォルトの SQLSRV_FETCH_BOTH は両方の形を含みます。 sqlsrv_fetch_array()の場合、nullはこれ以上行がないことを意味し、falseはエラーを意味します。 行内のSQL NULL はPHP nullで、行が欠けているわけではありません。 これらの値を区別する際には === を使用してください。

PDO_SQLSRVで開いて、クエリを実行して、閉じる

この別プログラムを connect-pdo.phpとして保存し、同じ環境で php connect-pdo.php 実行してください。 sqlsrv: は PHP の汎用的な PDO_ODBC ドライバではなく、PDO_SQLSRV を選択します。

<?php
$config = [];
foreach (['SQL_SERVER', 'SQL_DATABASE', 'SQL_USER', 'SQL_PASSWORD'] as $name) {
    $value = getenv($name);
    if ($value === false || $value === '') {
        throw new RuntimeException("Set $name before running this example.");
    }
    $config[$name] = $value;
}
foreach (['SQL_DATABASE', 'SQL_USER', 'SQL_PASSWORD'] as $name) {
    $config[$name] = '{' . str_replace('}', '}}', $config[$name]) . '}';
}
$server = $config['SQL_SERVER'];
$database = $config['SQL_DATABASE'];
$pdo = new PDO(
    "sqlsrv:Server=$server;Database=$database;Encrypt=true;"
    . "TrustServerCertificate=false;LoginTimeout=30",
    $config['SQL_USER'],
    $config['SQL_PASSWORD'],
    [
        PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
        PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
        PDO::SQLSRV_ATTR_ENCODING => PDO::SQLSRV_ENCODING_UTF8,
    ]
);

$stmt = null;
try {
    $sql = "SELECT CAST(42 AS int) AS Value, N'caf' + NCHAR(233) AS Label, "
        . "CAST(NULL AS int) AS Missing";
    $stmt = $pdo->prepare($sql, [PDO::SQLSRV_ATTR_QUERY_TIMEOUT => 30]);
    $stmt->execute();
    $row = $stmt->fetch();
    if ($row !== ['Value' => '42', 'Label' => "caf\u{00e9}", 'Missing' => null]) {
        throw new RuntimeException('Unexpected PDO_SQLSRV values or PHP types.');
    }
    echo json_encode($row, JSON_THROW_ON_ERROR), PHP_EOL;
} finally {
    $stmt = null;
    $pdo = null;
}

予想される出力:

{"Value":"42","Label":"caf\u00e9","Missing":null}

PDO_SQLSRVはこの int 列をデフォルトでPHP文字列として返します。 サポートされている数値列に対してPHPの数値型を要求するには、PDO::SQLSRV_ATTR_FETCHES_NUMERIC_TYPE を trueに設定してください。 decimal 値に対してPHPキャストを無差別に使わないでください。浮動小数点変換は精度を失う可能性があります。

PDO属性は接続または文オブジェクトの設定です。 PDO::ATTR_ERRMODE と PDO::ERRMODE_EXCEPTION を組み合わせると、データベース操作の失敗時に PDOException が発生します。 接続の構築は、その設定に関わらず失敗時に例外をスローします。 PDO::FETCH_ASSOC は名前付きキーを与え、 PDO::FETCH_NUM はゼロベースの数値キーを与え、 PDO::FETCH_BOTH は両方を与えます。 fetch() 結果の最後には false を返します。行内のSQLの NULL 値はPHP nullのままです。

これらのコマンドライン プログラムでは、エラーが発生すると実行が停止します。 ウェブアプリケーションでは、リクエストを処理するコードで例外をキャッチします。 保護ログに診断詳細を記録し、一般的なエラー応答を返します。 sqlsrv_errors()、例外トレース、接続文字列、トークンをブラウザに送信しないでください。

認証モードの選択

Mode 用途 参照先
SQL Server認証 Microsoft Entra ID が利用できない場合のオンプレミス SQL Server、コンテナ、Azure SQL SQL Server認証による接続
統合認証(接続設定にユーザー名やパスワードは設定しない) Windowsアイデンティティ、またはKerberos向けに設定されたLinux/macOSクライアント Windows 認証で接続
Microsoft Entra ID(AuthenticationまたはAccessTokenキーワード) Microsoft Entra ID 用に構成された Azure SQL と Fabric SQL のターゲット Microsoft Entra 認証を使用して接続する

SQL認証の場合、SQLSRVは接続オプション配列で UID と PWD を取ります。 PDO_SQLSRVは、ユーザー名とパスワードをDSNキーワードとしてではなく、new PDO() の第2引数と第3引数として受け取ります。 アクセストークンの場合、SQLSRVはoptions配列で AccessToken を受け取り、PDO_SQLSRVはDSNで取ります。

ユーザー名、パスワード、Authentication、AccessTokenを省くと、両方のドライバーはTrusted_Connection=Yesを使用してODBCに統合認証を要求します。 LinuxおよびmacOSでは、このリクエストには有効なKerberosチケットと ODBC統合認証設定が必要です。 任意のローカル アカウントにリモート サーバーへのアクセスを許可するわけではありません。

接続とそのステートメントを構成する

接続設定は開いたセッションに適用されます。 ステートメントの設定は特定のクエリに適用されます。 アプリケーションがデフォルト以外の値を必要とする場合、タイムアウトや結果型を明示的に設定してください。

Purpose SQLSRV PDO_SQLSRV 動作のオーナー
エンドポイントとデータベース サーバーの引数と Database オプション。 Server と Database DSN キーワード。 ODBCとSQLターゲット。
SQL 資格情報 UID と PWD のオプション。 コンストラクターのユーザー名とパスワードの引数。 拡張機能の資格情報の処理とサーバー認証。
Microsoft Entra 認証 Authentication オプション、または別 AccessToken オプション。 Authentication または AccessToken の DSN キーワード。外部トークンを使用する場合、資格情報は省略します。 ODBC認証;アプリケーションは外部トークンを取得します。
Encryption Encrypt => true。 DSN 内の Encrypt=true。 ODBC のトランスポート セキュリティ。
証明書の検証 TrustServerCertificate => false。 DSN 内の TrustServerCertificate=false。 ODBCおよびオペレーティングシステムの証明書信頼構成。
接続確立のタイムアウト LoginTimeout 接続オプション (秒単位)。 LoginTimeout DSN キーワード (秒単位)。 ODBC。 ステートメントの実行タイムアウトではありません。
クエリのタイムアウト QueryTimeout ステートメントのオプション (秒単位)。 PDO::SQLSRV_ATTR_QUERY_TIMEOUT (接続またはステートメント上)。 拡張およびODBCステートメント処理。
文字エンコード CharacterSet => 'UTF-8' 接続オプション。 PDO::SQLSRV_ATTR_ENCODING => PDO::SQLSRV_ENCODING_UTF8。 PHP拡張機能の変換。 PDO_SQLSRVの既定はUTF-8です。SQLSRVの既定はシステム エンコーディングです。
日付と時間オブジェクト ReturnDatesAsStrings はデフォルトで false されるため、日付と時刻の列は DateTime オブジェクトを返します。 既定では文字列です。オブジェクトを要求するには PDO::SQLSRV_ATTR_FETCHES_DATETIME_TYPE を使用します。 PHP拡張機能の型変換。
複数アクティブ結果セット (MARS) MultipleActiveResultSets 接続オプション。 MultipleActiveResultSets DSNキーワード。 ODBC とターゲットのサポート。 両方の拡張機能はデフォルトで有効化しています。Warehouse in Fabricでは無効にしてください。
アイドル状態からの回復 ConnectRetryCount と ConnectRetryInterval の接続オプション。 同じ DSN キーワードです。 ODBC。 任意のアプリケーション操作については、再試行を行いません。

キーワード、許容値、デフォルト情報の完全なリストについては、接続オプションをご覧ください。 PDOのDSNにCharacterSet、QueryTimeout、またはPDO::定数名を配置しないでください。

接続寿命の管理

リクエストやジョブがデータベース作業を必要とする場合は、接続を開いてください。 そのリクエストやジョブの間ずっと再利用し、完了したら解放してください。 行ごとに接続/切断を繰り返さないでください。 長期実行されるワーカーでは、次のジョブを受け入れる前に、リリース文を実行し、各トランザクションを完了させてください。

SQLSRVは接続を閉じると関連するステートメントを閉じます。 明示的にステートメントを早期に解放すると、接続を終了せずにリソースを解放します。 PDOの場合、 $pdo = null を割り当てるとその変数の参照だけが削除されます。 PDOStatement やその他の変数であっても、接続を維持することは可能です。 それらの参照も解放してください。 closeCursor() 保留中の結果を解放し、ステートメントを再利用できるようにします。これは接続クローズ方式ではありません。

両方のAPIはオートコミットモードで始まります。正常に実行されたステートメントは、トランザクションを開始しない限り、別のアプリケーションコミットなしでコミットされます。 一緒に成功するか一緒に失敗する必要がある書き込みのグループの場合は、sqlsrv_begin_transaction() または $pdo->beginTransaction()を使い、その後でコミットまたはロールバックを明示的に行います。 未処理のトランザクションで接続を閉じるのはロールバックを試みるのであって、コミットではありません。 トランザクション ポリシーの実装にシャットダウン クリーンアップだけ頼らないでください。 完全な例については トランザクションを実行する を参照してください。

PHPの接続ハンドルを解放しても、必ずしも物理的なネットワーク接続が閉じるわけではありません。 ODBCプーリングではそれを再利用のために保持できます。 プーリングはPHPリソースを無期限に保持する理由ではなく、PDO_SQLSRVも PDO::ATTR_PERSISTENT => trueをサポートしていません。 プラットフォーム固有のプーリング構成については 、接続プーリングを参照してください。

このガイドを SQL のターゲットに適用します

handle、fetch、cleanup の各パターンは、サポートされている SQL ターゲット上の両方の拡張機能に適用されます。 接続エンドポイント、認証、ネットワークアクセス、SQL の機能は様々です。

目標 適応
SQL Server これらのプログラムでは、SQL ログインを使用しています。 統合認証もPHPプロセスのアイデンティティを設定する際の選択肢の一つです。
Azure SQL Database 論理サーバーのホスト名と明示的なデータベースを使いましょう。 これらのプログラムでは、SQL 資格情報ではなく Microsoft Entra 認証を使用してください。
Azure SQL Managed Instance インスタンスエンドポイントとそのネットワークアクセス要件を活用してください。 プライベートエンドポイントがワークステーションからアクセス可能だとは思わないでください。
Azure Synapse Analytics SQLプールエンドポイントを使用し、オブジェクトを作成または修正するクエリを調整する前に T-SQL のサポートを確認してください。
Microsoft Fabric の SQL データベース データベース接続情報とMicrosoft Entra認証を活用しましょう。 SQL analytics エンドポイントを置き換えないでください。
Microsoft Fabric 内のウェアハウス ウェアハウスのエンドポイントとデータベース、Microsoft Entra 認証、MultipleActiveResultSets=false を使用します。

サービス固有の設定については、AzureおよびFabric接続を参照してください。

接続のトラブルシューティング

失敗したステップから始めましょう。 TCP(伝送制御プロトコル)のチェックが成功しても、認証や証明書の検証が成功したとは限りません。

症状: チェック
Call to undefined function sqlsrv_connect() 実行中のPHPプロセスはsqlsrvを読み込みませんでした。 php.iniと起動時の警告を確認してください。
PDO レポートcould not find driver そのプロセスに pdo_sqlsrv が読み込まれており、sqlsrv が PDO::getAvailableDrivers() に現れることを確認します。
ODBCドライバーが見つかりません Microsoft ODBCドライバーをインストールし、その登録状況とアーキテクチャを確認してください。 PHP拡張をインストールしてもODBCはインストールされません。
接続タイムアウトまたはサーバーが見つからない サーバー名、ポート、名前解決、ルーティング、ファイアウォールルール、そしてSQL ServerがTCPで待ち受けているかどうかを確認してください。
証明書チェーンやホスト名の検証が失敗する 正しい信頼チェーンをインストールし、証明書のホスト名を使いましょう。 TrustServerCertificate=trueを単なる本番環境向けの修正として扱わないでください。
ログインに失敗する、またはデータベースを開けない 認証モード、データベース名、ログイン/ユーザーマッピング、権限を確認してください。 認証情報を省略すると、統合認証が要求されます。SQL 認証が選択されるわけではありません。
ターミナルでは成功するが、ウェブリクエストは失敗する PHPランタイム、ロードされた拡張機能、プロセスID/実行ユーザー情報、環境変数、ネットワークアクセスを比較してください。 設定詳細を含む公開 phpinfo() ページを公開しないでください。
後続の操作は、ハンドルが閉じられていると失敗します すべてのステートメントの処理中は接続を維持してください。 接続を閉じた後に新しい接続を作成する;古いハンドルは自動的に再び開かない。

その他の接続に関する記事