请问如何防止重复添加数据?

比如:导航名称或者商品的分类名称
之前添加了一个 "男装" 的分类
之后另一个工作人员不知道有"男装"分类了.还会继续添加.
请问如何防止?
难道要获取到数据库的全部分类,然后循环判断是否等于???这样的话,效率太慢了吧?

阅读 11.5k
16 个回答

数据库分类的名称设置为unique

这些数据读远远大于写,一般编辑的的操作不是很频繁,直接从数据库中读取所有的分类没有什么问题的。但前台页面显示分类信息的时候,大量的读操作,这些分类信息最好放在缓存中,然后从缓存中读取。

难道要获取到数据库的全部分类,然后循环判断是否等于

使用select count(1) from t_classify a where a.classify_name = 'xxx' 就可以了。
如果你的分类数据有放在缓存中,可以直接从缓存取数据判断(如果用了缓存,你就要维护好缓存中的分类数据,防止脏数据。)。

很多回答者回答先判断再添加操作,这种操作还是不能保证不会重复添加的。

由于并发的存在,这种判断没有再添加的操作不能保证数据不会重复添加。判断是否有,再操作,是二步操作,不是原子性的。

举个例子:

addClassify(className){
    if(!isExistInDB(className)){//如果不存在
        插入分类
    }
}

如果有二个用户,都进行"男装"分类的添加。
a用户,代码执行到isExistInDB,判断出没有男装,准备插入(还没有真正插入到数据库或者插入到数据库后事务还没有提交),这个时候b用户也执行到isExistInDB(),还是得到没有男装这个分类,也会插入男装分类。这样不就插入重复数据了吗!

使用如下方式防止重复添加
1:数据库悲观锁。
这种方式自己到搜搜,不推荐使用。
2:唯一索引。
分类名称上建立以为索引,每次插入商品分类,因为有唯一索引的存在,同样的商品分类数据库是禁止插入的。
3:分布式锁,如果应用是多台部署,推荐使用这种方式。分布式锁实现方式有很多种,比如使用乐观锁,使用redis去实现等等。
比如:使用分布式锁的伪码。

if(tryAcquireLock()){//如果获取锁
     try{
         if(!ifExist(classifyName)){
        保存到数据库
         }else{
         抛出异常或者其他处理
         }
     }finally{
         releaseLock();//释放锁
     }
     
}

你都会获取数据库数据了, 为什么不会用 where 条件?

如果你使用的是MySQL

INSERT INTO table_name (column1, column2, column3...)
VALUES (value1, value2, value3...)
ON DUPLICATE KEY UPDATE column2 = '男装';

官方文档

幂等、分布式锁

用关键字去数据库做模糊查询

在后台业务层的时候可以在添加前先判断是否已经存在“男装”这个分类,如果存在可以向前端传输“分类已存在”的信息,不做存储的动作

新手上路,请多包涵

数据库对应字段设置成unique最简单的实现

这个问题跟你的业务需求有关,如果需求要求同名分类只能创建一次,那么创建时,后端应该校验名称重复,前端给出业务提示。

可以使用ignore关键字呀

我觉得就是提交上来的东西,在数据库中搜索一遍,若找不到对应信息则创新新的,若找到的则报出异常

我想你应该是在web上添加数据的吧,一般我们都会在保存前进行校验,是否字段超长,是否重复,校验不通过不许保存,这个不需要到数据库层面去限制吧

字段使用unique约束

杀鸡焉用牛刀,unique字段类型就够了,插入的时候try catch就好了。别整那么麻烦

大部分时候,一行sql语句就搞定了,不需要再去做循环判断。即便是循环判断,也不会慢。

SELECT COUNT(*) FROM CATEGORRIES WHERE CATE_NAME="XX"; 

有做过注册吗,和那个原理一样的,把提交上来的名称在数据库查询一次,如果有就返回已添加就OK了,而且也不会慢。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题