PHP 與 MySQL 交互的 5 大核心注意點,涵蓋語法終止符、數據類型誤區、通配符陷阱、NULL 處理、防注入鋼印。
// 錯誤:雙重分號導致解析異常
mysql_query("INSERT INTO t (a) VALUES ('1');");
// 正確:PHP 處理分號,驅動自動補全
mysql_query("INSERT INTO t (a) VALUES ('1')");
// 垂直顯示結果集時用 \G 替代分號 (僅命令行客戶端)
| 誤區 | 真相 |
|---|---|
| TEXT 是獨立類型 | 實為 LONG VARCHAR/MEDIUMTEXT 別名,用 VARCHAR(65535) 或 TEXT 族 |
| DATE 格式隨意 | 強制 YYYY-MM-DD,PHP 生成:date('Y-m-d') |
| DATE 可直接減法得天數 | MySQL 支持 DATEDIFF(d1,d2) / TIMESTAMPDIFF(DAY,d1,d2),不可直接相減 |
| SET/ENUM 區別模糊 | SET 多選 (位掩碼存儲,最多 64 值);ENUM 單選 (最多 65535 值);超 64 值集合需多列或關聯表 |
*:僅用於 SELECT 列列表 (SELECT *),不可用於 WHERE%:僅用於 LIKE/RLIKE 模式匹配,匹配任意長度字符 (含 0 字符)_:僅用於 LIKE/RLIKE,匹配任意單字符WHERE col LIKE '%abc%',不可單獨用 WHERE col = '%abc%'
-- 表定義
CREATE TABLE t (
city VARCHAR(50) NOT NULL DEFAULT '未知', -- 強制非空 + 默認值
age TINYINT NOT NULL DEFAULT 0
);
-- PHP 查詢構建 (安全模式)
$city = $_GET['city'] ?? '%'; // 未傳遞則全匹配
$sql = "SELECT * FROM users WHERE city LIKE ?";
$stmt = $mysqli->prepare($sql);
$stmt->bind_param('s', $city);
$stmt->execute();
核心原則:所有業務列定義 NOT NULL + 合理默認值,應用層統一用 % 代替空字符串通配,避免 NULL 與 '' 語義混淆導致 LIKE '%' 匹配不到 NULL 行。
// MySQLi PreparedStatement
$stmt = $mysqli->prepare("SELECT * FROM users WHERE email = ? AND status = ?");
$stmt->bind_param('si', $email, $status); // s=string, i=integer
$stmt->execute();
$result = $stmt->get_result();
while ($row = $result->fetch_assoc()) { ... }
// PDO (跨數據庫、更現代)
$pdo = new PDO("mysql:host=localhost;dbname=test;charset=utf8mb4", $user, $pass);
$stmt = $pdo->prepare("SELECT * FROM users WHERE email = :email");
$stmt->execute([':email' => $email]);
foreach ($stmt as $row) { ... }
禁用:mysql_* 系列函數 (PHP 7.0 移除)、字符串拼接 SQL、addslashes() 手動轉義。