数据库允许空值(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 ...
随机推荐
- node中controller的get和post方法获取参数
1.get: const body = ctx.query; // get请求 2.post: const body = ctx.request.body; // post请求
- 策略模式------《Head First 设计模式》
第一章---策略模式 xzmxddx 学习方式:书籍<Head First 设计模式>,这本书通俗易懂,所有知识点全部取自本书. 面向对象设计原则 封装变化 多用组合,少用继承 针对接口编 ...
- SQL 行转列(列的值不规则的数目)
--创建一个临时表用来存储数据 create table #tmp_SNValue_Table (FieldName nvarchar(20), [Value] nvarchar(max)) inse ...
- CentOS查看进程端口号以及kill操作
查看端口: 使用 netstat -anp | grep 8090即:netstat –apn | grep 8090 查看进程:1.ps 命令用于查看当前正在运行的进程,grep 是 ...
- Spring Boot教程(十四)快速入门
快速入门 本章主要目标完成Spring Boot基础项目的构建,并且实现一个简单的Http请求处理,通过这个例子对Spring Boot有一个初步的了解,并体验其结构简单.开发快速的特性. 系统要求: ...
- JAVA单例模式的实现伪代码
什么是单例?:其定义是单例对象的类只能允许一个实例存在 单例的实现基本原理:1.将该类的构造方法定义为私有访问,不对外暴露从而使其他类不能实例化该类对象,只能通过该类的静态方法得到该类的唯一实例 2. ...
- mysql 数据增删改的总结
一.在MySQL管理软件中,可以通过SQL语句中的DML语言来实现数据的操作,包括 1.使用INSERT实现数据的插入2.UPDATE实现数据的更新3.使用DELETE实现数据的删除4.使用SELEC ...
- spring boot: Whitelabel Error Page的解决方案
http://blog.csdn.net/u014788227/article/details/53670112
- MySQL中concat以及group_concat的使用
摘自:https://www.jianshu.com/p/43cb4c5d33c1 说明: 本文中使用的例子均在下面的数据库表tt2下执行: 一.concat()函数 1.功能:将多个字符串连接成一个 ...
- always_populate_raw_post_data
Deprecated: Automatically populating $HTTP_RAW_POST_DATA is deprecated and will be removed in a futu ...