MySQL 一些让人容易忽视的知识点
一下都是MySQL在实际开发中,经常容易让人忽视的点,希望对您有帮助,帮您越过这些坑。
一:MySQL AND优先级大于OR
今天上班时在写一个业务的时候又发现了一个MySQL的问题:
我们的业务是这样的,用户可以修改自己的行数据,但这些行数据中有些数据是不能重复的,举个例子比如我们如果要开公司就要去工商局注册公司名,这时工商局可能就有一个《公司名》的表,这个表有一个主键id字段,然后有一个公司名称字段,公司英文名称字段,以及公司地点字段等等其他的数据字段,很明显这里的公司名以及公司英文名必须是唯一,因为不能有同名的公司。然后我们的业务提供给这个公司一个修改自己这条行数据的功能,比如你可以修改自己公司的中文名称或英文名称,或者地址等等,但是因为公司名是唯一的,所以在我们update数据前,我们先做了一个判断,看是否用户提交的数据中的公司名称以及英文是否已经存在,如果已经存在则告诉他,中文公司名或者是英文名已存在,请修改后重新提交。这里看似业务没有问题,但其实我们稍加测试后就发现了问题:
当用户在修改数据时只修改了中文名称或者英文名称时,此时就会有问题,比如用户想更改自己的英文公司名,因为用户提交的数据的中文名称还是原来的,所以我们在查询时发现这个中文名已经存在,所以会返回修改失败。
比如我们的判断语句是:select * from base_pop where name=$name or en-name=$en-name;只要这个查询返回结果集,就说明修改后的公司名已存在,修改失败。但是我们这里并没有考虑到局部修改的问题,甚至是如果你只想修改公司地址这种可以重复的信息,而没有更改时中英文名称时,这条SQL都会有返回集,所以都会返回修改不成功。
所以后来我们SQL更改为:select * from base_pop where name=$name or en-name=$en-name and id!=$id;这样修改后,基本上就没有问题了。已经可以完成大部分的业务需求,然而这里却引出了MySQL另外的一个问题,也就是我们今天的主题!
请看下图:
从上面这两张图中我们可以看到,当我们写:(A,B,C为三个表达式,如name=1这种),
where A and/or B and/or C; 这种where条件是有时候他的返回集和 where (A and/or B) and/or C; 的返回集一样,而有的时候又和where A and/or (B and/or C); 的返回集一样。这是什么情况呢,这里和我们设想的应该和C语言一样,自左向右运算的想法并不一样。到底MySQL自己的运算机制是自左向右还是自右向左的呢,怎么有的时候是向左有的时候是向右呢?
然而我们仔细查看后返现,会发现上面两种图有一个共性,不管是自作向右还是自右向左,我们发现返回结果集相同的SQL语句的括号总是括这包含and的语句,难道MySQL默认是先执行and语句的?
于是我们查看《MySQL手册》,得出以下结论:
我们发现,果然和我们的猜想一样,AND的操作符优先级就是比OR高,MySQL是用C语言写的,其实C语言在这里也是一样的,在C中&&的操作符优先级就是比||高,所以MySQL这里也是一样的,并不仅仅是简单的左结合性的问题。
这个在开发中也是比较常见的,有的时候会使用不至两个表达式。
二:MySQL中文乱序
今天上班,发现了一个有趣的东西,我们有一张表存的是国内运营商的资料,如id,name之类的。我们有一个业务,需要让用户选择自己对应的运营商,所以后台需要向前端返回运营商的名字以及id,name用来给用户展示,id用来记录用户选择了什么。如下图:
首先,标的结构如下:
表里的数据如下:
根据业务,我们写入了如下的SQL语句:
没想到返回的结果街竟然是这样的,为什么会是乱序的呢?为什么id和name都没有呈现出一定的顺序?
仔细看了看,我发现返回的结果集只有两个字段,这不仅让我想起了InnoDB的非聚集索引的结构,(可参看《数据库为什么要用B+数结构--MySQL索引结构的实现》),难道是因为这条SQL使用了name字段上的非聚集索引?所以主键相对无序,但是name字段也没有表现出顺序啊,但是如果我们的查询语句是这样写的,按理说应该就是使用的非聚集索引。此时我有想到哦了MyISAM的倒排索引的全文索引,的确,InnoDB的B+树索引在处理中文的时候是会有一点问题。于是我们做出如下测试:
我们先在表中插入几条测试数据,让这几条数据是英文的:
然后再执行之前的查询语句,
果不其然,这里我们新插入的a,b,c确实表现出的他应该有的顺序。
所以这里的中文应该是有序排列的,只不过没有对应拼音,这应该和中文字符的编码有关系,我们都知道gbk,utf-8等等,汉字在计算机中的存储并不是用拼音,所以没有展现出有序性,如果我们把这些汉字转换成2进制,应该就能看到他们是有序排列的。所以我们在开发中如果要有序,需要自己加上order by:
最后,我们再做一个测试,看看我们的猜想对不对,是否使用的非聚集索引:如下
首先,表中的索引有:
我们的SQL使用的索引是:
果不其然,使用的就是name字段的索引。
这个在实际开发中还是挺常见的,在InnoDB中当我们使用中文的时候,还是要多加注意。
MySQL 一些让人容易忽视的知识点的更多相关文章
- MySQL做练习时总结的一些知识点
MySQL做练习时总结的一些知识点 0:mysql有三种注释方法 上午插入记录的时候一直没有成功,郁闷不知道为什么.因为是很多条记录一起插入,中间一些不用的数据就用"--" ...
- 【Java基本功】很多人经常忽视的Java基础知识点
*.Java文件 问题:一个".java"源文件中是否可以包括多个类(不是内部类)?有什么限制? 答案:可以有多个类,但只能有一个public的类,并且public的类名必须与文件 ...
- 【千纸诗书】—— PHP/MySQL二手书网站后台开发之知识点记录
前言:使用PHP和MySQL开发后台管理系统的过程中,发现有一些通用的[套路小Tip],这里集中记录一下.结合工作中ing的后台业务,我逐渐体会到:除了技术知识外.能使用户体验好的“使用流程设计”积累 ...
- mysql运维必会的一些知识点整理
(1)基础笔试命令考察 1.开启MySQL服务 /etc/init.d/mysqld start service mysqld start systemctl start mysqld 2.检测端口是 ...
- mysql运维必会的一些知识点整理(转自民工哥)
(1)基础笔试命令考察 1.开启MySQL服务 /etc/init.d/mysqld start service mysqld start systemctl start mysqld 2.检测端口是 ...
- Python中容易忽视的知识点
今天坐在实验室,觉得有点无聊,想了下,很久没写博客了,就来写一点,正好遇到了一个有意思的小问题,分享给大家. 首先我们通过一个小的实验来看一下内容: 不管是 Python2 还是 Python3 环境 ...
- MySQL,必须掌握的6个知识点
本人免费整理了Java高级资料,涵盖了Java.Redis.MongoDB.MySQL.Zookeeper.Spring Cloud.Dubbo高并发分布式等教程,一共30G,需要自己领取.传送门:h ...
- mysql中查询语句中的一个知识点说明
1, 简单说明. select * from tb_name where 1[不为零即可];则会显示所有记录,select * from tb_name where 0;则不显示任何记录 假设数据库中 ...
- 第 10 章 MySQL Server 性能优化
前言: 本章主要通过针对MySQL Server(mysqld)相关实现机制的分析,得到一些相应的优化建议.主要涉及MySQL的安装以及相关参数设置的优化,但不包括mysqld之外的比如存储引擎相关的 ...
随机推荐
- C语言 · 约数个数
算法提高 约数个数 时间限制:1.0s 内存限制:512.0MB 输入一个正整数N,输出其约数的个数. 样例输入 12 样例输出 6 样例说明 12的约数包括:1,2,3,4,6,1 ...
- hdu 5443 The Water Problem(长春网络赛——暴力)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5443 The Water Problem Time Limit: 1500/1000 MS (Java ...
- 兔子--android中百度地图的开发
效果: API Key的申请地址:http://lbsyun.baidu.com/apiconsole/key 申请注意事项: 安全码:以下界面的SHA1 fingerprint值+;+包名 比如: ...
- jquery用ajax方式从后台获取json数据后如何将内容填充到下拉列表
对于问题从后台获取json数据,将内容填充到下拉列表,代码非常简单,具体过程请看下面代码. 需求:url:链接 par:ID sel:下拉列表选择器 function BuildS ...
- 【ArcGIS for Android】经纬度坐标、地图投影坐标、屏幕坐标互相转换
SpatialReference mSR4326 = SpatialReference.create(4326); SpatialReference mSR3857 = SpatialReferenc ...
- Android弹出一项权限请求
Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); startActivityForResult(ena ...
- Linux 下8种优秀的屏幕录制机
导读 屏幕录制机已经成为常见的和良好的实践来记录一个重要桌面会话,例如,你想玩一个难度较大的游戏,并且向记录是如何完成的,或者你打算创建一个视频教程,入门文章或指南,或任何其他活动和记录你的桌面会话, ...
- [JAVA]基于微信公众平台开放接口编写的sdk
最近在研究微信公众平台提供的公众服务号,以及提供的开放接口. 写了一个相对来说比较简单的基于java的微信sdk,目前实现的功能没有覆盖所有接口. 有兴趣的话,大家可以在这个基础上进行改进和完善,这样 ...
- 【黑金原创教程】【TimeQuest】【第五章】网表质量与外部模型
声明:本文为黑金动力社区(http://www.heijin.org)原创教程,如需转载请注明出处,谢谢! 黑金动力社区2013年原创教程连载计划: http://www.cnblogs.com/al ...
- 【BZOJ3416】Poi2013 Take-out 栈
[BZOJ3416]Poi2013 Take-out Description 小F喜欢玩一个消除游戏——take-out 保证k+1|n,保证输入数据有解这是一个单人游戏 游戏者的目标是消除初始时给定 ...