关于数据库字段不允许重复的问题

鸣鸣Amadues 2015-09-22 04:15:03
假设现在有一张用户表,字段uuid是主键,另外有邮箱和手机字段,不是主键,但是也不能重复。
如果我在数据库里把邮箱和手机都设置为unique,经过测试,必须是两个字段都相同时,系统才认为是重复的。
也就是手机和邮箱假如只有一个重复,也是可以通过unique验证的。

假如在后台代码这里写逻辑判断是否重复,有可能发生两笔操作(即两个线程)同时在运行,无法检测互相之间是否有重复,这样也可以通过验证提交到数据库。

请问还有什么其他办法吗?
...全文
13453 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
y2501104129 2019-07-24
  • 打赏
  • 举报
回复
[c
krisOtk 2017-03-28
  • 打赏
  • 举报
回复
谢了 ..........
zhuangqingch 2015-09-28
  • 打赏
  • 举报
回复
引用 3 楼 Raffin 的回复:
[quote=引用 2 楼 zhuangqingch 的回复:] 对于楼主的描述:“邮箱和手机都设置为unique,经过测试,必须是两个字段都相同时,系统才认为是重复的”,这个可能是你设置错了。你应该是用了联合唯一约束,所以才会这样。如果分别当独给邮箱和手机添加唯一约束,只要其中一个重复,都会插入失败的。 另外这种唯一操作,建议用程序来处理。但要控制好并发问题。主要思路为: 1、在项目使用缓存,如HashSet,将已被使用的过的邮箱和手机存储其中。并注意加锁。 2、当有新的数据在存储时,到缓存中判断是否已存在手机号或邮箱号,存在的话,则说明已经重复。 3、当服务器重启时。在项目启动阶段从对应的表中,将已有的所有手机号和邮箱号添加入缓存中。 当然以上这种方案也要结合你当前项目的数据量来考虑要不要这样处理。就这些吧。楼主看下有没有疑问。
"应该是用了联合唯一约束" 我用的是MySQL,创建表的时候设置unique,按照你的意思,似乎可以另外设置? 用缓存的话你要考虑缓存和数据库同步的问题,还有万一事务失败,你也要从缓存里剔除掉你刚刚存入缓存但是还没有提交到数据库的那些数据,这样你还要考虑事务方面的回滚,会把问题复杂化的。总之,缓存为增加程序复杂度和系统开销,我感觉如果可以在数据库层面解决就不要在程序里写。[/quote] 唯一约束,可以给单独一个字段设置,即表示在多条记录中,该字段的值不可出现重复。也可以设置多个字段组合起来要求唯一,即在多条记录中,不可出现多个字段值同时重复。设置方式如下: 创建表时设置:

CREATE TABLE `t_user` (
      `Id` int(11) NOT NULL AUTO_INCREMENT,  -- 自增
      `name` varchar(50) NOT NULL unique,  -- 唯一性约束
      `phone` varchar(18) NOT NULL,  
      `mail` varchar(18) NOT NULL,  
       UNIQUE KEY (`phone`,`mail`), -- 联合唯一性约束
       PRIMARY KEY (`Id`)
) ENGINE=InnoDB AUTO_INCREMENT=1018 DEFAULT CHARSET=gbk;
创建表之后设置:

ALTER TABLE `t_user` ADD UNIQUE KEY(`name`);  -- 唯一约束
ALTER TABLE `t_user` ADD UNIQUE KEY(`phone`,`mail`); -- 联合唯一约束
另外,对于缓存的,说下楼主说的系统复杂度和开销问题。对于系统复杂度来说,无非是多了缓存这一层。个人感觉没什么复杂的。对于系统开销来说,主要是看你的用户量或者说数据量。现在的硬件条件一般都支撑得起来。 至于数据库同步问题更不是问题。如果同步要求高的,可以先使用同步方式执行数据库插入。插入成功(无异常)后再执行缓存保存操作。如果同步要求不高的。可以采用异步方式执行数据库插入。再保存缓存。保存缓存后,异步插入数据库操作可能还没执行完,即可能出现插入异常后缓存已保存的情况。这时可以写个数据库操作回调。当失败时调用回调将对应缓存删除。 其实系统要采取什么方案,关键还是看你系统的业务需求。如果你的系统对响应要求比较高时,你所有查询操作都直接同步操作数据库的方式肯定是不可取的。而缓存这方面也主要是想解决数据查询的效率问题,是否需要用取决于你系统的业务需求。
鸣鸣Amadues 2015-09-26
  • 打赏
  • 举报
回复
引用 2 楼 zhuangqingch 的回复:
对于楼主的描述:“邮箱和手机都设置为unique,经过测试,必须是两个字段都相同时,系统才认为是重复的”,这个可能是你设置错了。你应该是用了联合唯一约束,所以才会这样。如果分别当独给邮箱和手机添加唯一约束,只要其中一个重复,都会插入失败的。 另外这种唯一操作,建议用程序来处理。但要控制好并发问题。主要思路为: 1、在项目使用缓存,如HashSet,将已被使用的过的邮箱和手机存储其中。并注意加锁。 2、当有新的数据在存储时,到缓存中判断是否已存在手机号或邮箱号,存在的话,则说明已经重复。 3、当服务器重启时。在项目启动阶段从对应的表中,将已有的所有手机号和邮箱号添加入缓存中。 当然以上这种方案也要结合你当前项目的数据量来考虑要不要这样处理。就这些吧。楼主看下有没有疑问。
"应该是用了联合唯一约束" 我用的是MySQL,创建表的时候设置unique,按照你的意思,似乎可以另外设置? 用缓存的话你要考虑缓存和数据库同步的问题,还有万一事务失败,你也要从缓存里剔除掉你刚刚存入缓存但是还没有提交到数据库的那些数据,这样你还要考虑事务方面的回滚,会把问题复杂化的。总之,缓存为增加程序复杂度和系统开销,我感觉如果可以在数据库层面解决就不要在程序里写。
zhuangqingch 2015-09-22
  • 打赏
  • 举报
回复
对于楼主的描述:“邮箱和手机都设置为unique,经过测试,必须是两个字段都相同时,系统才认为是重复的”,这个可能是你设置错了。你应该是用了联合唯一约束,所以才会这样。如果分别当独给邮箱和手机添加唯一约束,只要其中一个重复,都会插入失败的。 另外这种唯一操作,建议用程序来处理。但要控制好并发问题。主要思路为: 1、在项目使用缓存,如HashSet,将已被使用的过的邮箱和手机存储其中。并注意加锁。 2、当有新的数据在存储时,到缓存中判断是否已存在手机号或邮箱号,存在的话,则说明已经重复。 3、当服务器重启时。在项目启动阶段从对应的表中,将已有的所有手机号和邮箱号添加入缓存中。 当然以上这种方案也要结合你当前项目的数据量来考虑要不要这样处理。就这些吧。楼主看下有没有疑问。
  • 打赏
  • 举报
回复
建议:可以用邮箱跟手机做联合主键,uuid做唯一

67,512

社区成员

发帖
与我相关
我的任务
社区描述
J2EE只是Java企业应用。我们需要一个跨J2SE/WEB/EJB的微容器,保护我们的业务核心组件(中间件),以延续它的生命力,而不是依赖J2SE/J2EE版本。
社区管理员
  • Java EE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧