Appearance
12.5 修改数据 update
UPDATE 语句基础
UPDATE 语句用于修改数据库表中已存在的记录,是数据库操作中常用的操作之一。
基本语法
sql
UPDATE table_name SET column1 = value1, column2 = value2, ... WHERE condition;基本更新
1. 更新单条记录
php
<?php
require_once 'db.php';
$conn = getDbConnection();
// 更新单条记录
$sql = "UPDATE users SET age = 26, email = 'updated@example.com' WHERE id = 1";
if ($conn->query($sql) === TRUE) {
echo "记录更新成功,影响行数: " . $conn->affected_rows;
} else {
echo "更新失败: " . $conn->error;
}
$conn->close();
?>2. 更新多条记录
php
<?php
require_once 'db.php';
$conn = getDbConnection();
// 更新多条记录
$sql = "UPDATE users SET age = age + 1 WHERE age < 18";
if ($conn->query($sql) === TRUE) {
echo "记录更新成功,影响行数: " . $conn->affected_rows;
} else {
echo "更新失败: " . $conn->error;
}
$conn->close();
?>使用预处理语句
预处理语句可以防止 SQL 注入攻击,同时提高执行效率。
1. 更新单条记录
php
<?php
require_once 'db.php';
$conn = getDbConnection();
// 准备语句
$stmt = $conn->prepare("UPDATE users SET age = ?, email = ? WHERE id = ?");
$stmt->bind_param("isi", $age, $email, $id);
// 设置参数并执行
$age = 27;
$email = 'newemail@example.com';
$id = 1;
if ($stmt->execute()) {
echo "记录更新成功,影响行数: " . $stmt->affected_rows;
} else {
echo "更新失败: " . $stmt->error;
}
$stmt->close();
$conn->close();
?>2. 批量更新
php
<?php
require_once 'db.php';
$conn = getDbConnection();
// 准备语句
$stmt = $conn->prepare("UPDATE users SET age = ? WHERE id = ?");
$stmt->bind_param("ii", $age, $id);
// 要更新的数据
$updates = [
[28, 2],
[29, 3],
[30, 4]
];
// 执行多次更新
$successCount = 0;
foreach ($updates as $update) {
$age = $update[0];
$id = $update[1];
if ($stmt->execute()) {
$successCount++;
}
}
echo "成功更新 $successCount 条记录";
$stmt->close();
$conn->close();
?>更新数据与表单结合
1. 基本表单处理
php
<?php
require_once 'db.php';
$conn = getDbConnection();
$errors = [];
$success = false;
$user = null;
// 获取用户信息
if (isset($_GET['id'])) {
$id = (int)$_GET['id'];
$stmt = $conn->prepare("SELECT * FROM users WHERE id = ?");
$stmt->bind_param("i", $id);
$stmt->execute();
$result = $stmt->get_result();
if ($result->num_rows > 0) {
$user = $result->fetch_assoc();
} else {
$errors[] = '用户不存在';
}
$stmt->close();
}
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($user)) {
// 表单验证
if (empty($_POST['username'])) {
$errors[] = '用户名不能为空';
}
if (empty($_POST['email'])) {
$errors[] = '邮箱不能为空';
} else if (!filter_var($_POST['email'], FILTER_VALIDATE_EMAIL)) {
$errors[] = '邮箱格式不正确';
}
if (empty($errors)) {
// 准备语句
$stmt = $conn->prepare("UPDATE users SET username = ?, email = ? WHERE id = ?");
$stmt->bind_param("ssi", $username, $email, $id);
// 设置参数
$username = htmlspecialchars($_POST['username']);
$email = htmlspecialchars($_POST['email']);
if ($stmt->execute()) {
$success = true;
// 重新获取用户信息
$stmt = $conn->prepare("SELECT * FROM users WHERE id = ?");
$stmt->bind_param("i", $id);
$stmt->execute();
$result = $stmt->get_result();
$user = $result->fetch_assoc();
} else {
$errors[] = '更新失败: ' . $stmt->error;
}
$stmt->close();
}
}
$conn->close();
?>
<!DOCTYPE html>
<html>
<head>
<title>编辑用户</title>
<style>
body { font-family: Arial, sans-serif; max-width: 400px; margin: 0 auto; padding: 20px; }
.error { color: red; }
.success { color: green; }
input { width: 100%; padding: 10px; margin: 5px 0; }
input[type="submit"] { background-color: #4CAF50; color: white; border: none; cursor: pointer; }
</style>
</head>
<body>
<h2>编辑用户</h2>
<?php if (!empty($errors)): ?>
<div class="error">
<ul>
<?php foreach ($errors as $error): ?>
<li><?php echo $error; ?></li>
<?php endforeach; ?>
</ul>
</div>
<?php endif; ?>
<?php if ($success): ?>
<div class="success">
用户更新成功!
</div>
<?php endif; ?>
<?php if ($user): ?>
<form action="" method="post">
<label>用户名: <input type="text" name="username" value="<?php echo $user['username']; ?>"></label><br>
<label>邮箱: <input type="email" name="email" value="<?php echo $user['email']; ?>"></label><br>
<input type="submit" value="更新用户">
</form>
<?php endif; ?>
</body>
</html>更新数据时的注意事项
1. WHERE 子句
非常重要:如果省略 WHERE 子句,UPDATE 语句将更新表中的所有记录!
php
// 危险!会更新所有记录
$sql = "UPDATE users SET age = 30";
// 安全:只更新指定记录
$sql = "UPDATE users SET age = 30 WHERE id = 1";2. 数据类型匹配
确保更新的值与表字段的数据类型匹配:
- 字符串类型:使用引号包围
- 数字类型:直接使用,不使用引号
- 日期类型:使用引号包围,格式为 'YYYY-MM-DD'
- 布尔类型:使用 1 或 0
3. 转义特殊字符
使用预处理语句或 mysqli_real_escape_string 函数转义特殊字符:
php
// 使用 mysqli_real_escape_string
$username = mysqli_real_escape_string($conn, $_POST['username']);
$sql = "UPDATE users SET username = '$username' WHERE id = 1";4. 处理 NULL 值
要将字段设置为 NULL,使用 NULL 关键字(不带引号):
php
$sql = "UPDATE users SET age = NULL WHERE id = 1";
// 使用预处理语句
$stmt = $conn->prepare("UPDATE users SET age = ? WHERE id = ?");
$age = null;
$stmt->bind_param("ii", $age, $id);事务处理
对于需要更新多条相关记录的情况,使用事务确保数据一致性:
php
<?php
require_once 'db.php';
$conn = getDbConnection();
// 开始事务
$conn->begin_transaction();
try {
// 更新用户信息
$stmt = $conn->prepare("UPDATE users SET username = ? WHERE id = ?");
$stmt->bind_param("si", $username, $userId);
$username = "新用户名";
$userId = 1;
$stmt->execute();
// 更新用户资料
$stmt = $conn->prepare("UPDATE user_profiles SET full_name = ? WHERE user_id = ?");
$stmt->bind_param("si", $fullName, $userId);
$fullName = "新全名";
$stmt->execute();
// 提交事务
$conn->commit();
echo "用户信息更新成功";
} catch (mysqli_sql_exception $e) {
// 回滚事务
$conn->rollback();
echo "更新失败: " . $e->getMessage();
}
$stmt->close();
$conn->close();
?>高级更新技巧
1. 使用表达式更新
php
<?php
require_once 'db.php';
$conn = getDbConnection();
// 使用表达式更新
$sql = "UPDATE users SET age = age + 1, login_count = login_count + 1 WHERE id = 1";
if ($conn->query($sql) === TRUE) {
echo "记录更新成功";
} else {
echo "更新失败: " . $conn->error;
}
$conn->close();
?>2. 使用 CASE 语句
php
<?php
require_once 'db.php';
$conn = getDbConnection();
// 使用 CASE 语句
$sql = "UPDATE users SET
status = CASE
WHEN age < 18 THEN '未成年'
WHEN age >= 18 AND age < 60 THEN '成年'
ELSE '老年'
END
";
if ($conn->query($sql) === TRUE) {
echo "记录更新成功,影响行数: " . $conn->affected_rows;
} else {
echo "更新失败: " . $conn->error;
}
$conn->close();
?>3. 基于子查询更新
php
<?php
require_once 'db.php';
$conn = getDbConnection();
// 基于子查询更新
$sql = "UPDATE users SET age = (SELECT AVG(age) FROM users) WHERE id = 1";
if ($conn->query($sql) === TRUE) {
echo "记录更新成功";
} else {
echo "更新失败: " . $conn->error;
}
$conn->close();
?>最佳实践
- 使用 WHERE 子句:始终指定 WHERE 子句,避免更新所有记录
- 使用预处理语句:防止 SQL 注入攻击
- 数据验证:在更新前验证数据的有效性
- 错误处理:处理更新过程中的错误
- 事务处理:对于相关操作使用事务
- 检查影响行数:使用 $conn->affected_rows 检查更新是否成功
- 优化更新:只更新必要的字段,避免更新所有字段
练习
- 更新单条用户记录
- 更新多条用户记录
- 使用预处理语句更新数据
- 结合表单更新数据
- 使用事务更新相关数据
- 使用表达式和 CASE 语句更新数据
