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之外的比如存储引擎相关的 ...
随机推荐
- SVN文件排除
背景:原来SVN库人事2.0在24.42server上,后来server改革,把库迁移到了24.248server上. 原来24.42上的库,在update或commit后文件总是绿色的.看着心里特别 ...
- C基础之移位操作
因为左移操作不会导致符号位出现缺位,所以不考虑符号位,低位补0即可:右移操作会涉及到符号位出现缺位的问题,所以在有符号数的右移操作时要考虑符号位怎么补的问题. 左移操作(<<)对于无符号数 ...
- RSYNC在zabbix中的检查
RSYNC在zabbix中的检查 作者:高波 归档:学习笔记 2017/08/21 快捷键: Ctrl + 1 标题1 Ctrl + 2 标题2 Ctrl + 3 标题3 Ctr ...
- c配置库ccl使用小结
配置文件为key=value键值对形式 下载与安装 库文件下载:ccl-0.1.1.tar.gz 安装: tar -zxvf ccl-0.1.1.tar.gz cd ccl-0.1.1 ./con ...
- 关于Nvelocity的主要语法和一些代码示例
context.Response.ContentType = "text/html"; VelocityEngine vltEngine = new VelocityEngine( ...
- C++ 匿名对象的生命周期
//匿名对象的生命周期 #define _CRT_SECURE_NO_WARNINGS #include<iostream> using namespace std; class Poin ...
- 如果想要跨平台,在file类下有separtor(),返回锁出平台的文件分隔符
对于命令:File f2=new file(“d:\\abc\\789\\1.txt”) 这个命令不具备跨平台性,因为不同的OS的文件系统很不相同. 如果想要跨平台,在file类下有separtor( ...
- Unity获取文件夹下指定类型的文件数量
有个文件夹里面有很多的图片,都是.png格式的,要是一个一个的拖到脚本上觉得很麻烦,就写了一个遍历添加的cars,变量是List<Sprite> 代码如下: using UnityEngi ...
- 在visual studio中运行C++心得
1.在visual studio中建立C++项目 (1)新建->项目->空项目 C++ (2)右击项目->添加->新建项->C++文件(.app) (3编写C++文件 ...
- ArcGIS 相同要素类的多Shp文件或多要素合并