首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHP 寫入中文到 SQL Server 2008+ 亂碼完整解決方案

     編輯:PHP 相關知識

問題根因

SQL Server 預設使用 UCS-2/UTF-16 儲存 Unicode (NCHAR/NVARCHAR),但舊版驅動或錯誤配置導致編碼轉換失敗,常見現象:

  • PHP 腳本 UTF-8 → 驅動未正確轉 UTF-16 → 寫入亂碼
  • 讀取時 UTF-16 → 未正確轉 UTF-8 → 顯示亂碼
  • 錯誤訊息:An error occurred translating the query string to UTF-16

驅動選擇關鍵

方案一:官方 sqlsrv/pdo_sqlsrv (推薦,零編碼煩惱)

安裝 (Windows)

  1. 下載 Microsoft Drivers for PHP for SQL Server 對應 PHP 版本 (x64/x86、TS/NTS)
  2. 將 php_sqlsrv_82_nts_x64.dll、php_pdo_sqlsrv_82_nts_x64.dll 放入 ext/
  3. 安裝 Microsoft ODBC Driver 17/18 for SQL Server (msodbcsql.msi)
  4. php.ini 啟用:extension=sqlsrv, extension=pdo_sqlsrv
  5. 重啟 php-fpm/Apache

連接代碼 (自動處理 UTF-8 ⇄ UTF-16)

<?php
$server = '127.0.0.1';
$database = 'TestDB';
$uid = 'sa'; $pwd = 'StrongPass';

/* PDO_SQLSRV */
$dsn = "sqlsrv:Server=$server;Database=$database;CharacterSet=UTF-8";
$pdo = new PDO($dsn, $uid, $pwd, [
    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
    PDO::ATTR_EMULATE_PREPARES => false,
]);

/* 直接寫入中文,無需 iconv */
$stmt = $pdo->prepare("INSERT INTO Opinion (content) VALUES (?)");
$stmt->execute(['測試中文內容']);  // 直接傳入 UTF-8 字符串

/* 讀取 */
$stmt = $pdo->query("SELECT content FROM Opinion");
while ($row = $stmt->fetch()) {
    echo $row['content']; // 自動為 UTF-8
}
?>

方案二:舊系統維護 - pdo_dblib (FreeTDS) 配置

freetds.conf

[global]
    tds version = 8.0          # 關鍵:TDS 8.0 支援 Unicode
    client charset = UTF-8     # 客戶端編碼
    text size = 2147483646     # 避免長文本截斷

PHP 連接

$dsn = "dblib:host=$server;dbname=$database;charset=utf8";
$pdo = new PDO($dsn, $uid, $pwd, [
    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
]);
// 同樣可直接傳入 UTF-8 字符串

方案三:避坑指南 (常見錯誤與修正)

驅動支援版本Unicode 支援建議
php_mssql.dllSQL Server 2000-2005差,已移除❌ 禁用
php_sqlsrv.dll / pdo_sqlsrv2005+ (官方)原生 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'中文')
欄位類型用 VARCHARVARCHAR 非 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 到 sqlsrv)

  1. 安裝 ODBC Driver 17+ + php_sqlsrv/pdo_sqlsrv
  2. 將 mssql_connect → PDO/PDO_SQLSRV 連接
  3. 將 mssql_query → prepare/execute 參數化
  4. 所有字符欄位 VARCHAR → NVARCHAR
  5. 移除所有 iconv、SET NAMES 等手動編碼代碼
  6. 測試中文、Emoji、特殊符號讀寫

核心原則:使用官方 sqlsrv/pdo_sqlsrv + NVARCHAR + 參數化查詢 + 連接字串 CharacterSet=UTF-8,完全消除中文亂碼問題。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved