Mysql 多个字段有唯一约束,写入时如果有重复的,如何知道哪个字段重复了?

2018-06-19 20:51:40 +08:00
 mostkia

RT。。我是通过 PHP 的 pdo 方式来获取 mysql 的返回值的。其实也没什么特殊的使用场景,就是想写一个注册功能,注册时让用户知道是哪个参数重复了(比如用户名、电话、邮箱)等这些不允许重复的字段。因为默认 mysql 只会返回 23000 错误码,并不会返回具体哪一个字段重复了。

考虑过先 select 多条件查找,发现了后返回给 php 提示用户,如果没发现有重复的内容则再使用 php 访问数据库写入,但这样就访问了数据库 2 次了,对性能不太友好,也不优雅。可能是我比较笨吧,想来想去没什么好办法。

原谅我只是个前端,对 sql 只会简单的读写。虚心请教一下,是否有 SQL 语法可以做到。

5155 次点击
所在节点    MySQL
23 条回复
thread2
2018-06-19 21:25:02 +08:00
用户填完“用户名、电话、邮箱”后,点击提交前,异步查询下,如果重复则提示,如果不重复则允许提交
mostkia
2018-06-19 21:45:12 +08:00
@thread2 恩,感谢你的回答,这也是一个思路,这样的话鼠标离开输入框,激活一个 ajax 事件,后台直接 select 当前输入框参数,就能知道哪个重复了,而后台使用唯一约束让前台进行这方面的过滤也不会存在安全问题。但性能方面应该和我的方法差不多吧,区别只是一个放在前台分散验证,而我的方法是上传后在后台集中验证。如果能一次访问是不是更好呢?
thread2
2018-06-19 21:47:15 +08:00
@mostkia 用户体验稍微好点
soho176
2018-06-19 22:57:19 +08:00
这不就是每个网站 最基本的注册功能吗
torbrowserbridge
2018-06-19 22:58:43 +08:00
获取并解析 mysql 的错误信息可实现。不过代价大了一点。
watzds
2018-06-19 23:00:52 +08:00
这有啥性能问题,注册量这么大就好了
letitbesqzr
2018-06-19 23:04:32 +08:00
我们项目是绝对不允许这些错误让 mysql 处理的,加唯一约束只是为了查询速度,事先用代码一个个的条件的判断好,有一步错误就返回,sql exception 属于是绝对意外的异常了。
947211232
2018-06-19 23:12:46 +08:00
应该有获取错误信息的函数方法的,否则真的不可思议了——根据错误信息设置你要返回前端的消息提示
mostkia
2018-06-19 23:25:48 +08:00
@watzds @letitbesqzr 恩,也就是说,让 mysql 一个一个条件的 select 这样查找,数据库时可行的是吗?如果这样的话,假设有 3 个字段需要判断(一般都至少有 3 个,邮箱,用户名,电话等),那至少要读写数据库 4 次( 3 次判断,没问题写入 1 次),高并发情况下我觉得也太多了。。当然注册一般没那么多并发,只是对于数据库这样使用还是心存疑惑,感觉这种方法好笨...哈哈,可能是我太多虑了吧。回头写一下吧,出问题再说。。感谢所有回答的朋友了。
msg7086
2018-06-20 01:02:43 +08:00
> 访问了数据库 2 次了,对性能不太友好

能不能说说访问两次对性能产生了多少影响?
msg7086
2018-06-20 01:11:31 +08:00
你看,数据库如果放在 SSD 上跑的话,1000qps 轻轻松松。假设其中有 50qps 分给注册,那你一秒钟能承受 25 个新用户注册,一天下来可以跑 100 万新注册用户,一个月就是 3 千万。

你要有了 3 千万新用户,不买个更好点的服务器么……

数据库优化的时候去关注这种带索引查询的性能意义很小。N+1 或者无索引查询优化才是应该关注的地方。
mostkia
2018-06-20 08:10:17 +08:00
@msg7086 我只是觉得可能有更好的办法,毕竟新手,有时候对自己想到的办法还是不太自信,结果似乎大家都是和我一样的做法,那我也没什么问题了,直接这样老老实实一步一步判断就行了。性能问题也是我想当然的,理解肯定不及各位常年使用数据库的大佬,还是谢谢各位解答的朋友了。能百忙之中回答我的问题就很感谢了。
q397064399
2018-06-20 09:02:18 +08:00
@mostkia #12 原谅我爆个粗口,, 扯什么鸡巴蛋的性能问题,MySQL 单表少于 5 亿,不要瞎几把谈性能问题,有空可以去研究其它的东西,内存回收 分布式系统,在代码层面上依赖数据库的报错机制本身就有问题,能在应用层干掉的 就要在应用层干掉,数据库是存储数据的,不是给你弄业务逻辑的,最烦那种写存储过程的,这种东西本来就应该是应用干的事情,职责要明确。
liuzhedash
2018-06-20 09:07:34 +08:00
@mostkia #9
胸弟,只要你正确加了索引就完全可行,乘以 10 都没问题。
hand515
2018-06-20 09:47:20 +08:00
怕网络次数多影响性能,那就用 union all 或者 OR 查询,一次提交
watzds
2018-06-20 09:48:02 +08:00
@mostkia 可以 where a =? OR b = ?
mostkia
2018-06-20 13:01:27 +08:00
@q397064399 额。。这位兄台可能对数据库有着很深的执念啊....又难道我是发了一个不可理喻的问题?我虽然只是个前端,对于数据库设计也并不熟悉。但追求更好的写法,避免自己一个人造轮子踩坑应该没什么原罪吧。。依我的看法,不要说 5 亿数据的表了,表的优化没事先做好,数据量能超过百万还能用就很看人品了,数据库的优化应该事先做好,而不是等到出性能问题了再改表,到时候可能数据多了也不好改的,所以就请教一下而已。。。
结贴了。结贴了,手动下沉。。一直挂在顶部,指不定等一下又碰到几个暴躁老哥呢。。 =_=
mostkia
2018-06-20 13:09:22 +08:00
@liuzhedash 好的,谢谢,已经按照楼上几位大佬的方案写好了控制后台了。。
msg7086
2018-06-20 15:45:59 +08:00
@mostkia 数据库优化其实不需要「事先」做好,而是应该跑起业务做压测以后再看哪些地方是性能瓶颈,然后再集中优化。你现在思考的问题属于过早优化,90%的场景下是浪费时间,剩下最多 10%碰巧被你优化上了。

记住这句话:

Premature optimization is the root of all evil.
mostkia
2018-06-20 16:14:58 +08:00
@msg7086 基础的应该做好准备吧,比如加索引什么的。我查资料的时候,看到翻车的太多太多了,都是一开始写的不好,然后到处问。。唉,也是看怕了。随便从浏览器历史记录里翻出来了几个案例...
https://bbs.csdn.net/topics/90035915
https://bbs.csdn.net/topics/392091851?page=1
他们的数据库 10W 条就炸了。所以按这些案例来讲,我仍旧认为初期那些基础的优化还是有些必要的。当然这不是这个帖子要讨论的主题。。这个帖子似乎讨论方向一直朝着奇怪的方向前进着。。掰都掰不回来,其实我已经在 12、18 楼接受了各位大佬的看法并已经明确放弃使用 sql 语法来写了,转而使用 php 直接做逻辑层,现在代码都写好了,但关于性能的讨论却没断过,哈哈,感觉自己是在钓鱼,也是 6 的不行。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/464210

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX