背景:mssql 擴展已廢棄
PHP 5.3 起移除了舊的 mssql 擴展(基於 FreeTDS),官方推薦使用 Microsoft 提供的 sqlsrv / pdo_sqlsrv 驅動,支持 Windows / Linux,功能完整、性能更優。
驅動下載與安裝 (Windows)
- 訪問 Microsoft Drivers for PHP for SQL Server 下載頁面。
- 選擇匹配 PHP 版本 (VC 編譯版本、TS/NTS)、架構 (x86/x64) 的包。例如:
php_sqlsrv_74_ts_x64.dll。
- 將
php_sqlsrv_*.dll 和 php_pdo_sqlsrv_*.dll 放入 ext/ 目錄。
- 編輯
php.ini 啟用:
extension=php_sqlsrv_74_ts_x64.dll
extension=php_pdo_sqlsrv_74_ts_x64.dll
- 重啟 Web 服務器,
php -m | grep sqlsrv 驗證。
Linux 安裝 (Ubuntu 示例)
# 1. 添加 Microsoft 源
curl https://packages.microsoft.com/keys/microsoft.asc | apt-key add -
curl https://packages.microsoft.com/config/ubuntu/20.04/prod.list > /etc/apt/sources.list.d/mssql-release.list
# 2. 安裝驅動 (需 unixODBC)
apt-get update
ACCEPT_EULA=Y apt-get install msodbcsql17 unixodbc-dev
# 3. 安裝 PHP 擴展 (pecl)
pecl install sqlsrv pdo_sqlsrv
# 4. 啟用
echo "extension=sqlsrv.so" > /etc/php/7.4/mods-available/sqlsrv.ini
echo "extension=pdo_sqlsrv.so" >> /etc/php/7.4/mods-available/sqlsrv.ini
phpenmod sqlsrv
# 5. 重啟 php-fpm
systemctl restart php7.4-fpm
連接字符串 (DSN) 格式
| 場景 | DSN 示例 |
| 默認實例 (本機) | sqlsrv:Server=localhost;Database=TestDB |
| 命名實例 | sqlsrv:Server=localhost\SQLEXPRESS;Database=TestDB |
| 指定端口 | sqlsrv:Server=192.168.1.100,1433;Database=TestDB |
| Windows 認證 | sqlsrv:Server=localhost;Database=TestDB;Trusted_Connection=yes |
| SQL Server 認證 | sqlsrv:Server=localhost;Database=TestDB;UID=user;PWD=pass |
sqlsrv 過程式 API 基本用法
$serverName = 'localhost'; // 或 '127.0.0.1'
$connectionInfo = [
'Database' => 'TestDB',
'UID' => 'sa',
'PWD' => 'your_password',
'CharacterSet' => 'UTF-8', // 重要:避免中文亂碼
];
$conn = sqlsrv_connect($serverName, $connectionInfo);
if ($conn === false) {
die(print_r(sqlsrv_errors(), true));
}
echo "連接成功!\n";
// 查詢
$sql = "SELECT * FROM users WHERE status = ?";
$stmt = sqlsrv_query($conn, $sql, [1]);
if ($stmt === false) {
die(print_r(sqlsrv_errors(), true));
}
while ($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) {
print_r($row);
}
sqlsrv_free_stmt($stmt);
sqlsrv_close($conn);
PDO_SQLSRV 面向對象用法 (推薦)
$dsn = 'sqlsrv:Server=localhost;Database=TestDB';
$pdo = new PDO($dsn, 'sa', 'your_password', [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
]);
// 預處理防注入
$stmt = $pdo->prepare("SELECT * FROM users WHERE email = ?");
$stmt->execute(['user@example.com']);
$user = $stmt->fetch();
// 事務
try {
$pdo->beginTransaction();
$pdo->exec("INSERT INTO logs (msg) VALUES ('test')");
$pdo->commit();
} catch (Exception $e) {
$pdo->rollBack();
}
常見問題排查
| 錯誤現象 | 原因與解決 |
SQLSTATE[IMSSP]: This extension requires the Microsoft ODBC Driver | 未安裝 ODBC 驅動 (Windows: msodbcsql.msi; Linux: msodbcsql17) |
| 中文亂碼 / 存入變成 ??? | 連接字符串添加 CharacterSet=UTF-8 (sqlsrv) 或 DSN ;charset=UTF-8 (PDO) |
Login failed for user | 檢查 SQL Server 驗證模式 (混合模式)、用戶名密碼、防火牆 1433 端口 |
| 存儲過程 OUT 參數獲取失敗 | PDO 需用 bindParam(..., PDO::PARAM_INPUT_OUTPUT);sqlsrv 用 sqlsrv_query 配合 SQLSRV_PARAM_OUT |
存儲過程調用示例 (sqlsrv)
$proc = "{CALL get_user_info(?, ?, ?)}";
$params = [
[1, SQLSRV_PARAM_IN], // @id
['', SQLSRV_PARAM_OUT], // @name
['', SQLSRV_PARAM_OUT], // @email
];
$stmt = sqlsrv_query($conn, $proc, $params);
if ($stmt) {
// OUT 參數值已寫回 $params 數組對應位置
echo "Name: " . $params[1][0] . "\n";
echo "Email: " . $params[2][0] . "\n";
}
總結
- 必須使用 sqlsrv/pdo_sqlsrv:mssql 擴展已從 PHP 7 完全移除。
- ODBC 驅動是前置依賴:Windows/Linux 均需安裝對應版本。
- 字符集顯式指定 UTF-8:避免中文存取亂碼。
- 優先使用 PDO:代碼可移植、預處理更安全、異常模式更現代。
- 生產環境啟用連接池:
ConnectionPooling=1 (DSN 參數) 提升高併發性能。