PDO::exec(长文讲解)
💡一则或许对你有用的小广告
欢迎加入小哈的星球 ,你将获得:专属的项目实战(已更新的所有项目都能学习) / 1v1 提问 / Java 学习路线 / 学习打卡 / 每月赠书 / 社群讨论
- 新开坑项目:《Spring AI 项目实战》 正在持续爆肝中,基于 Spring AI + Spring Boot 3.x + JDK 21..., 点击查看 ;
- 《从零手撸:仿小红书(微服务架构)》 已完结,基于
Spring Cloud Alibaba + Spring Boot 3.x + JDK 17...
,点击查看项目介绍 ;演示链接: http://116.62.199.48:7070 ;- 《从零手撸:前后端分离博客项目(全栈开发)》 2 期已完结,演示链接: http://116.62.199.48/ ;
截止目前, 星球 内专栏累计输出 90w+ 字,讲解图 3441+ 张,还在持续爆肝中.. 后续还会上新更多项目,目标是将 Java 领域典型的项目都整一波,如秒杀系统, 在线商城, IM 即时通讯,权限管理,Spring Cloud Alibaba 微服务等等,已有 3100+ 小伙伴加入学习 ,欢迎点击围观
在 PHP 数据库编程中,PDO::exec
是一个高效且实用的方法,尤其适用于执行不需要返回结果集的 SQL 操作。无论是创建数据库表、批量插入数据,还是更新和删除记录,PDO::exec
都能以简洁的方式完成任务。本文将从基础概念到实战案例,逐步解析 PDO::exec
的核心功能、使用技巧及常见问题,帮助开发者快速掌握这一工具。
一、什么是 PDO 和 PDO::exec?
1.1 PDO 简介
PHP Data Objects(PDO)是 PHP 内置的一个数据库抽象层,支持多种数据库(如 MySQL、PostgreSQL、SQLite 等)。它提供了一套统一的接口,使开发者无需为不同数据库编写重复代码。
1.2 PDO::exec 的定义
PDO::exec
是 PDO 对象的一个方法,用于执行 SQL 语句,主要适用于不返回结果集的操作,例如:
INSERT
(插入数据)UPDATE
(更新数据)DELETE
(删除数据)CREATE TABLE
(创建表)ALTER TABLE
(修改表结构)
与 PDO::query
不同,PDO::exec
不会返回查询结果,而是返回受影响的行数,或在发生错误时返回 false
。
1.3 形象比喻
可以将 PDO::exec
想象为一位快递员:
- 任务明确:你告诉他“把包裹送到某地址”(执行 SQL 指令)。
- 不带回执:快递员完成任务后,只会告诉你“包裹已送达”(返回受影响行数),而不会带回包裹内容。
二、PDO::exec 的基本语法与参数
2.1 方法语法
mixed PDO::exec ( string $statement )
-
参数:
$statement
:要执行的 SQL 语句,必须为字符串类型。
-
返回值:
- 成功时返回受影响的行数(如插入、更新、删除操作的行数)。
- 失败时返回
false
,并抛出PDOException
异常(需开启异常模式)。
2.2 使用步骤
- 建立数据库连接:使用
PDO
构造函数创建数据库连接对象。 - 执行 SQL 语句:通过
PDO::exec
方法传递 SQL 语句。 - 处理结果或错误:根据返回值判断操作是否成功。
三、实战案例:从基础到进阶
3.1 案例 1:创建数据库表
需求:创建一个名为 users
的表,包含 id
、name
和 email
字段。
// 1. 连接数据库
$dsn = 'mysql:host=localhost;dbname=test';
$username = 'root';
$password = '';
$options = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
];
try {
$pdo = new PDO($dsn, $username, $password, $options);
} catch (PDOException $e) {
die("连接失败: " . $e->getMessage());
}
// 2. 执行 SQL 创建表
$sql = "CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(50) NOT NULL,
email VARCHAR(100) UNIQUE
)";
// 3. 使用 exec 执行
$affectedRows = $pdo->exec($sql);
if ($affectedRows === false) {
echo "创建表失败!";
} else {
echo "表创建成功!";
}
3.2 案例 2:批量插入数据
需求:向 users
表中插入 3 条用户数据。
// SQL 语句(注意:INSERT 可以批量操作)
$insertSql = "INSERT INTO users (name, email) VALUES
('Alice', 'alice@example.com'),
('Bob', 'bob@example.com'),
('Charlie', 'charlie@example.com')";
// 执行并获取受影响行数
$affectedRows = $pdo->exec($insertSql);
echo "成功插入 $affectedRows 条记录。";
3.3 案例 3:更新与删除操作
需求:将用户 Alice
的邮箱改为 alice_new@example.com
,并删除 Charlie
的记录。
// 更新操作
$updateSql = "UPDATE users SET email = 'alice_new@example.com' WHERE name = 'Alice'";
$pdo->exec($updateSql);
// 删除操作
$deleteSql = "DELETE FROM users WHERE name = 'Charlie'";
$pdo->exec($deleteSql);
四、关键知识点详解
4.1 返回值的解读
- 成功时:返回受影响的行数。例如:
- 插入 3 条数据 → 返回
3
。 - 更新 1 条数据 → 返回
1
。
- 插入 3 条数据 → 返回
- 失败时:返回
false
,常见原因包括:- SQL 语法错误。
- 主键冲突或违反唯一约束(如重复的
email
)。
4.2 错误处理与调试
4.2.1 异常模式
通过设置 PDO::ATTR_ERRMODE
为 PDO::ERRMODE_EXCEPTION
,可在错误发生时自动抛出异常:
try {
$pdo->exec("INSERT INTO users (name) VALUES ('Dave')"); // 缺少 email 字段,会触发错误
} catch (PDOException $e) {
echo "错误: " . $e->getMessage();
}
4.2.2 非异常模式
若未开启异常模式,需手动检查返回值:
$result = $pdo->exec("INSERT INTO users (name) VALUES ('Dave')");
if ($result === false) {
// 获取错误信息
$errorInfo = $pdo->errorInfo();
echo "错误代码: " . $errorInfo[0];
echo "错误描述: " . $errorInfo[2];
}
4.3 PDO::exec 与 PDO::query 的区别
特性 | PDO::exec | PDO::query |
---|---|---|
返回值 | 受影响的行数或 false | 返回 PDOStatement 对象或 false |
适用场景 | 不返回结果集的操作(如 DML) | 返回结果集的操作(如 SELECT) |
占位符支持 | 不支持参数绑定 | 支持参数绑定(需配合 prepare ) |
比喻:
PDO::exec
是“执行官”,专注于完成任务,不关心结果内容。PDO::query
是“调查员”,会带回详细的结果报告。
五、进阶技巧与最佳实践
5.1 批量操作优化
通过将多个 SQL 语句合并为一条,减少网络交互次数,提升性能。例如:
// 原始写法(多次执行)
$pdo->exec("INSERT INTO users...");
$pdo->exec("INSERT INTO orders...");
// 优化后(单次执行)
$pdo->exec("INSERT INTO users...; INSERT INTO orders...");
5.2 避免 SQL 注入的注意事项
虽然 PDO::exec
不支持参数绑定(占位符),但在涉及动态数据时,必须使用 PDO::prepare
配合占位符。例如:
// 错误示例(易受 SQL 注入攻击)
$userInput = "Robert'; DROP TABLE users; --";
$pdo->exec("INSERT INTO users (name) VALUES ('$userInput')");
// 正确示例(使用 prepare)
$stmt = $pdo->prepare("INSERT INTO users (name) VALUES (?)");
$stmt->execute([$userInput]);
5.3 事务的结合使用
在需要保证操作原子性时,可结合事务使用 PDO::exec
:
// 开启事务
$pdo->beginTransaction();
try {
$pdo->exec("UPDATE accounts SET balance = balance - 100 WHERE user_id = 1");
$pdo->exec("UPDATE accounts SET balance = balance + 100 WHERE user_id = 2");
$pdo->commit(); // 提交事务
} catch (PDOException $e) {
$pdo->rollBack(); // 回滚事务
echo "转账失败!";
}
六、常见问题解答
Q1:为什么 PDO::exec
返回 false
?
可能原因包括:
- SQL 语法错误(如缺少引号、字段名错误)。
- 数据库权限不足。
- 违反约束(如唯一索引冲突)。
解决方法:检查错误信息(通过errorInfo()
或异常捕获)。
Q2:PDO::exec
能执行 SELECT
语句吗?
不能。SELECT
需使用 PDO::query
或 PDO::prepare
。
Q3:如何获取自增 ID(如插入后的 id
)?
插入操作后,使用 PDO::lastInsertId()
方法:
$pdo->exec("INSERT INTO users (name) VALUES ('Eve')");
$newId = $pdo->lastInsertId();
echo "新插入的 ID 是:$newId";
结论
PDO::exec
是 PHP 数据库操作中不可或缺的工具,尤其适合执行 DML(数据操作语言)语句。通过本文的案例和解析,开发者可以掌握其核心功能、错误处理技巧,以及与事务、参数化查询的结合应用。无论是基础的增删改操作,还是复杂的批量处理,PDO::exec
都能以简洁的方式提升开发效率。
在实际开发中,建议始终开启异常模式,并结合 PDO::prepare
防范 SQL 注入。随着对 PDO
框架的深入理解,开发者将能更灵活地应对各种数据库操作场景,写出健壮、高效的代码。