預處理語句 是資料庫防注入、提升重複執行效率的核心機制。本文系統講解 MySQL 預處理的語法流程、占位符綁定變量、動態參數執行,並給出 PHP PDO 實戰代碼。
定義:將 SQL 模板預先發送給服務端進行解析、編譯、優化,生成执行計劃並緩存。後續執行時僅需傳遞參數值,跳過解析編譯階段。
核心優勢:
PREPARE stmt_name FROM 'SQL 语句';
示例:固定 SQL
PREPARE stmt_insert FROM 'INSERT INTO users(name, age) VALUES("Tom", 25)';

EXECUTE stmt_name;

使用 ? 作為佔位符,表示動態變化的數據位置。
PREPARE stmt_name FROM 'SQL 含 ? 佔位符'; SET @var = 值; EXECUTE stmt_name USING @var;
PREPARE stmt_find FROM 'SELECT * FROM users WHERE id = ?'; SET @uid = 100; EXECUTE stmt_find USING @uid;


PREPARE stmt_multi FROM 'INSERT INTO users(name, age, email) VALUES(?, ?, ?)'; SET @name = 'Jerry', @age = 30, @email = 'jerry@example.com'; EXECUTE stmt_multi USING @name, @age, @email;

DEALLOCATE PREPARE stmt_name;
錯誤寫法(拼接 SQL,極度危險):
$sql = "SELECT * FROM users WHERE name = '" . $_GET['name'] . "'";
正確寫法(PDO 預處理):
try {
$pdo = new PDO("mysql:host=localhost;dbname=test;charset=utf8mb4", "root", "password");
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$stmt = $pdo->prepare("SELECT * FROM users WHERE name = ? AND status = ?");
$stmt->execute([$_GET['name'], 1]); // 參數綁定,自動轉義
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
print_r($row);
}
} catch (PDOException $e) {
error_log($e->getMessage());
}

PDO::ATTR_EMULATE_PREPARES = false 強制使用服務端原生預處理。prepare()。DEALLOCATE PREPARE 或 PDO 對象銷毀釋放服務端資源。預處理是資料庫安全與性能的基石,務必在項目規範中強制要求使用。