数据库允许空值(null),往往是悲剧的开始(1分钟系列)
数据库字段允许空值,会遇到一些问题,此处包含的一些知识点,和大家聊一聊。
数据准备:
create table user (
id int,
name varchar(20),
index(id)
)engine=innodb;
insert into user values(1,'shenjian');
insert into user values(2,'zhangsan');
insert into user values(3,'lisi');
说明:
id为索引,非唯一(non unique),允许空(null)。
知识点1(热身):负向查询不能命中索引,会导致全表扫描。

explain select * from user where id!=1;
索引字段id上的不等于查询,如上图所示:
(1)type=ALL,全表扫描;
(2)rows=3,全表只有3行;
知识点2(划重点):允许空值,不等于(!=)查询,可能导致不符合预期的结果。

insert into user(name) values('wangwu');
先构造一条id为NULL的数据,可以看到共有4条记录。
select * from user where id!=1;
再次执行不等于查询。
你猜结果集有几条记录(共4条,不等于排除1条)?
答错了!
结果集只有2条记录,空值记录记录并未出现在结果集里。

select * from user where id!=1 or id is null;
如果想到得到符合预期的结果集,必须加上一个or条件。
画外音:恶心不恶心,这个大坑你踩过没有?
知识点3(附加):某些or条件,又可能导致全表扫描,此时应该优化为union。

explain select * from user where id=1;
索引字段id上的等值查询,能命中索引,如上图所示:
(1)type=ref,走非唯一索引;
(2)rows=1,预估扫描1行;

explain select * from user where id is null;
索引字段id上的null查询,也能命中索引,如上图所示:
(1)type=ref,走非唯一索引;
(2)rows=1,预估扫描1行;

explain select * from user where id=1 or id is null;
如果放到一个SQL语句里用or查询,则会全表扫描,如上图所示:
(1)type=ALL,全表扫描;
(2)rows=4,全表只有4行;

explain select * from user where id=1
union
select * from user where id is null;
此时应该优化为union查询,又能够命中索引了,如上图所示:
(1)type=ref,走非唯一索引;
(2)rows=1,预估扫描1行;
画外音:第三行临时表的ALL,是两次结果集的合并。
总结
(1)负向比较(例如:!=)会引发全表扫描;
(2)如果允许空值,不等于(!=)的查询,不会将空值行(row)包含进来,此时的结果集往往是不符合预期的,此时往往要加上一个or条件,把空值(is null)结果包含进来;
(3)or可能会导致全表扫描,此时可以优化为union查询;
(4)建表时加上默认(default)值,这样能避免空值的坑;
(5)explain工具是一个好东西;
希望大家有收获!
画外音:本文测试于MySQL5.6。
数据库允许空值(null),往往是悲剧的开始(1分钟系列)的更多相关文章
- 数据库允许空值(null),往往是悲剧的开始 (转)
数据库字段允许空值,会遇到一些问题,此处包含的一些知识点,和大家聊一聊. 数据准备: create table user ( id int, name varchar(20), index(id) ) ...
- 数据库允许空值(null),往往是悲剧的开始
原文: 58沈剑 架构师之路 https://mp.weixin.qq.com/s/XRSPITgWWK-2Ee-cSIqw1w 数据库字段允许空值,会遇到一些问题,此处包含的一些知识点,和大 ...
- SQL Serve数据库排序空值null始终前置的方法
[转:http://blog.knowsky.com/233986.htm] [sqlserver]: sqlserver 认为 null 最小. 升序排列:null 值默认排在最前. 要想排后面,则 ...
- sqlserver、oracle数据库排序空值null问题解决办法
转:https://www.cnblogs.com/pacer/archive/2010/03/02/1676371.html [sqlserver]: sqlserver 认为 null 最小. 升 ...
- SQL学习之空值(Null)检索
在创建表表,我们可以指定其中的列包不包含值,在一列不包含值时,我们可以称其包含空值null. 确定值是否为null,不能简单的检查是否=null.select语句有一个特殊的where子句,可用来检查 ...
- 浅谈MDX处理空值NULL及格式化结果
MDX查询结果中往往会含有"NULL"值,这是某维度下对应的的量值不存在导致的,为了让报表呈现更好的效果,在有些情况下,需要将"NULL"的切片值置换成0,这些 ...
- 数据库中的null问题
在数据库中有些列的值可以为null,这一篇,我们围绕数据库中的null来讲述. 1. null与 “”.0的区别 数据库中的null表示——不知道,“”——一个空字符串,0则是一个数值. 所以n ...
- MDX Cookbook 03 - MDX 查询中负数,零和空值 NULL 的格式化处理
FORMAT_STRING 属性在处理计算成员(通常是度量值成员)的时候会经常使用到,比如指定标准 Standard, 货币 Currency 或者 Percent 百分比格式.除此之外,还可以自定义 ...
- C#向Sql数据库插入空值的控制
string name = textBox1.Text; int age = Convert.ToInt32(textBox2.Text.Trim()); ? null : (int?)Convert ...
随机推荐
- discriminator 鉴别器
在特定的情况下使用不同的pojo进行关联, 鉴别器元素就是被设计来处理这个情况的.鉴别器非常容易理解,因为它的表现很像 Java 语言中的 switch 语句:discriminator 标签常用的两 ...
- MySQL学习-MySQL内置功能_事务操作
1.事务详解 1.1 事务的概念 MySQL 事务主要用于处理操作量大,复杂度高的数据.比如说,在人员管理系统中,你删除一个人员,你即需要删除人员的基本资料,也要删除和该人员相关的信息,如信箱,文章等 ...
- 【原创】asp.net webdiyer AspNetPager控件分页码改变时,序号列从新从1开始问题的解决
长话短说,首先看repeater 配合 webdiyer AspNetPager使用时webdiyer AspNetPager属性设置代码. <webdiyer:AspNetPager ID ...
- SpringMVC 零配置 无web.xml
对SpringMVC启动流程的讲解 https://www.cnblogs.com/beiyan/p/5942741.html 与SpringMVC的整合 https://hanqunfeng.ite ...
- 使用SecureCRT连接虚拟机中Linux系统 和 虚拟机网络配置
使用SecureCRT连接步骤:1.首先打开虚拟机,点击左上角的编辑,再点击虚拟网络编辑器(已经进行虚拟网络编辑的忽略此步骤,直接进行第二步) 点击VMnet8网络,点击更改设置,此步骤需要管理员权限 ...
- django form组件 cookies,session
django form组件 渲染标签 就是组件里面的字段在前端展示叫做渲染标签 校验数据 用户输入的数据提交给后端组件叫做校验数据 forms组件中定义的字段都是必须传值的(required=Tr ...
- dom和bom之间的区别
BOM的核心是windows,表示的是一个浏览器的实例,在网页中自定义的任何一个对象.变量和函数,都以windows作为其全局对象 DOM是针对HTML和XML文档的一个API bom:(Browse ...
- 使用javascript和jquery获取类方法
1.本质区别 jquery是一个javascript库.jquery是一个基于javascript语言的框架,本质上就是javascript. 2.代码编写的差异 jquery大大简化了JavaScr ...
- 自定义事件 Event 、CustomEvent的使用
通过Event和dispathEvents触发自定义事件 <span id="btn">获取</span> <script> var event ...
- jeesite直接登录——真实破解
前台 后台 @RequiresPermissions("alarm:alarm:view")一定要注释 —————————————————————————————————————— ...