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

Express.js+MySQL+React CRUD新增FirstName重复校验实现

FirstName重复校验实现步骤

整个实现做三层覆盖,从数据兜底到前端交互全链路生效,不会出现漏校验问题。

1. 数据库层加唯一约束(必做,兜底防并发重复)

先在MySQL中执行以下SQL,给FirstName字段加唯一索引,从数据库层面禁止重复值插入:

ALTER TABLE emp_table ADD UNIQUE INDEX idx_firstname (FirstName);

2. 后端接口改造

原有后端接口存在两个问题:一是插入/更新前没有做重复校验,二是出错时仅打印控制台日志,没有给前端返回正确的错误状态码和提示,前端无法捕获错误。

改造新增接口(POST /api/post)

将原有/api/post路由替换为以下代码:

app.post("/api/post", (req, res) => {
  const { FirstName, LastName, FatherName, userCNIC, Contact, Gender } = req.body;
  // 先查询当前FirstName是否已存在
  const checkDupSql = "SELECT id FROM emp_table WHERE FirstName = ? LIMIT 1";
  db.query(checkDupSql, [FirstName], (checkErr, checkRes) => {
    if (checkErr) return res.status(500).send("服务器异常,请稍后重试");
    if (checkRes.length > 0) return res.status(400).send("First Name已存在,请勿重复添加");
    
    // 校验通过再执行插入
    const insertSql = "INSERT INTO emp_table (FirstName, LastName, FatherName, userCNIC, Contact, Gender) VALUES (?, ?, ?, ?, ?, ?)";
    db.query(insertSql, [FirstName, LastName, FatherName, userCNIC, Contact, Gender], (insertErr, insertRes) => {
      if (insertErr) {
        // 捕获唯一索引冲突错误,做兜底提示
        if (insertErr.code === 'ER_DUP_ENTRY') return res.status(400).send("First Name已存在,请勿重复添加");
        return res.status(500).send("数据添加失败,请重试");
      }
      res.send("Values inserted!");
    });
  });
});

改造更新接口(PUT /api/update/:id)

编辑场景需要注意:如果用户没有修改FirstName,查询时要排除当前正在编辑的记录本身,否则会误判重复。将原有/api/update/:id路由替换为以下代码:

app.put("/api/update/:id", (req, res) => {
  const { id } = req.params;
  const { FirstName, LastName, FatherName, userCNIC, Contact, Gender } = req.body;
  // 查询重复时排除当前编辑的记录
  const checkDupSql = "SELECT id FROM emp_table WHERE FirstName = ? AND id != ? LIMIT 1";
  db.query(checkDupSql, [FirstName, id], (checkErr, checkRes) => {
    if (checkErr) return res.status(500).send("服务器异常,请稍后重试");
    if (checkRes.length > 0) return res.status(400).send("First Name已存在,请更换后提交");
    
    // 校验通过再执行更新
    const updateSql = "UPDATE emp_table SET FirstName = ?, LastName = ?, FatherName = ?, userCNIC = ?, Contact = ?, Gender = ? WHERE id = ?";
    db.query(updateSql, [FirstName, LastName, FatherName, userCNIC, Contact, Gender, id], (updateErr, updateRes) => {
      if (updateErr) {
        if (updateErr.code === 'ER_DUP_ENTRY') return res.status(400).send("First Name已存在,请更换后提交");
        return res.status(500).send("数据更新失败,请重试");
      }
      res.send(updateRes);
    });
  });
});

3. 前端逻辑修复

原有前端代码存在两个逻辑bug,会导致错误提示无法正常展示:

  • 没有统一阻止表单默认提交行为,会触发页面刷新
  • 不管接口请求成功还是失败,都会直接弹出成功提示、500ms后跳转首页,用户看不到返回的错误信息
    将AddEdit.js中的handleSubmit函数替换为以下代码即可:
const handleSubmit = (e) => {
  // 进入提交逻辑先阻止表单默认刷新行为
  e.preventDefault();
  const phoneno = /^\d{11,12}$/;
  const cnicno = /^\d{12,13}$/;

  // 基础字段校验
  if (!FirstName || !LastName || !FatherName || !userCNIC || !Contact || !Gender) {
    toast.error("请填写所有必填字段");
    return;
  }
  if (!Contact.match(phoneno)) {
    toast.error("请输入正确的手机号");
    return;
  }
  if (!userCNIC.match(cnicno)) {
    toast.error("请输入正确的CNIC编号");
    return;
  }

  if (!id) {
    // 新增场景
    axios.post("http://localhost:5000/api/post", {
      FirstName, LastName, FatherName, userCNIC, Contact, Gender
    }).then(() => {
      // 只有请求成功才弹成功提示、清空表单、跳首页
      toast.success("联系人添加成功");
      setState(initialState);
      setTimeout(() => navigate("/"), 500);
    }).catch(err => {
      // 失败只弹错误,不跳页
      toast.error(err.response.data);
    })
  } else {
    // 编辑场景
    axios.put(`http://localhost:5000/api/update/${id}`, {
      FirstName, LastName, FatherName, userCNIC, Contact, Gender
    }).then(() => {
      toast.success("联系人更新成功");
      setState(initialState);
      setTimeout(() => navigate("/"), 500);
    }).catch(err => {
      toast.error(err.response.data);
    })
  }
};

两层校验的作用:应用层提前查询返回友好提示,交互体验更好;数据库唯一索引+错误捕获是兜底方案,防止高并发场景下出现重复数据。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 06:22:03