数据库允许空值(null),往往是悲剧的开始 (转)
数据库字段允许空值,会遇到一些问题,此处包含的一些知识点,和大家聊一聊。
数据准备:
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工具是一个好东西;
出处:https://mp.weixin.qq.com/s?__biz=MjM5ODYxMDA5OQ==&mid=2651962495&idx=1&sn=74e9e0dc9d03a872fd5bce5769f6c22a&chksm=bd2d09a38a5a80b50da3b67c03da8417426cbb201427557959fa91e9094a848a14e0db214370&scene=21#wechat_redirect
数据库允许空值(null),往往是悲剧的开始 (转)的更多相关文章
- 数据库允许空值(null),往往是悲剧的开始(1分钟系列)
数据库字段允许空值,会遇到一些问题,此处包含的一些知识点,和大家聊一聊. 数据准备: 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 ...
随机推荐
- PHP培训教程 php几个不起眼儿的小技巧
说是不起眼儿的小技巧,其实应该说是不常用的常规应用吧.很多事情就是这样,知道是一马事儿,会用是一马事儿,精习又是另外一马事儿.而成为高手更是需要扎实的基本功. str_repeat 重复输出字符串就靠 ...
- ELK结合logback
之前ELK的安装可以查看前面一篇博客 下面是我的logback的配置文件,通过logback的appender直接导入logstash <?xml version="1.0" ...
- memset设置最大值
初始化为最大值 memset(mp,0x7f,sizeof(mp));
- Ubuntu16.04 同时连接无线网络和以太网端口
背景: 激光雷达VLP16通过以太网线连接电脑.在本博客所述的设置之前,一旦连接以太网线,本机(dell笔记本)的无线网络立即断开,即无法同时连接无线网络和以太网端口. 问题查找: 命令行 $ ip ...
- 当在本地磁盘服务(Windows)中无法删除指定分区时的解决方案
有时候,我们在使用Windows管理磁盘分区时,可能会出现部分分区无法删除的情况,也就是说右键快捷菜单中没有删除卷的操作项. 此时,我们可以按照如下的步骤进行操作即可完成: Step 1: 以管理员身 ...
- windows下开启远程连接Mysql
使用“Ctrl + R”组合键快速打开cmd窗口,并输入“cmd”命令,打开cmd窗口. 使用“mysql -uroot -proot”命令可以连接到本地的mysql服务. 使用“use mysq ...
- easyui 功能列传递一行数据
DeleteRow(' + JSON.stringify(row).replace(/"/g, '"') + ',0,' + Pindex + ',' + index + ')
- es之索引的别名操作
1:增加别名 为索引school添加一个别名alias1: 1.1:创建索引 PUT student{ "settings": {"number_of_shards&qu ...
- 突破css选择器的局限,实现一个css地址选择器?
首先看一个效果,注意地址栏的变化 然后思考一下,用css如何实现? css选择器的局限 选择器是css中的一大特色,用于选择需要添加样式的元素. 选择器的种类有很多,比如 元素选择器 p {color ...
- js 放回上一页
window.history.go(-1);//返回上一页不刷新 window.location.href = document.referrer;//返回上一页并刷新