PHP 與 MySQL 是經典黃金搭檔,但細節不慎極易踩坑。本文歸納 5 類高頻問題:分號處理、數據類型誤區、通配符用法、NULL 值陷阱、編碼亂碼,並給出現代最佳實踐(PDO/預處理/嚴格模式)。
// 錯誤示範:雙重分號導致解析錯誤
mysqli_query($conn, "INSERT INTO t (c) VALUES ('v');");
// 正確:PHP 端以分號結束,SQL 字串內不加分號
mysqli_query($conn, "INSERT INTO t (c) VALUES ('v')");
PHP 會自動為 SQL 語句補全終止符。
SELECT * FROM users WHERE id = 1\G
適用於命令行調試,程式碼中不可用。
| 誤區 | 正確認知 |
|---|---|
| TEXT 是獨立類型 | TEXT 實為 LONG VARCHAR / MEDIUMTEXT 別名 |
| DATE 格式任意 | 嚴格為 YYYY-MM-DD,PHP 用 date('Y-m-d') 生成 |
| DATE 可直接相減得天數 | MySQL 需用 DATEDIFF(),PHP 端用 strtotime 計算 |
| SET/ENUM 無上限 | SET 最多 64 個成員,ENUM 最多 65535 個;超限需拆多欄位 |
%:匹配任意長度字符,**必須搭配 LIKE** 使用。_:匹配**單個**字符,同樣需配合 LIKE。*:僅用於 SELECT * 選擇所有欄位,不屬於模糊匹配運算子。-- 正確:查找姓名含「張」的用戶
SELECT * FROM users WHERE name LIKE '%張%';
-- 錯誤:WHERE name = '%張%' -- 不會觸發模糊匹配
NULL。最佳實踐: 開啟 sql_mode=STRICT_TRANS_TABLES,NO_ZERO_DATE,NO_ZERO_IN_DATE,ERROR_FOR_DIVISION_BY_ZERO,強制嚴格檢查。
utf8mb4(支援 Emoji)。SET NAMES utf8mb4(PDO 可在 DSN 指定 charset=utf8mb4)。<meta charset="utf-8">。$pdo = new PDO('mysql:host=localhost;dbname=test;charset=utf8mb4', 'user', 'pass', [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false, // 真預處理
]);
$stmt = $pdo->prepare('INSERT INTO users (name, email) VALUES (?, ?)');
$stmt->execute([$name, $email]);
預處理徹底解決 SQL 注入、特殊字符轉義、分號干擾等歷史包袱。
掌握分號規則、數據類型本質、通配符語法、NULL 語義、編碼鏈路五大核心,並全面遷移至 PDO + 預處理 + 嚴格模式,即可避開 90% 的 PHP-MySQL 開發坑點,寫出安全、高效、可維護的代碼。