SQL Server 預設使用 UCS-2/UTF-16 儲存 Unicode (NCHAR/NVARCHAR),但舊版驅動或錯誤配置導致編碼轉換失敗,常見現象:
An error occurred translating the query string to UTF-16| 驅動 | 支援版本 | Unicode 支援 | 建議 |
|---|---|---|---|
| php_mssql.dll | SQL Server 2000-2005 | 差,已移除 | ❌ 禁用 |
| php_sqlsrv.dll / pdo_sqlsrv | 2005+ (官方) | 原生 UTF-16 | ✅ 首選 |
| pdo_dblib (FreeTDS) | 2000+ | 需配置 tds version = 8.0 | 次選 |
| ODBC (php_odbc) | 所有 | 依賴 DSN 配置 | 兼容舊系統 |
| 錯誤做法 | 問題 | 正確做法 |
|---|---|---|
iconv('utf-8','GB2312',$str) | SQL Server 不用 GB2312,強制轉碼導致數據損壞 | 直接傳 UTF-8,驅動自動轉 UTF-16 |
sqlsrv_query($conn, "SET NAMES GB2312") | MySQL 語法,SQL Server 無此命令 | 連接字串加 CharacterSet=UTF-8 |
SQL 字符串未加引號 VALUES (中文) | 語法錯誤:Invalid column name '中文' | 參數化查詢 VALUES (?) 或 VALUES (N'中文') |
| 欄位類型用 VARCHAR | VARCHAR 非 Unicode,中文存 ? 或亂碼 | 必須用 NVARCHAR / NCHAR |
| 插入時加 N 前綴但參數化 | VALUES (N?) 無效,N 僅適用字面量 | 參數化無需 N,驅動自動處理 |
<?php
// test_chinese.php
require 'vendor/autoload.php'; // 或直接配置
$pdo = new PDO(
"sqlsrv:Server=127.0.0.1;Database=TestDB;CharacterSet=UTF-8",
'sa', 'Pass123',
[PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]
);
// 建表 (需 NVARCHAR)
$pdo->exec("CREATE TABLE #test_chinese (id INT IDENTITY, content NVARCHAR(MAX))");
// 寫入
$tests = [
'簡體中文',
'繁體中文:測試',
'Emoji 😀🎉',
'English + 中文混合',
'特殊符號:¥@#%&*()',
];
$stmt = $pdo->prepare("INSERT INTO #test_chinese (content) VALUES (?)");
foreach ($tests as $t) {
$stmt->execute([$t]);
echo "Inserted: $t\n";
}
// 讀取驗證
$stmt = $pdo->query("SELECT content FROM #test_chinese");
while ($row = $stmt->fetch()) {
$original = $row['content'];
// 這裡 $original 已是 UTF-8
echo "Read back: $original\n";
// 可對比原始數據
}
echo "測試完成,若無亂碼則配置正確。";
mssql_connect → PDO/PDO_SQLSRV 連接mssql_query → prepare/execute 參數化VARCHAR → NVARCHARiconv、SET NAMES 等手動編碼代碼核心原則:使用官方 sqlsrv/pdo_sqlsrv + NVARCHAR + 參數化查詢 + 連接字串 CharacterSet=UTF-8,完全消除中文亂碼問題。