MySQL 4.1 引入四層字符集體系:
PHP 腳本發送 SQL 時,若連接層仍為 latin1,中文會被錯誤編碼寫入,讀出時再按 latin1 解碼,產生亂碼。
SHOW VARIABLES LIKE 'character_set_%';
SHOW VARIABLES LIKE 'collation_%';
關鍵變量:
character_set_client:客戶端發送數據的編碼character_set_connection:連接層處理編碼character_set_results:結果集返回編碼-- 相當於執行以下三條
SET character_set_client = utf8;
SET character_set_results = utf8;
SET character_set_connection = utf8;
<?php
$mysqli = new mysqli('localhost', 'root', 'pass', 'db');
if ($mysqli->connect_errno) die('Connect Error: ' . $mysqli->connect_error);
// 關鍵:建立連接後立即設置
$mysqli->set_charset('utf8mb4'); // 推薦 utf8mb4 支援 Emoji
// 或 $mysqli->query("SET NAMES utf8mb4");
// PDO 方式
$pdo = new PDO('mysql:host=localhost;dbname=db;charset=utf8mb4', 'root', 'pass');
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
?>
-- 建庫指定
CREATE DATABASE mydb DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
-- 建表指定
CREATE TABLE t (c VARCHAR(100)) CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- 修改現有表(需轉換數據)
ALTER TABLE t CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
| 現象 | 原因 | 解決 |
|---|---|---|
| 存入正常,讀出亂碼 | character_set_results 錯誤 | SET NAMES / set_charset |
| 讀出正常,存入亂碼 | character_set_client 錯誤 | 同上 |
| 中文截斷/報錯 | 字段長度按字節計算,utf8mb4 佔 4 字節 | 擴大字段長度或用 TEXT |
| 排序不符合拼音 | 校對規則非中文 | COLLATE utf8mb4_unicode_ci |
utf8mb4 + utf8mb4_unicode_ci。SET NAMES utf8mb4(或 set_charset)。charset=utf8mb4 參數,最簡潔。