在PHP开发的实际业务场景中,增删改查操作经常会遇到重复数据的问题,比如用户重复提交表单导致同一条数据多次入库,或者查询列表时出现重复的记录,处理不好会影响业务逻辑的正常运行。下面结合实际场景介绍对应的处理方法。

一、新增操作时防止重复数据
1. 数据库层面设置唯一约束
最直接的方式是在数据库表中对需要唯一的字段设置唯一索引,这样即使PHP端出现重复提交,数据库也会直接拒绝插入,返回错误提示。比如用户表的手机号字段需要唯一,建表时可以添加如下约束:
CREATE TABLE `user` ( `id` int(11) NOT NULL AUTO_INCREMENT, `phone` varchar(20) NOT NULL COMMENT '手机号', `username` varchar(50) NOT NULL COMMENT '用户名', PRIMARY KEY (`id`), UNIQUE KEY `uniq_phone` (`phone`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
当PHP执行插入操作时,如果phone字段重复,会抛出唯一约束冲突的错误,我们可以捕获这个错误做对应的提示处理:
<?php
$pdo = new PDO('mysql:host=127.0.0.1;dbname=test;charset=utf8mb4', 'root', 'root');
$phone = '13800138000';
$username = '测试用户';
$sql = "INSERT INTO `user` (`phone`, `username`) VALUES (?, ?)";
$stmt = $pdo->prepare($sql);
try {
$stmt->execute([$phone, $username]);
echo "新增成功";
} catch (PDOException $e) {
// 判断是否为唯一约束错误,错误码23000
if ($e->getCode() == 23000) {
echo "该手机号已注册,请勿重复提交";
} else {
echo "新增失败:" . $e->getMessage();
}
}
?>
2. PHP代码层先校验是否存在
在插入前先查询数据库判断对应数据是否已经存在,存在则不再执行插入操作,这种方式适合需要自定义校验逻辑的场景:
<?php
$pdo = new PDO('mysql:host=127.0.0.1;dbname=test;charset=utf8mb4', 'root', 'root');
$phone = '13800138000';
// 先查询手机号是否已存在
$checkSql = "SELECT COUNT(*) FROM `user` WHERE `phone` = ?";
$checkStmt = $pdo->prepare($checkSql);
$checkStmt->execute([$phone]);
$count = $checkStmt->fetchColumn();
if ($count > 0) {
echo "该手机号已存在,无法新增";
} else {
$insertSql = "INSERT INTO `user` (`phone`, `username`) VALUES (?, ?)";
$insertStmt = $pdo->prepare($insertSql);
$insertStmt->execute([$phone, '测试用户']);
echo "新增成功";
}
?>
二、查询操作时去除重复数据
1. 使用SQL的DISTINCT关键字
如果查询时需要返回去重后的结果,可以直接在SQL语句中使用DISTINCT关键字,比如查询所有不重复的用户手机号:
SELECT DISTINCT `phone` FROM `user`;
对应的PHP执行代码示例如下:
<?php
$pdo = new PDO('mysql:host=127.0.0.1;dbname=test;charset=utf8mb4', 'root', 'root');
$sql = "SELECT DISTINCT `phone` FROM `user`";
$stmt = $pdo->query($sql);
$result = $stmt->fetchAll(PDO::FETCH_ASSOC);
print_r($result);
?>
2. 使用GROUP BY分组去重
如果需要同时获取去重字段和其他字段的信息,可以使用GROUP BY进行分组,比如查询每个手机号对应的最新注册用户:
SELECT `phone`, MAX(`id`) as max_id FROM `user` GROUP BY `phone`;
3. PHP数组层面去重
如果查询出来的结果集存在重复,也可以在PHP代码中使用array_unique函数对数组进行去重,该函数会保留数组的第一个重复值,移除后面的重复项:
<?php
// 模拟查询出来的包含重复数据的数组
$data = [
['id' => 1, 'phone' => '13800138000'],
['id' => 2, 'phone' => '13800138000'],
['id' => 3, 'phone' => '13900139000']
];
// 提取phone字段组成新数组去重
$phoneArr = array_column($data, 'phone');
$uniquePhone = array_unique($phoneArr);
print_r($uniquePhone);
// 如果需要保留原数组结构,可以遍历过滤
$uniqueData = [];
$tempPhone = [];
foreach ($data as $item) {
if (!in_array($item['phone'], $tempPhone)) {
$tempPhone[] = $item['phone'];
$uniqueData[] = $item;
}
}
print_r($uniqueData);
?>
三、修改操作时处理重复数据
修改数据时也需要校验修改后的内容是否和其他记录重复,比如修改用户手机号时,需要判断新的手机号是否已经被其他用户使用:
<?php
$pdo = new PDO('mysql:host=127.0.0.1;dbname=test;charset=utf8mb4', 'root', 'root');
$userId = 1;
$newPhone = '13800138001';
// 先查询新手机号是否已被其他用户使用
$checkSql = "SELECT COUNT(*) FROM `user` WHERE `phone` = ? AND `id` != ?";
$checkStmt = $pdo->prepare($checkSql);
$checkStmt->execute([$newPhone, $userId]);
$count = $checkStmt->fetchColumn();
if ($count > 0) {
echo "该手机号已被其他用户使用,无法修改";
} else {
$updateSql = "UPDATE `user` SET `phone` = ? WHERE `id` = ?";
$updateStmt = $pdo->prepare($updateSql);
$updateStmt->execute([$newPhone, $userId]);
echo "修改成功";
}
?>
四、删除重复数据的方法
如果表中已经存在重复数据,需要删除多余的重复项只保留一条,可以使用如下SQL语句,比如保留id最小的重复手机号记录:
DELETE FROM `user`
WHERE `phone` IN (
SELECT `phone` FROM (
SELECT `phone` FROM `user` GROUP BY `phone` HAVING COUNT(*) > 1
) t1
)
AND `id` NOT IN (
SELECT MIN(`id`) FROM (
SELECT `id`, `phone` FROM `user` GROUP BY `phone` HAVING COUNT(*) > 1
) t2
);
注意MySQL中不能直接在子查询中查询同一张表后直接删除,所以需要多嵌套一层子查询来避免这个限制。
总结
处理PHP增删改查中的重复数据,优先推荐在数据库层面设置唯一约束,从根源上避免重复数据产生。查询时的去重可以优先使用SQL的DISTINCT或者GROUP BY,性能比PHP数组去重更好。修改和删除操作则需要结合业务场景做好前置校验,保证数据的唯一性和准确性。
PHP增删改查去重方法array_uniqueSQL_DISTINCT修改时间:2026-06-27 08:51:37