命名参数(:name)和问号参数(?)均防sql注入,但命名参数支持重复使用、可读性高、维护性强,且键名须带冒号;问号参数按位置绑定、不可复用、易出错,二者不可混用。

PHP PDO 中命名参数(:name)和问号参数(?)都能防止 SQL 注入,但用法、可读性、复用性和灵活性有明显差异。
参数写法与绑定方式不同
问号参数是**位置占位符**,按 SQL 语句中 ? 出现的顺序,依次绑定值;命名参数是**标识符占位符**,用冒号加名称(如 :user_id)表示,绑定时通过键名匹配。
- 问号参数示例:
$stmt = $pdo->prepare("SELECT * FROM users WHERE status = ? AND age > ?");<br>$stmt->execute(['active', 18]); - 命名参数示例:
$stmt = $pdo->prepare("SELECT * FROM users WHERE status = :status AND age > :min_age");<br>$stmt->execute([':status' => 'active', ':min_age' => 18]);
命名参数支持重复使用,问号参数不支持
同一个命名参数可在 SQL 中多次出现,只需绑定一次;问号参数每个位置独立,重复条件必须写多个 ? 并传对应多个值。
- 命名参数可复用:
$stmt = $pdo->prepare("SELECT * FROM users WHERE created_at > :date OR updated_at > :date");<br>$stmt->execute([':date' => '2024-01-01']); - 问号参数需重复传值:
$stmt = $pdo->prepare("SELECT * FROM users WHERE created_at > ? OR updated_at > ?");<br>$stmt->execute(['2024-01-01', '2024-01-01']);
可读性与维护性差异明显
SQL 中使用 :name 能直观看出每个占位符代表什么含义,尤其在复杂查询或字段多时更易理解;问号参数只靠顺序推断,容易出错,改参数顺序还需同步调整 execute() 的数组顺序。
立即学习“PHP免费学习笔记(深入)”;
- 命名参数让 SQL 更接近自然语言逻辑,比如
WHERE name LIKE :pattern AND category = :cat - 问号参数在长语句中容易数错位置,特别是中间插入新条件后,后续所有索引都可能偏移
注意:不能混用,且命名参数键名必须带冒号
PDO 明确禁止在同一 SQL 中同时使用 ? 和 :name;命名参数在 execute() 数组中,键名要包含冒号(如 ':id'),否则 PDO 找不到对应占位符。
- 错误写法:
$stmt->execute(['id' => 123]);→ 应为[':id' => 123] - 错误混用:
"WHERE id = ? AND name = :name"→ 会报错 - 命名参数也支持
bindParam(),此时键名不用带冒号,但变量需提前声明











