| SQL | 類型 | 行為 | 效能 |
|---|---|---|---|
WHERE id = 1 | 數值 | 直接比較 | 最快 |
WHERE id = '1' | 字串 | 隱式轉換 CAST('1' AS UNSIGNED) | 略慢,可能導致索引失效 |
結論:**數值欄位用數值字面值**,避免隱式轉換。
直接拼接 SQL 會語法錯誤:
INSERT INTO t(name) VALUES ('O'Reilly'); -- 錯誤
| 函數 | 適用場景 | 缺點 | 建議 |
|---|---|---|---|
addslashes() | 單位元組字串 (Latin1) | 多位元組 (UTF-8/GBK) 可被 0xbf27 繞過 | **不建議**用於中文環境 |
mysql_real_escape_string() | 考慮連線字符集,PHP 4.3.0+ | 需已建立連線 | **舊專案首選** |
mysqli_real_escape_string() | mysqli 版本,同上 | 需連線物件 | **mysqli 專案首選** |
PDO::quote() | PDO 統一介面 | 較慢 | **現代專案首選** |
**根治 SQL 注入、免轉義、效能最佳**
$stmt = $pdo->prepare("INSERT INTO users(name, email) VALUES (?, ?)");
$stmt->execute(["O'Reilly", "o@example.com"]);
PHP ≤ 5.3 預設開啟,自動對 $_GET/POST/COOKIE 加斜線,**已移除於 PHP 5.4+**。舊碼遷移時務必檢查:
if (get_magic_quotes_gpc()) {
$_POST = array_map('stripslashes', $_POST);
$_GET = array_map('stripslashes', $_GET);
$_COOKIE = array_map('stripslashes', $_COOKIE);
}
mysql_escape_string():不考慮連線字符集,**已棄用**mysql_real_escape_string():依 mysql_set_charset() 字符集轉義,**必須在連線後呼叫**mysqli_real_escape_string($link, $str)mysql_real_escape_string($str) (需先 mysql_set_charset('utf8mb4'))addslashes()、手動 str_replace("'", "\\'")、拼接 SQL單引號處理的核心是**拒絕拼接 SQL**。參數化查詢同時解決轉義、注入、效能三大問題,是現代資料庫開發的鐵律。