不,PDO::exec()≠prepare() + execute()。它们是 PDO 提供的两种不同的 SQL 执行方式,适用于不同场景,在安全性、功能、返回值和使用限制上均有本质区别。
一、核心区别概览
| 特性 | PDO::exec($sql) | PDO::prepare($sql) → execute($bindings) |
|---|---|---|
| 参数绑定 | ❌ 不支持 | ✅ 支持(防 SQL 注入) |
| 适用语句 | 无结果集的语句(如INSERT,UPDATE,DELETE,DDL) | 任何语句(包括SELECT) |
| 返回值 | 受影响的行数(int),失败返回false | execute()返回bool,结果需通过fetch()/fetchAll()获取 |
| SQL 注入风险 | ⚠️ 若拼接用户输入,极高风险 | ✅ 安全(只要正确使用绑定) |
| 预处理 | ❌ 不使用预处理 | ✅ 使用预处理(可复用语句) |
| 能否执行 SELECT | ❌ 不能(无结果集返回) | ✅ 可以 |
二、详细解析
1.PDO::exec():简单、危险、有限
- 用途:执行不返回结果集的 SQL 语句。
- 典型场景:
$pdo->exec("CREATE TABLE users (id INT, name VARCHAR(100))");$pdo->exec("DELETE FROM logs WHERE created_at < '2020-01-01'"); - 致命缺陷:
// ❌ 危险!直接拼接用户输入$table=$_GET['table'];$pdo->exec("DROP TABLE$table");// 可能 DROP 任意表!
💡
exec()本质是query()的简化版,但只返回行数,且不支持绑定。
2.prepare() + execute():安全、灵活、通用
- 用途:执行任何 SQL,尤其适合含动态值的查询。
- 工作流程:
$stmt=$pdo->prepare("DELETE FROM users WHERE email = ?");$stmt->execute(['john@example.com']);// 安全绑定echo$stmt->rowCount();// 获取影响行数 - 优势:
- SQL 模板与数据分离 →防注入
- 支持
SELECT→ 可获取结果集 - 预处理语句可复用 → 性能优化
三、能否用exec()替代prepare + execute?
| 场景 | 是否可行 | 说明 |
|---|---|---|
执行INSERT且值固定 | ✅ 可行 | 但无优势 |
执行INSERT且值来自用户 | ❌绝对不可 | 注入风险 |
执行SELECT | ❌ 不可行 | exec()不返回结果集 |
执行CREATE TABLE | ✅ 可行 | DDL 通常无动态值,可用exec() |
✅最佳实践:
只要涉及动态数据(尤其是用户输入),必须使用prepare() + execute()。exec()仅用于完全静态、无外部输入的 DDL 或管理语句。
四、Laravel 中的使用策略
Laravel几乎从不直接使用PDO::exec()来执行含绑定的查询:
- 所有 Query Builder / Eloquent 查询 →
prepare() + execute() - Schema 操作(如
Schema::create())→ 内部可能用exec(),但 SQL 由 Laravel 生成,无用户输入
例如:
// Laravel 内部(简化)publicfunctionstatement($query,$bindings=[]){if(empty($bindings)){return$this->getPdo()->exec($query);// ← 仅当无绑定时用 exec()}$statement=$this->getPdo()->prepare($query);return$statement->execute($bindings);// ← 有绑定时用 prepare+execute}五、总结
PDO::exec()是“一次性、无绑定、无结果”的快捷方式;prepare() + execute()是“安全、通用、可复用”的标准方式。
| 问题 | 答案 |
|---|---|
exec()能防 SQL 注入吗? | ❌ 不能(除非 SQL 完全静态) |
prepare + execute能做exec()的事吗? | ✅ 能,且更安全 |
| Laravel 用哪个? | 🛡️优先prepare + execute,仅在无绑定时可能用exec() |
因此,永远不要认为exec()等价于prepare + execute—— 它们是为不同目的设计的工具,安全性天差地别。