PHP 与 MySQL 详解实战入门(2)
前言
在 Web 开发中,PHP 与 MySQL 的组合一直是构建动态数据驱动应用的核心技术栈。从用户信息的存储到商品数据的展示,从内容的更新到过期记录的清理,几乎所有交互场景都离不开对数据库的操作。掌握 PHP 操作 MySQL 的核心技能,不仅是实现数据持久化的基础,更是构建高效、安全、可维护应用的关键。
本文系统梳理了 PHP 操作 MySQL 的核心流程与关键技术,从最基础的读取数据(SELECT),到通过WHERE子句筛选数据、LIMIT实现分页、ORDER BY排序结果,再到数据的更新(UPDATE)与删除(DELETE),完整覆盖了 CRUD(创建、读取、更新、删除)的核心场景。内容不仅包含过程式、面向对象(MySQLi)及 PDO 三种主流操作方式的对比,更强调了安全实践(如异常处理、参数绑定)和性能优化(如显式指定列名、事务控制),旨在帮助开发者从 “会用” 提升到 “用好”,规避常见的安全隐患与性能陷阱。无论你是刚接触 PHP 数据库开发的初学者,还是需要巩固基础的开发者,这些内容都将为你构建可靠的数据交互层提供清晰的指引。
(6)PHP MySQL 读取数据
1.从 MySQL 表读取数据的基本方法
MySQL 中通过SELECT
语句读取表数据,基本语法为:
-- 读取指定列
SELECT column1, column2 FROM table_name;
-- 读取所有列(不推荐,建议显式指定列名)
SELECT * FROM table_name;
结合 PHP,可通过数据库扩展的查询方法执行SELECT
语句,获取结果集后逐行处理。
假设的表数据
以下示例基于persons
表的现有数据(与前文插入的数据一致):
id | first_name | last_name | |
---|---|---|---|
1 | Peter | Parker | peterparker@mail.com |
2 | John | Rambo | johnrambo@mail.com |
3 | Clark | Kent | clarkkent@mail.com |
4 | John | Carter | johncarter@mail.com |
5 | Harry | Potter | harrypotter@mail.com |
2.读取数据示例
a. 过程式方式(MySQLi)
<?php
$host = 'localhost';
$user = 'db_admin'; // 专用账户,禁止root
$pass = 'SecurePass@2024'; // 强密码
$dbname = 'demo';
// 连接数据库
$link = mysqli_connect($host, $user, $pass, $dbname);
if (!$link) {
throw new mysqli_sql_exception("连接失败:" . mysqli_connect_error());
}
// 强制字符集(PHP 8+ 必须)
mysqli_set_charset($link, 'utf8mb4');
// 执行查询(推荐显式指定列名,替代SELECT *)
$sql = "SELECT id, first_name, last_name, email FROM persons";
$result = mysqli_query($link, $sql);
if (!$result) {
throw new mysqli_sql_exception("查询失败:" . mysqli_error($link));
}
// 处理结果集
if (mysqli_num_rows($result) > 0) {
echo "<table border='1'>";
echo "<tr><th>ID</th><th>名</th><th>姓</th><th>邮箱</th></tr>";
// 逐行读取数据
while ($row = mysqli_fetch_assoc($result)) { // 推荐使用assoc获取关联数组
echo "<tr>";
echo "<td>{$row['id']}</td>";
echo "<td>{$row['first_name']}</td>";
echo "<td>{$row['last_name']}</td>";
echo "<td>{$row['email']}</td>";
echo "</tr>";
}
echo "</table>";
} else {
echo "未找到匹配记录。";
}
// 释放结果集和连接
mysqli_free_result($result);
mysqli_close($link);
?>
b. 面向对象方式(MySQLi)
<?php
$host = 'localhost';
$user = 'db_admin';
$pass = 'SecurePass@2024';
$dbname = 'demo';
try {
// 连接数据库(PHP 8+ 连接失败自动抛异常)
$mysqli = new mysqli($host, $user, $pass, $dbname);
$mysqli->set_charset('utf8mb4');
// 执行查询
$sql = "SELECT id, first_name, last_name, email FROM persons";
$result = $mysqli->query($sql);
if (!$result) {
throw new mysqli_sql_exception("查询失败:" . $mysqli->error);
}
// 处理结果
if ($result->num_rows > 0) {
echo "<table border='1'>";
echo "<tr><th>ID</th><th>名</th><th>姓</th><th>邮箱</th></tr>";
while ($row = $result->fetch_assoc()) { // 关联数组更直观
echo "<tr>";
echo "<td>{$row['id']}</td>";
echo "<td>{$row['first_name']}</td>";
echo "<td>{$row['last_name']}</td>";
echo "<td>{$row['email']}</td>";
echo "</tr>";
}
echo "</table>";
} else {
echo "未找到匹配记录。";
}
// 释放资源(空安全运算符防未定义错误)
$result?->free();
$mysqli?->close();
} catch (mysqli_sql_exception $e) {
die("操作失败:" . $e->getMessage());
}
?>
c. PDO 方式
<?php
$host = 'localhost';
$user = 'db_admin';
$pass = 'SecurePass@2024';
$dbname = 'demo';
try {
// 连接数据库(指定字符集和异常模式)
$pdo = new PDO(
"mysql:host=$host;dbname=$dbname;charset=utf8mb4",
$user,
$pass,
[PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]
);
// 执行查询
$sql = "SELECT id, first_name, last_name, email FROM persons";
$result = $pdo->query($sql);
// 处理结果(PDO::FETCH_ASSOC获取关联数组)
if ($result->rowCount() > 0) {
echo "<table border='1'>";
echo "<tr><th>ID</th><th>名</th><th>姓</th><th>邮箱</th></tr>";
while ($row = $result->fetch(PDO::FETCH_ASSOC)) {
echo "<tr>";
echo "<td>{$row['id']}</td>";
echo "<td>{$row['first_name']}</td>";
echo "<td>{$row['last_name']}</td>";
echo "<td>{$row['email']}</td>";
echo "</tr>";
}
echo "</table>";
} else {
echo "未找到匹配记录。";
}
// 释放结果集
$result = null;
} catch (PDOException $e) {
die("操作失败:" . $e->getMessage());
} finally {
unset($pdo); // 释放连接
}
?>
(7)WHERE语句
WHERE子句仅用于提取满足指定条件的那些记录。WHERE子句的基本语法可以通过以下方式给出:
SELECT column_name(s) FROM table_name WHERE column_name operator value
让我们使用SELECT语句中的WHERE子句进行一个SQL查询,然后通过将其传递给PHP mysqli_query()函数来执行该查询,以获取过滤后的数据。
1. 面向过程方式
<?php
// 启用MySQLi异常模式(PHP 8+推荐)
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
try {
// 数据库连接(PHP 8+支持更简洁的连接方式)
$link = mysqli_connect("localhost", "root", "", "demo");
// 设置字符编码(强制UTF-8,避免乱码)
mysqli_set_charset($link, 'utf8mb4');
// 查询语句(使用单引号包裹字符串值)
$sql = "SELECT * FROM persons WHERE first_name = 'john'";
$result = mysqli_query($link, $sql);
if (mysqli_num_rows($result) > 0) {
echo "<table border='1'>";
echo "<tr><th>id</th><th>名</th><th>姓</th><th>邮箱</th></tr>";
// 使用fetch_assoc()获取关联数组(更明确)
while ($row = mysqli_fetch_assoc($result)) {
echo "<tr>";
echo "<td>{$row['id']}</td>";
echo "<td>{$row['first_name']}</td>";
echo "<td>{$row['last_name']}</td>";
echo "<td>{$row['email']}</td>";
echo "</tr>";
}
echo "</table>";
} else {
echo "未找到匹配记录";
}
// 释放结果集
mysqli_free_result($result);
// 关闭连接
mysqli_close($link);
} catch (mysqli_sql_exception $e) {
// PHP 8+的异常处理,更清晰地捕获错误
die("数据库操作失败: " . $e->getMessage());
}
?>
2. 面向对象方式
<?php
// 启用MySQLi异常模式
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
try {
// 实例化MySQLi对象(PHP 8+构造函数参数更严格)
$mysqli = new mysqli("localhost", "root", "", "demo");
// 设置字符编码
$mysqli->set_charset('utf8mb4');
$sql = "SELECT * FROM persons WHERE first_name = 'john'";
$result = $mysqli->query($sql);
if ($result->num_rows > 0) {
echo "<table border='1'>";
echo "<tr><th>id</th><th>名</th><th>姓</th><th>邮箱</th></tr>";
// 使用面向对象的fetch_assoc()
while ($row = $result->fetch_assoc()) {
echo "<tr>";
echo "<td>{$row['id']}</td>";
echo "<td>{$row['first_name']}</td>";
echo "<td>{$row['last_name']}</td>";
echo "<td>{$row['email']}</td>";
echo "</tr>";
}
echo "</table>";
// 释放结果集
$result->free();
} else {
echo "未找到匹配记录";
}
// 关闭连接
$mysqli->close();
} catch (mysqli_sql_exception $e) {
die("数据库操作失败: " . $e->getMessage());
}
?>
3. PDO 方式
<?php
try {
// PDO连接(PHP 8+支持DSN中指定charset)
$pdo = new PDO(
"mysql:host=localhost;dbname=demo;charset=utf8mb4",
"root",
"",
[
// PHP 8+推荐的选项配置
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, // 异常模式
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, // 默认关联数组
PDO::ATTR_EMULATE_PREPARES => false // 禁用预处理模拟(更安全)
]
);
$sql = "SELECT * FROM persons WHERE first_name = 'john'";
$result = $pdo->query($sql);
if ($result->rowCount() > 0) {
echo "<table border='1'>";
echo "<tr><th>id</th><th>名</th><th>姓</th><th>邮箱</th></tr>";
// 直接遍历结果集(PHP 8+支持)
foreach ($result as $row) {
echo "<tr>";
echo "<td>{$row['id']}</td>";
echo "<td>{$row['first_name']}</td>";
echo "<td>{$row['last_name']}</td>";
echo "<td>{$row['email']}</td>";
echo "</tr>";
}
echo "</table>";
} else {
echo "未找到匹配记录";
}
} catch (PDOException $e) {
die("数据库操作失败: " . $e->getMessage());
}
// PDO会自动关闭连接,无需手动unset
?>
(8)LIMIT语句
1.LIMIT 子句基础语法
LIMIT
子句用于限制 SQL 查询返回的记录数量,核心作用是优化性能(减少数据传输)和实现分页。
基本语法
-- 语法1:返回前 N 条记录(从第1条开始)
SELECT 列名 FROM 表名 LIMIT 记录数;
-- 语法2:从偏移量开始,返回 N 条记录(偏移量从0开始)
SELECT 列名 FROM 表名 LIMIT 偏移量, 记录数;
参数说明
- 记录数:必填,指定返回的最大行数(非负整数)。
- 偏移量:可选,指定开始返回记录的位置(从 0 开始,即
LIMIT 0,5
表示返回前 5 条)。
2.基础示例:返回有限记录
假设demo
数据库的persons
表数据如下:
id | first_name | last_name | |
---|---|---|---|
1 | Peter | Parker | peterparker@mail.com |
2 | John | Rambo | johnrambo@mail.com |
3 | Clark | Kent | clarkkent@mail.com |
4 | John | Carter | johncarter@mail.com |
5 | Harry | Potter | harrypotter@mail.com |
1. MySQLi 面向过程方式(PHP 8+)
<?php
// 启用MySQLi异常模式(PHP 8+推荐)
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
try {
// 连接数据库并设置字符编码
$link = mysqli_connect("localhost", "root", "", "demo");
mysqli_set_charset($link, 'utf8mb4'); // 支持emoji等特殊字符
// 查询前3条记录(LIMIT 3 等价于 LIMIT 0,3)
$sql = "SELECT * FROM persons LIMIT 3";
$result = mysqli_query($link, $sql);
if (mysqli_num_rows($result) > 0) {
echo "<table border='1'>";
echo "<tr><th>ID</th><th>名</th><th>姓</th><th>邮箱</th></tr>";
// 使用fetch_assoc()获取关联数组(更直观)
while ($row = mysqli_fetch_assoc($result)) {
echo "<tr>";
echo "<td>{$row['id']}</td>";
echo "<td>{$row['first_name']}</td>";
echo "<td>{$row['last_name']}</td>";
echo "<td>{$row['email']}</td>";
echo "</tr>";
}
echo "</table>";
} else {
echo "未找到记录";
}
// 释放资源
mysqli_free_result($result);
mysqli_close($link);
} catch (mysqli_sql_exception $e) {
die("数据库错误:" . $e->getMessage()); // 统一异常处理
}
?>
2. MySQLi 面向对象方式
<?php
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
try {
// 实例化MySQLi对象
$mysqli = new mysqli("localhost", "root", "", "demo");
$mysqli->set_charset('utf8mb4'); // 设置编码
// 从偏移量1开始,返回2条记录(即第2、3条)
$sql = "SELECT * FROM persons LIMIT 1, 2";
$result = $mysqli->query($sql);
if ($result->num_rows > 0) {
echo "<table border='1'>";
echo "<tr><th>ID</th><th>名</th><th>姓</th><th>邮箱</th></tr>";
while ($row = $result->fetch_assoc()) { // 面向对象的fetch方法
echo "<tr>";
echo "<td>{$row['id']}</td>";
echo "<td>{$row['first_name']}</td>";
echo "<td>{$row['last_name']}</td>";
echo "<td>{$row['email']}</td>";
echo "</tr>";
}
echo "</table>";
$result->free(); // 释放结果集
} else {
echo "未找到记录";
}
$mysqli->close(); // 关闭连接
} catch (mysqli_sql_exception $e) {
die("数据库错误:" . $e->getMessage());
}
?>
3. PDO 方式
<?php
try {
// 连接数据库并配置参数(PHP 8+推荐)
$pdo = new PDO(
"mysql:host=localhost;dbname=demo;charset=utf8mb4",
"root",
"",
[
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, // 异常模式
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, // 默认关联数组
PDO::ATTR_EMULATE_PREPARES => false // 禁用预处理模拟(更安全)
]
);
// 返回第4-5条记录(偏移量3,返回2条)
$sql = "SELECT * FROM persons LIMIT 3, 2";
$result = $pdo->query($sql);
if ($result->rowCount() > 0) {
echo "<table border='1'>";
echo "<tr><th>ID</th><th>名</th><th>姓</th><th>邮箱</th></tr>";
foreach ($result as $row) { // 直接遍历结果集
echo "<tr>";
echo "<td>{$row['id']}</td>";
echo "<td>{$row['first_name']}</td>";
echo "<td>{$row['last_name']}</td>";
echo "<td>{$row['email']}</td>";
echo "</tr>";
}
echo "</table>";
} else {
echo "未找到记录";
}
} catch (PDOException $e) {
die("数据库错误:" . $e->getMessage());
}
?>
三、核心应用:分页功能实现
LIMIT
最常用的场景是分页,将大量记录拆分到多个页面。以下是完整分页实现步骤:
1. 分页核心逻辑
- 页码参数:从 URL 获取当前页码(如
page=1
)。 - 每页记录数:固定值(如每页显示 2 条)。
- 偏移量计算:
偏移量 = (当前页码 - 1) × 每页记录数
。 - 总页数计算:
总页数 = ceil(总记录数 / 每页记录数)
。
2. 完整分页示例
<?php
try {
$pdo = new PDO(
"mysql:host=localhost;dbname=demo;charset=utf8mb4",
"root",
"",
[
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC
]
);
// 1. 获取并验证页码参数(防止无效输入)
$page = filter_input(INPUT_GET, 'page', FILTER_VALIDATE_INT) ?? 1; // 默认为第1页
$page = max($page, 1); // 确保页码≥1
$perPage = 2; // 每页显示2条
// 2. 计算偏移量
$offset = ($page - 1) * $perPage;
// 3. 查询当前页记录
$stmt = $pdo->prepare("SELECT * FROM persons LIMIT :offset, :perPage");
$stmt->bindParam(':offset', $offset, PDO::PARAM_INT); // 强制整数类型(防注入)
$stmt->bindParam(':perPage', $perPage, PDO::PARAM_INT);
$stmt->execute();
$persons = $stmt->fetchAll();
// 4. 查询总记录数(用于计算总页数)
$totalRecords = $pdo->query("SELECT COUNT(*) FROM persons")->fetchColumn();
$totalPages = ceil($totalRecords / $perPage);
// 5. 显示记录
if ($persons) {
echo "<table border='1'>";
echo "<tr><th>ID</th><th>名</th><th>姓</th><th>邮箱</th></tr>";
foreach ($persons as $row) {
echo "<tr>";
echo "<td>{$row['id']}</td>";
echo "<td>{$row['first_name']}</td>";
echo "<td>{$row['last_name']}</td>";
echo "<td>{$row['email']}</td>";
echo "</tr>";
}
echo "</table>";
} else {
echo "当前页无记录";
}
// 6. 生成分页链接
echo "<div style='margin-top: 10px;'>";
if ($page > 1) {
echo "<a href='?page=" . ($page - 1) . "'>上一页</a> ";
}
for ($i = 1; $i <= $totalPages; $i++) {
// 高亮当前页
$active = ($i == $page) ? "style='color: red;'" : "";
echo "<a href='?page=$i' $active>$i</a> ";
}
if ($page < $totalPages) {
echo "<a href='?page=" . ($page + 1) . "'>下一页</a>";
}
echo "</div>";
} catch (PDOException $e) {
die("分页错误:" . $e->getMessage());
}
?>
(9)ORDER BY
1.ORDER BY 子句基础语法
ORDER BY
子句用于对 SQL 查询结果进行排序,可按单个或多个列升序 / 降序排列,是数据展示中不可或缺的功能(如列表排序、排行榜等)。
1.基本语法
-- 语法1:按单列排序(默认升序ASC)
SELECT 列名 FROM 表名 ORDER BY 排序列 [ASC|DESC];
-- 语法2:按多列排序(先按列1排序,列1相同则按列2排序)
SELECT 列名 FROM 表名 ORDER BY 列1 [ASC|DESC], 列2 [ASC|DESC];
2.参数说明
- 排序列:指定用于排序的字段(如
first_name
、id
)。 - ASC:升序排序(默认值,可省略),如字母从 A 到 Z,数字从 0 到 9。
- DESC:降序排序,如字母从 Z 到 A,数字从 9 到 0。
2.基础示例:单字段排序
假设demo
数据库的persons
表数据如下:
id | first_name | last_name | |
---|---|---|---|
1 | Peter | Parker | peterparker@mail.com |
2 | John | Rambo | johnrambo@mail.com |
3 | Clark | Kent | clarkkent@mail.com |
4 | John | Carter | johncarter@mail.com |
5 | Harry | Potter | harrypotter@mail.com |
1. MySQLi 面向过程方式
<?php
// 启用MySQLi异常模式(PHP 8+推荐)
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
try {
// 连接数据库并设置字符编码
$link = mysqli_connect("localhost", "root", "", "demo");
mysqli_set_charset($link, 'utf8mb4'); // 支持特殊字符
// 按first_name升序排序(默认ASC,可省略)
$sql = "SELECT * FROM persons ORDER BY first_name ASC";
$result = mysqli_query($link, $sql);
if (mysqli_num_rows($result) > 0) {
echo "<table border='1'>";
echo "<tr><th>ID</th><th>名</th><th>姓</th><th>邮箱</th></tr>";
// 使用fetch_assoc()获取关联数组
while ($row = mysqli_fetch_assoc($result)) {
echo "<tr>";
echo "<td>{$row['id']}</td>";
echo "<td>{$row['first_name']}</td>";
echo "<td>{$row['last_name']}</td>";
echo "<td>{$row['email']}</td>";
echo "</tr>";
}
echo "</table>";
} else {
echo "未找到记录";
}
// 释放资源
mysqli_free_result($result);
mysqli_close($link);
} catch (mysqli_sql_exception $e) {
die("数据库错误:" . $e->getMessage()); // 统一异常处理
}
?>
2. MySQLi 面向对象方式
<?php
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
try {
// 实例化MySQLi对象
$mysqli = new mysqli("localhost", "root", "", "demo");
$mysqli->set_charset('utf8mb4'); // 设置编码
// 按first_name降序排序(DESC显式指定)
$sql = "SELECT * FROM persons ORDER BY first_name DESC";
$result = $mysqli->query($sql);
if ($result->num_rows > 0) {
echo "<table border='1'>";
echo "<tr><th>ID</th><th>名</th><th>姓</th><th>邮箱</th></tr>";
while ($row = $result->fetch_assoc()) {
echo "<tr>";
echo "<td>{$row['id']}</td>";
echo "<td>{$row['first_name']}</td>";
echo "<td>{$row['last_name']}</td>";
echo "<td>{$row['email']}</td>";
echo "</tr>";
}
echo "</table>";
$result->free(); // 释放结果集
} else {
echo "未找到记录";
}
$mysqli->close(); // 关闭连接
} catch (mysqli_sql_exception $e) {
die("数据库错误:" . $e->getMessage());
}
?>
3. PDO 方式
<?php
try {
// 连接数据库并配置参数
$pdo = new PDO(
"mysql:host=localhost;dbname=demo;charset=utf8mb4",
"root",
"",
[
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, // 异常模式
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, // 默认关联数组
PDO::ATTR_EMULATE_PREPARES => false // 禁用预处理模拟
]
);
// 按id降序排序(从大到小)
$sql = "SELECT * FROM persons ORDER BY id DESC";
$result = $pdo->query($sql);
if ($result->rowCount() > 0) {
echo "<table border='1'>";
echo "<tr><th>ID</th><th>名</th><th>姓</th><th>邮箱</th></tr>";
foreach ($result as $row) { // 直接遍历结果集
echo "<tr>";
echo "<td>{$row['id']}</td>";
echo "<td>{$row['first_name']}</td>";
echo "<td>{$row['last_name']}</td>";
echo "<td>{$row['email']}</td>";
echo "</tr>";
}
echo "</table>";
} else {
echo "未找到记录";
}
} catch (PDOException $e) {
die("数据库错误:" . $e->getMessage());
}
?>
(10)UPDATE
1.UPDATE 子句基础语法
UPDATE
语句用于修改数据库表中的现有记录,核心作用是更新符合条件的数据。必须结合WHERE
子句使用,否则会误更新全表数据!
-- 基础语法:更新单表中的字段
UPDATE 表名
SET 列1 = 值1, 列2 = 值2, ...
WHERE 条件; -- 关键:指定更新哪些记录
核心说明
SET
子句:指定要更新的列和对应的值(多个列用逗号分隔)。WHERE
子句:筛选需要更新的记录(如id = 1
、status = 'active'
),缺失则更新全表!- 返回值:MySQL 返回受影响的行数(可用于判断更新是否成功)。
假设demo
数据库的persons
表初始数据如下:
id | first_name | last_name | |
---|---|---|---|
1 | Peter | Parker | peterparker@mail.com |
2 | John | Rambo | johnrambo@mail.com |
2. MySQLi 面向过程方式
<?php
// 启用MySQLi异常模式(PHP 8+推荐)
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
try {
// 连接数据库并设置编码
$link = mysqli_connect("localhost", "root", "", "demo");
mysqli_set_charset($link, 'utf8mb4');
// 更新id=1的记录:修改email
$sql = "UPDATE persons
SET email = 'peter.new@mail.com'
WHERE id = 1";
$affectedRows = mysqli_query($link, $sql);
// 判断更新结果(mysqli_affected_rows返回受影响行数)
if (mysqli_affected_rows($link) > 0) {
echo "记录更新成功!受影响行数:" . mysqli_affected_rows($link);
} else {
echo "未找到匹配记录或无需更新。";
}
mysqli_close($link);
} catch (mysqli_sql_exception $e) {
die("更新失败:" . $e->getMessage()); // 统一异常处理
}
?>
3. MySQLi 面向对象方式
<?php
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
try {
// 实例化MySQLi对象
$mysqli = new mysqli("localhost", "root", "", "demo");
$mysqli->set_charset('utf8mb4');
// 更新id=2的记录:同时修改first_name和last_name
$sql = "UPDATE persons
SET first_name = 'Johnny', last_name = 'Rambo Jr'
WHERE id = 2";
$mysqli->query($sql);
// 判断结果($mysqli->affected_rows获取受影响行数)
if ($mysqli->affected_rows > 0) {
echo "更新成功!受影响行数:" . $mysqli->affected_rows;
} else {
echo "未找到匹配记录或数据无变化。";
}
$mysqli->close();
} catch (mysqli_sql_exception $e) {
die("更新失败:" . $e->getMessage());
}
?>
4. PDO 方式
<?php
try {
// 连接数据库并配置参数
$pdo = new PDO(
"mysql:host=localhost;dbname=demo;charset=utf8mb4",
"root",
"",
[
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, // 异常模式
PDO::ATTR_EMULATE_PREPARES => false // 禁用预处理模拟(安全)
]
);
// 更新id=1的记录:使用PDO::exec()执行更新
$sql = "UPDATE persons
SET email = 'peter.updated@mail.com'
WHERE id = 1";
$affectedRows = $pdo->exec($sql); // exec()返回受影响行数
if ($affectedRows > 0) {
echo "更新成功!受影响行数:" . $affectedRows;
} else {
echo "未找到匹配记录或数据未变更。";
}
} catch (PDOException $e) {
die("更新失败:" . $e->getMessage());
}
?>
5.高级用法:事务处理与批量更新
a. 事务确保更新原子性
当需要同时更新多个表或多条记录时,使用事务保证操作的原子性(要么全成功,要么全失败):
<?php
try {
$pdo = new PDO(
"mysql:host=localhost;dbname=demo;charset=utf8mb4",
"root",
"",
[PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]
);
// 开始事务
$pdo->beginTransaction();
// 操作1:更新用户表
$stmt1 = $pdo->prepare("UPDATE persons SET balance = balance - 100 WHERE id = 1");
$stmt1->execute();
// 操作2:更新日志表
$stmt2 = $pdo->prepare("INSERT INTO logs (user_id, action) VALUES (?, '扣款100元')");
$stmt2->execute([1]);
// 提交事务(所有操作成功才生效)
$pdo->commit();
echo "事务执行成功!";
} catch (PDOException $e) {
// 回滚事务(任何操作失败则全部撤销)
$pdo->rollBack();
die("事务失败:" . $e->getMessage());
}
?>
b. 批量更新多条记录
通过循环或批量 SQL 语句一次性更新多条记录:
<?php
try {
$pdo = new PDO(
"mysql:host=localhost;dbname=demo;charset=utf8mb4",
"root",
"",
[PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]
);
// 批量更新数据(例如:批量修改状态)
$updates = [
['id' => 1, 'status' => 'active'],
['id' => 2, 'status' => 'inactive'],
['id' => 3, 'status' => 'active']
];
// 预处理单条更新语句
$stmt = $pdo->prepare("UPDATE persons SET status = :status WHERE id = :id");
// 循环执行批量更新
foreach ($updates as $data) {
$stmt->execute($data);
}
echo "批量更新完成!共更新 " . count($updates) . " 条记录。";
} catch (PDOException $e) {
die("批量更新失败:" . $e->getMessage());
}
?>
(11)DELETE
1.删除数据库表数据
正如将记录插入表中一样,您可以使用SQL DELETE语句从表中删除记录。它通常与WHERE子句结合使用,仅删除那些符合特定条件或条件的记录。
DELETE语句的基本语法可以通过以下方式给出:
DELETE FROM table_name WHERE column_name=some_value
让我们使用DELETE语句和WHERE子句进行一个SQL查询,然后通过将其传递给PHP mysqli_query()函数来执行此查询,以删除表记录。请看demo数据库中的以下persons表:
+----+------------+-----------+----------------------+
| id | first_name | last_name | email |
+----+------------+-----------+----------------------+
| 1 | Peter | Parker | peterparker@mail.com |
| 2 | John | Rambo | johnrambo@mail.com |
| 3 | Clark | Kent | clarkkent@mail.com |
| 4 | John | Carter | johncarter@mail.com |
| 5 | Harry | Potter | harrypotter@mail.com |
+----+------------+-----------+----------------------+
下面示例中的PHP代码将从persons表中删除first_name等于John的人的记录。
2.面向过程方式
<?php
/* 尝试MySQL服务器连接。 假设您正在运行MySQL。
具有默认设置的服务器(没有密码的用户“root”) */
$link = mysqli_connect("localhost", "root", "", "demo");
//检查连接
if($link === false){
die("错误:无法连接。 " . mysqli_connect_error());
}
//尝试执行删除
$sql = "DELETE FROM persons WHERE first_name='John'";
if(mysqli_query($link, $sql)){
echo "记录已成功删除。";
} else{
echo "错误:无法执行 $sql. " . mysqli_error($link);
}
//关闭连接
mysqli_close($link);
?>
3.面向对象方式
<?php
/* 尝试MySQL服务器连接。 假设您正在运行MySQL。
具有默认设置的服务器(没有密码的用户“root”) */
$mysqli = new mysqli("localhost", "root", "", "demo");
//检查连接
if($mysqli === false){
die("错误:无法连接。 " . $mysqli->connect_error);
}
//尝试执行删除
$sql = "DELETE FROM persons WHERE first_name='John'";
if($mysqli->query($sql) === true){
echo "记录已成功删除。";
} else{
echo "错误:无法执行 $sql. " . $mysqli->error;
}
//关闭连接
$mysqli->close();
?>
4.PDO方式
<?php
/* 尝试MySQL服务器连接。 假设您正在运行MySQL。
具有默认设置的服务器(没有密码的用户“root”)*/
try{
$pdo = new PDO("mysql:host=localhost;dbname=demo", "root", "");
//将PDO错误模式设置为异常
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch(PDOException $e){
die("错误:无法连接。 " . $e->getMessage());
}
//尝试更新查询执行
try{
$sql = "DELETE FROM persons WHERE first_name='John'";
$pdo->exec($sql);
echo "记录已成功删除。";
} catch(PDOException $e){
die("错误:无法执行 $sql. " . $e->getMessage());
}
//关闭连接
unset($pdo);
?>
删除后,persons表将如下所示:
+----+------------+-----------+----------------------+
| id | first_name | last_name | email |
+----+------------+-----------+----------------------+
| 1 | Peter | Parker | peterparker@mail.com |
| 3 | Clark | Kent | clarkkent@mail.com |
| 5 | Harry | Potter | harrypotter@mail.com |
+----+------------+-----------+----------------------+
正如您看到的,记录已成功从persons表中删除。
**警告:**DELETE语句中的WHERE子句指定应该删除哪些记录。如果省略WHERE子句,所有记录都将被删除。
结语
PHP 操作 MySQL 的核心技能,是连接前端交互与后端数据的桥梁。从本文介绍的读取数据、条件筛选、分页排序,到更新与删除操作,每一个环节都承载着数据流转的逻辑,也暗藏着需要规避的风险 —— 例如UPDATE和DELETE中缺失WHERE子句可能导致的全表数据误操作,或未使用预处理语句带来的 SQL 注入隐患。
通过学习三种操作方式(MySQLi 过程式、面向对象、PDO)的特性,我们不仅掌握了实现功能的工具,更理解了 “选择合适方法” 的重要性:PDO 的跨数据库兼容性、MySQLi 的原生性能优势,都需根据项目场景灵活取舍。而事务处理、批量操作等进阶技巧,则进一步提升了代码的健壮性与效率。
然而,技术的掌握不止于语法本身。真正的实践中,还需结合业务场景优化查询(如合理使用索引)、强化安全校验(如数据过滤与权限控制)、完善错误处理与日志记录。希望本文的内容能成为你开发路上的基石,让你在构建数据驱动应用时,既能精准实现需求,又能兼顾安全、性能与可维护性,为用户提供稳定可靠的服务。