You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何避免同一主类别下重复子类别插入数据库?

同一主类别下重复子类别插入限制失效的解决方法

问题根源

当前代码的检查逻辑存在漏洞,同时缺乏数据库层面的兜底约束,导致重复子类别仍能被插入:

  • 直接将POST参数拼入SQL语句,存在SQL注入风险,可能干扰查询逻辑;
  • 未对输入的子类别名称做空格、大小写统一处理,比如"Phone"和"phone"会被判定为不同内容;
  • 仅靠代码查询做检查,存在并发插入漏洞,多请求同时操作时可能绕过检查。

修复方案

1. 重构代码:用预处理语句+输入清洗

替换原有PHP逻辑,通过预处理语句避免注入,同时清洗输入内容确保查询准确:

<?php
include "include/config.php";
session_start(); // 必须在输出前启动session,否则无法存储提示信息

if (isset($_POST['create_scats'])) {
    $main_cat_id = $_POST['main_cat_id'];
    // 清洗子类别名称:去首尾空格,统一转小写(可根据需求取消大小写统一)
    $sub_cat_name = trim(strtolower($_POST['sub_cat_name']));

    // 预处理语句检查重复
    $checkStmt = mysqli_prepare($con, "SELECT id FROM sub_cat WHERE main_cat_id = ? AND LOWER(sub_cat_name) = ?");
    mysqli_stmt_bind_param($checkStmt, "is", $main_cat_id, $sub_cat_name);
    mysqli_stmt_execute($checkStmt);
    mysqli_stmt_store_result($checkStmt);

    if (mysqli_stmt_num_rows($checkStmt) > 0) {
        $_SESSION['scaterror'] = "<h4 style='color:#ed2324; text-align:center'>该主类别下已存在此子类别。</h4>";
        header('Location: add-sub-category.php');
        exit;
    } else {
        // 预处理插入语句
        $insertStmt = mysqli_prepare($con, "INSERT INTO sub_cat (main_cat_id, sub_cat_name) VALUES (?, ?)");
        // 可选:用ucwords还原首字母大写,保持名称格式统一
        mysqli_stmt_bind_param($insertStmt, "is", $main_cat_id, ucwords($sub_cat_name));
        $insertSuccess = mysqli_stmt_execute($insertStmt);

        if ($insertSuccess) {
            $_SESSION['scatsuccess'] = "<h4 style='color:#00cc00; text-align:center'>子类别创建成功。</h4>";
            header('Location: add-sub-category.php');
            exit;
        } else {
            // 捕获数据库唯一约束报错
            if (mysqli_errno($con) == 1062) {
                $_SESSION['scaterror'] = "<h4 style='color:#ed2324; text-align:center'>该主类别下已存在此子类别。</h4>";
                header('Location: add-sub-category.php');
                exit;
            }
            echo '操作失败,请重试!';
        }
    }
    mysqli_stmt_close($checkStmt);
    mysqli_stmt_close($insertStmt);
}
?>

2. 数据库层面添加联合唯一约束(彻底杜绝重复)

直接在sub_cat表上添加联合唯一索引,从根源阻止同一主类别下的重复子类别插入:

ALTER TABLE sub_cat ADD UNIQUE KEY unique_main_sub (main_cat_id, sub_cat_name);

添加后,即使代码检查失效,数据库也会自动拒绝重复插入,配合代码中的错误捕获可以给用户准确提示。

3. 前端优化(提升用户体验)

在输入框添加实时去空格处理,减少无效输入:

<input class="form-control" name="sub_cat_name" type="text" placeholder="子类别名称" oninput="this.value = this.value.trim()">

注意事项

  • 确保session_start()在页面所有输出之前调用,否则无法正常存储提示信息;
  • 如果业务需要区分子类别名称的大小写,去掉代码中的strtolower()和SQL中的LOWER()即可。

内容的提问来源于stack exchange,提问作者Ivance Edwards

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 22:34:51