Microsoft PHP for SQL Server 驅動程式是 PHP 擴充功能,你可以用來從 PHP 腳本讀寫 Microsoft SQL 資料庫引擎 中的資料。 這兩個擴充功能使用相同的 Microsoft ODBC 驅動程式 for SQL Server,但它們提供不同的 PHP API 及驅動程式專屬選項:
-
SQLSRV 會暴露一個針對 SQL Server 功能量身打造的程序式 API(
sqlsrv_*函式)。 - PDO_SQLSRV 實作了 PHP 資料物件(PDO) 介面。 你可以保留 PDO 呼叫在現有資料庫程式碼中,但在切換資料庫前先檢視查詢和驅動程式的專屬設定。
兩個驅動程式都可連接 Azure SQL Database、Microsoft Fabric 中的 SQL 資料庫、Azure SQL 受控執行個體,以及所有支援的 SQL Server 版本和版本類型,包括 Express 版本。 兩個驅動程式都接受 PHP 串流作為輸入參數。 SQLSRV 支援以串流形式取得大型二進位與字元值。 不要以為 PDO_SQLSRV 有與其他項目相同的輸出串流行為。
選擇你的起點
- 要驗證你的安裝並使用 SQLSRV 或 PDO_SQLSRV 執行參數化查詢,請先使用 Quickstart: Connect 並用 PHP 的 Microsoft 驅動程式查詢。
- 要在 Linux 或 macOS 上安裝驅動程式,請先從 Linux 和 macOS 的安裝教學開始,並下載 Microsoft PHP for SQL Server 的驅動程式。
- 若要使用無密碼驗證連線到 Azure SQL,請先參閱 使用 Microsoft Entra 驗證進行連線 和 連線選項。
- 要讓現有應用程式對短暫故障具備韌性,請前往 Idle 連線韌性。
- 要在 SQLSRV 和 PDO_SQLSRV 之間做決定,請參考 PHP Microsoft 驅動程式概覽,SQL Server 和執行函式比較。
- 要診斷安裝、連線或查詢問題,請前往 「故障排除」、「 處理錯誤與警告」以及 「日誌活動」。
- 要讓現有應用程式更快,請前往 效能調整。
Azure SQL 的生產環境基準
這個 PDO_SQLSRV 範例會從環境變數讀取伺服器和資料庫,並使用受控識別進行連線。 它建立資料來源名稱(DSN),並啟用傳輸層安全性(TLS)與憑證驗證。 請從受信任的應用程式設定讀取這些值,而非從網頁請求參數讀取。 在授與該身分對資料庫的存取權後,在擁有受管理身分端點的主機上執行該程式。
當出現列出的錯誤時,輔助函式最多嘗試三次連線或執行唯讀查詢。 他們在嘗試之間等待的時間變長,這是一種稱為 指數退縮的重試模式。 若查詢錯誤需要新連線,查詢助手會拋出異常,讓呼叫程式碼處理。
使用支援的 PHP 版本、PDO_SQLSRV 擴充功能,以及適用於 SQL Server 的 Microsoft ODBC Driver 18。 關於支援的認證值,請參見使用 Microsoft Entra 認證連接。 在未設計專屬的重試策略前,不要重複使用查詢助手來寫入或多語句交易:錯誤不一定能告訴你寫入是否已提交。
<?php
declare(strict_types=1);
// Transient errors that require a fresh connection to recover. SQLSTATE values
// starting with '08' cover ODBC connection-established and connection-broken
// states (for example, 08001, 08S01).
const CONNECT_RETRY_SQLSTATE_PREFIX = '08';
// SQL Server error codes that are transient regardless of when they surface:
// 1205 (deadlock victim), 1222 (lock request timeout), and the Azure SQL
// throttling, mid-query failover, and "database not currently available"
// codes that arrive with SQLSTATE HY000.
const TRANSIENT_SERVER_ERROR_CODES = [1205, 1222, 40501, 40613, 40197, 10928, 10929, 49918];
// This read helper retries only the listed errors on the same connection.
// Other errors propagate; the caller must decide whether to reconnect.
const RETRYABLE_READ_ERROR_CODES = [1205, 1222, 40501, 10928, 10929];
/**
* Open a connection, retrying transient failures with exponential backoff.
*/
function connectWithRetry(string $dsn, array $options, int $maxAttempts = 3): PDO
{
for ($attempt = 1; $attempt <= $maxAttempts; $attempt++) {
try {
$pdo = new PDO($dsn, null, null, $options);
error_log(sprintf('connected on attempt %d/%d', $attempt, $maxAttempts));
return $pdo;
} catch (PDOException $e) {
$sqlstate = (string) $e->getCode();
$driverCode = isset($e->errorInfo[1]) ? (int) $e->errorInfo[1] : 0;
$isTransient = str_starts_with($sqlstate, CONNECT_RETRY_SQLSTATE_PREFIX)
|| in_array($driverCode, TRANSIENT_SERVER_ERROR_CODES, true);
if (!$isTransient || $attempt === $maxAttempts) {
error_log(sprintf('connect failed on attempt %d/%d: %s', $attempt, $maxAttempts, $e->getMessage()));
throw $e;
}
$delay = 2 ** ($attempt - 1);
error_log(sprintf('connect attempt %d hit transient %s/%d; retrying in %d seconds', $attempt, $sqlstate, $driverCode, $delay));
sleep($delay);
}
}
throw new RuntimeException('connectWithRetry exhausted retries');
}
/**
* Retry the standalone read-only query for errors that allow connection reuse.
*/
function queryWithRetry(PDO $pdo, string $sql, array $params = [], int $maxAttempts = 3): PDOStatement
{
for ($attempt = 1; $attempt <= $maxAttempts; $attempt++) {
try {
$stmt = $pdo->prepare($sql);
$stmt->execute($params);
return $stmt;
} catch (PDOException $e) {
$driverCode = isset($e->errorInfo[1]) ? (int) $e->errorInfo[1] : 0;
$isTransient = in_array($driverCode, RETRYABLE_READ_ERROR_CODES, true);
if (!$isTransient || $attempt === $maxAttempts) {
error_log(sprintf('query failed on attempt %d/%d: %s', $attempt, $maxAttempts, $e->getMessage()));
throw $e;
}
$delay = 2 ** ($attempt - 1);
error_log(sprintf('query attempt %d hit transient code %d; retrying in %d seconds', $attempt, $driverCode, $delay));
sleep($delay);
}
}
throw new RuntimeException('queryWithRetry exhausted retries');
}
// Load endpoint details from application configuration. In Azure App Service,
// these can come from app settings or Key Vault-backed settings.
$server = getenv('SQL_SERVER') ?: null;
$database = getenv('SQL_DATABASE') ?: null;
if ($server === null || $database === null) {
throw new RuntimeException('Set SQL_SERVER and SQL_DATABASE in your application configuration.');
}
$databaseValue = '{' . str_replace('}', '}}', $database) . '}';
$dsn = sprintf(
'sqlsrv:Driver={ODBC Driver 18 for SQL Server};Server=%s;Database=%s;'
. 'Encrypt=true;TrustServerCertificate=false;'
. 'LoginTimeout=90;Authentication=ActiveDirectoryMsi;'
. 'ConnectRetryCount=5;ConnectRetryInterval=15;'
. 'MultiSubnetFailover=true;',
$server,
$databaseValue
);
$options = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false,
PDO::SQLSRV_ATTR_QUERY_TIMEOUT => 30,
];
$pdo = connectWithRetry($dsn, $options);
$stmt = queryWithRetry($pdo, 'SELECT name FROM sys.databases WHERE database_id > ? ORDER BY name', [1]);
foreach ($stmt as $row) {
echo $row['name'], PHP_EOL;
}
請將這些設定用於 Azure SQL Database 故障轉移群組和 Azure SQL 受控執行個體。
Driver={ODBC Driver 18 for SQL Server}明確選擇 ODBC 驅動程式 18,而非依賴驅動程式發現。 在執行範例前先安裝它。設定
SQL_DATABASE為資料庫的實際名稱。 該程式將閉合大括號加倍,並在放入 DSN 前將名字包覆在大括號中。 跳脫可以避免名稱中的特殊字元改變驅動程式讀取連線設定的方式。ConnectRetryCount以及ConnectRetryInterval控制 ODBC 閒置連線彈性。 該語句的查詢逾時會界定執行期間的復原範圍。 由於範例中的查詢逾時為 30 秒,ODBC 可能會在用盡所有五次重新連線嘗試前停止。LoginTimeout=90控制的是連線建立,而不是那個恢復預算。 應用程式層級的輔助工具在發生特定伺服器錯誤時會重試;它不會重試查詢逾時或重播部分擷取的結果。啟用驅動程式記錄以及程式的
error_log()呼叫。 對於 PDO_SQLSRV,可以在php.ini中設定pdo_sqlsrv.log_severity,或在執行階段搭配ini_set()。 對於 SQLSRV,請設定LogSeverity和LogSubsystems。sqlsrv_configure()欲了解更多資訊,請參閱 日誌活動。; php.ini - enable PDO_SQLSRV driver diagnostics alongside the application-level ; error_log() calls in the sample. Use 1 (errors) in production; -1 (all) is ; useful during triage but very chatty. [pdo_sqlsrv] pdo_sqlsrv.log_severity = 1對於 使用者指派 的受控識別,請將該識別的 ID 作為 PDO 的
$username引數傳遞(new PDO($dsn, $identityId, null, $options))。 在 Azure App 服務 或 Azure Container Instance 上使用該身分的 client ID;否則,使用其 object ID。 PHP 驅動程式會繼承底層 Microsoft ODBC Driver for SQL Server 的此行為;如需詳細資訊,請參閱 使用 Microsoft Entra ID 搭配 ODBC Driver。 使用 PDO 建構子的使用者名稱參數,而非將認證資訊嵌入 DSN。 假扮null使用者(如範例所示)選擇系統指派的 Azure 主機管理身份。 對於 SQLSRV(程序式),請在連線選項陣列中傳遞UID。當您連線到容錯移轉群組接聽程式、可用性群組接聽程式或容錯移轉叢集執行個體端點時,請設定
MultiSubnetFailover=true。 設定此值可提升單子網及多子網可用性群組監聽者的連線效能。 欲了解更多資訊,請參閱 高可用性支援與災難復原。若要使用讀取向外延展或可讀取的次要複本,請將
ApplicationIntent=ReadOnly新增至 DSN。使用你 SQL 服務提供的端點,包括其雲端專用網域。 調查憑證名稱不符的問題,而非停用憑證驗證。 只有在你知道該端點預期憑證名稱時才使用
HostNameInCertificate。ODBC 為管理身份及服務主體認證取得憑證。 有了
AccessToken,你的應用程式會取得該代幣並傳給驅動程式;ODBC 不會幫你取得。 如需詳細資訊,請參閱搭配使用 Microsoft Entra ID 與 ODBC 驅動程式。連線資訊要放在你的程式碼之外。 把它存進你應用程式的設定系統,並用 Azure Key Vault 來管理秘密。
使用 SQLSRV,請在傳遞給
sqlsrv_connect()的陣列中設定連線選項。 在決定是否重試前,請檢查退換false品並檢查sqlsrv_errors()。 使用QueryTimeout分別設定語句的逾時。 閒置連線彈性 展示的是 ODBC 重新連線,而非應用程式層級的重試迴圈。重試輔助程式會讀取由
isset()保護的$e->errorInfo[1]。PDOException::$errorInfo宣告為?array,且預設為null,因此防禦性檢查會回退使用0作為驅動程式代碼,並由 SQLSTATE08前綴決定是否重試。
關於此配置各部分的更多資訊,請參見:
如需 Azure SQL 暫態錯誤清單,請參閱 「Troubleshoot transient connection errors」。
重點功能
- 兩個 PHP API:SQLSRV 提供程序式函式。 PDO_SQLSRV 實作 PDO。 安裝其中一個擴充功能或兩個都安裝。
- 廣泛支援平台:可在 Windows、Linux 及 macOS 上運行,並支援 PHP 版本。
-
加密連線:透過
Encrypt=true的 TLS 加密連線,伺服器憑證驗證由TrustServerCertificate控制。 -
Microsoft Entra ID 認證:受控識別、服務主體,以及透過底層 Microsoft ODBC Driver for SQL Server 取得的存取權杖。 受控識別是無密碼的;
ActiveDirectoryServicePrincipal使用用戶端密碼。 - Always Encrypted:在用戶端加密敏感欄位,並以安全隔區支援對加密資料執行支援的作業。
-
連線韌性:內建使用
ConnectRetryCount和ConnectRetryInterval的閒置連線重試機制。 - PHP 串流:透過任一 API 從串流參數傳送大型二進位與字元值。 使用 SQLSRV 進行串流檢索。
-
豐富的 SQL Server 資料型別支援:datetimeoffset、table-valued parameters、nvarchar 以及帶有
PDO::SQLSRV_ENCODING_UTF8的 Unicode。
開始
| 文章 | Description |
|---|---|
| 系統需求 | 支援 PHP、作業系統及 SQL Server 版本。 |
| 支援矩陣 | PHP 驅動程式版本的詳細相容性矩陣。 |
| 下載 Microsoft PHP for SQL Server 驅動程式 | 下載連結並發布相關資料。 |
| Linux 與 macOS 安裝教學 | 在 Linux 和 macOS 上安裝驅動程式及其 ODBC 前置條件。 |
| 載入驅動程式 | 在 php.ini 中啟用擴充功能。 |
| 快速入門:連接並查詢 Microsoft PHP 驅動程式 | 驗證擴充功能,設定連線,並用 SQLSRV 或 PDO_SQLSRV 執行相同的參數化查詢。 |
| PHP SQL 驅動程式概述 | 套件裡有什麼?什麼時候該選擇 SQLSRV 或 PDO_SQLSRV。 |
設定和連線
| 文章 | Description |
|---|---|
| 連接伺服器 | 從 PHP 開啟一個連接到 SQL Server 實例的連線。 |
| 連線選項 | 完整參考資料,包含連線關鍵字、預設值及其設定方法。 |
| 連線到 Microsoft Azure SQL Database | 將 PHP 應用程式連接到 Azure SQL Database。 |
| 連接指定的埠口 | 鎖定非預設的 TCP 埠。 |
| 連接共用 | 在 PHP 請求間重複使用 ODBC 連線。 |
| 停用多個主動結果集(MARS) | 關閉 MARS 以達成相容性。 |
| LocalDB 的支援 | 連接到 SQL Server 的 LocalDB 實例。 |
| 高可用性支援與災難復原 | 可用性群組監聽器與多子網故障轉移。 |
| 閒置連線韌性 | 空閒連線斷裂時自動重新連接。 |
Authenticate
| 文章 | Description |
|---|---|
| 使用 Microsoft Entra 驗證進行連線 | 管理身份、服務主體、存取權杖和密碼流程。 |
| 使用 SQL Server 認證連接 | 使用包含使用者名稱和密碼的 SQL 登入。 |
| 使用 Windows 驗證連線 | 在 Windows 使用整合驗證,或在 Linux 和 macOS 使用 Kerberos。 |
Secure
| 文章 | Description |
|---|---|
| 安全性考量 | PHP 應用的威脅模型與防禦深度指引。 |
| 一直用 PHP 驅動程式加密 | 為敏感欄位設定客戶端加密。 |
| Always Encrypted 具有安全記憶體保護區 | 啟用加密欄位的豐富操作,並具備安全區塊。 |
資料擷取與更新
| 文章 | Description |
|---|---|
| 程式指南 | 找出這兩個驅動程式的程式設計任務。 |
| 執行函數比較 | 選擇適合你工作負載的執行函式。 |
| 直接執行與預備語句執行(PDO_SQLSRV) | 何時使用直接執行,何時使用預先陳述。 |
| 資料擷取 | 取得列、欄和串流值。 |
| 更新資料 | 插入、更新和刪除資料列。 |
| 執行參數化查詢 | 綁定參數以防範 SQL 注入。 |
| 以串流方式傳送資料 | 將大型二進位和字元值串流到 SQL Server。 |
| 執行交易 | 將一組語句一併提交或回滾。 |
| 使用表格值參數 | 將 TABLE 參數傳遞給預存程序。 |
| 指定游標類型並選擇列 | 選擇僅前進、靜態、動態或鍵集游標。 |
數據類型
| 文章 | Description |
|---|---|
| 資料型態轉換 | 驅動程式如何將 PHP 型別映射到 SQL Server 型別。 |
| 預設 SQL Server 資料型態 | 每個 PHP 值的預設 SQL Server 類型。 |
| 預設 PHP 資料型態 | 每個 SQL Server 欄位類型的預設 PHP 類型。 |
| 指定 SQL Server 資料型別(SQLSRV) | 綁定參數時覆寫 SQL Server 類型。 |
| 指定 PHP 資料型別 | 擷取時要覆蓋 PHP 類型。 |
| 傳送與取回 UTF-8 資料 | 設定 SQLSRV 的 CharacterSet 選項,或 PDO_SQLSRV 的 PDO::SQLSRV_ATTR_ENCODING 屬性。 |
| 在 Linux 和 macOS 上傳送與取回 ASCII 資料 | 在非 Windows 主機上處理 ASCII 的來回轉換。 |
| 格式化小數與貨幣(SQLSRV) | 使用 SQLSRV 驅動程式格式化 十進位 和 金錢 欄位。 |
| 格式化小數和貨幣(PDO_SQLSRV) | 使用 PDO_SQLSRV 驅動程式格式化 decimal 和 money 欄位。 |
| 非系統區域設定 | 局部十進位分隔符及其他地區考量。 |
錯誤和診斷
| 文章 | Description |
|---|---|
| 處理錯誤與警告 | 兩個驅動程式都有錯誤與警告處理。 |
| 配置錯誤與警告處理(SQLSRV) | 調整 SQLSRV 驅動程式如何回報錯誤與警告。 |
| 處理錯誤與警告(SQLSRV) | 檢查 SQLSRV 函式所回傳的錯誤。 |
| 記錄活動 | 啟用驅動程式日誌以進行診斷擷取。 |
部署和操作
| 文章 | Description |
|---|---|
| 性能調校 | 連線管理、批次處理、預備語句、游標、記憶體,以及伺服器端監控。 |
| Troubleshooting | 診斷常見的安裝、連線、查詢、資料型別、交易及容器問題。 |
參考內容
| 文章 | Description |
|---|---|
| SQLSRV 驅動程式 API 參考 | 所有 sqlsrv_* 函式、參數與回傳值。 |
| PDO_SQLSRV 驅動程式參考 | PDO_SQLSRV 驅動程式所支援的 PDO 和 PDOStatement 方法。 |
| 常數 | 驅動程式會暴露的常數,包括型別與編碼常數。 |
相關工作
| 文章 | Description |
|---|---|
| 發行說明 | 各版本歷史,包含新功能、錯誤修正、平台支援變更及下載連結。 |
| 關於文件中的程式碼範例 | 本節範例程式碼所使用的慣例。 |
| PHP SQL 驅動程式的範例 | SQLSRV 與 PDO_SQLSRV 的端到端範例應用程式。 |
| 支援資源 | 社群與支援管道。 |
提出功能要求
若要要求新增功能,請在 Microsoft Drivers for PHP for SQL Server GitHub 存放庫中提出 issue。