正式开始之前,我们先来看下 MySQL 服务器的配置和版本号信息,如所示:

select version();
-- 版本为
8.0.22

“兵马未动粮草先行”,看完了相关的配置之后,我们先来创建一张测试表和一些测试数据。

-- 如果存在 person 表先删除
DROP TABLE IF EXISTS person; -- 创建 person 表,其中 username 字段可为空,并为其设置普通索引
CREATE TABLE person (
id INT PRIMARY KEY auto_increment,
name VARCHAR(20),
mobile VARCHAR(13),
index(name)
) ENGINE='innodb'; -- person 表添加测试数据
insert into person(name,mobile) values('Java','13333333330'),
('MySQL','13333333331'),
('Redis','13333333332'),
('Kafka','13333333333'),
('Spring','13333333334'),
('MyBatis','13333333335'),
('RabbitMQ','13333333336'),
('Golang','13333333337'),
(NULL,'13333333338'),
(NULL,'13333333339'); select * from person;

构建的测试数据,如下图所示:

(图1)

有了数据之后,我们就来看当列中存在 NULL 值时,究竟会导致哪些问题?

1、count 数据丢失

当某列存在 NULL 值时,再使用 count 查询该列,就会出现数据“丢失”问题,如下 SQL 所示:

select count(*),count(name) from person;

查询执行结果如下:

(图2)

从上述结果可以看出,当使用的是 count(name) 查询时,就丢失了两条值为 NULL 的数据丢失。

解决方案 如果某列存在 NULL 值时,就是用 count(*) 进行数据统计。

注意 不要使用 count(常量)

阿里巴巴《Java开发手册》强制规定:不要使用 count(列名) 或 count(常量) 来替代 count(),count() 是 SQL92 定义的标准统计行数的语法,
跟数据库无关,跟 NULL 和非 NULL 无关。

说明:count(*) 会统计值为 NULL 的行,而 count(列名) 不会统计此列为 NULL 值的行。

2、distinct 数据丢失

当使用 count(distinct col1, col2) 查询时,如果其中一列为 NULL,那么即使另一列有不同的值,那么查询的结果也会将数据丢失,如下 SQL 所示:

select count(distinct name,mobile) from person;

查询执行结果如下:

(图3)

数据库的原始数据如下:

(图4)

从上述结果可以看出手机号一列的 10 条数据都是不同的,但查询的结果却为 8。

3、select 数据丢失

如果某列存在 NULL 值时,如果执行非等于查询(<>/!=)会导致为 NULL 值的结果丢失。比如以下这个数据:

(图5)

我需要查询除 name 等于“Java”以外的所有数据,预期返回的结果是 id 从 2 到 10 的数据,但当执行以下查询时:

select * from person where name<>'Java' order by id;
-- 或
select * from person where name!='Java' order by id;

查询结果均为以下内容:

(图6)

可以看出为 NULL 的两条数据凭空消失了,这个结果并不符合我们的正常预期。

解决方案

要解决以上的问题,只需要在查询结果中拼加上为 NULL 值的结果即可,执行 SQL 如下:

select * from person where name<>'Java' or isnull(name) order by id;

最终的执行结果如下:

(tu7)

4、导致空指针异常

如果某列存在 NULL 值时,可能会导致 sum(column) 的返回结果为 NULL 而非 0,如果 sum 查询的结果为 NULL 就可以能会导致程序执行时空指针异常(NPE),我们来演示一下这个问题。

首先,我们先构建一张表和一些测试数据:

-- 如果存在 goods 表先删除
DROP TABLE IF EXISTS goods; -- 创建 goods 表
CREATE TABLE goods (
id INT PRIMARY KEY auto_increment,
num int
) ENGINE='innodb'; -- goods 表添加测试数据
insert into goods(num) values(3),(6),(6),(NULL); select * from goods;

表中原始数据如下:

(图8)

接下来我们使用 sum 查询,执行以下 SQL:

select sum(num) from goods where id>3;

查询执行结果如下:

(图9)

当查询的结果为 NULL 而非 0 时,就可以能导致空指针异常。

解决空指针异常

可以使用以下方式来避免空指针异常:

select ifnull(sum(num), 0) from goods where id>4;

参考

1、公众号 java中文社群 的一篇文章。 非常感谢!

【网络好文】---MySQL为Null导致的四大坑的更多相关文章

  1. Mysql高手系列 - 第13篇:细说NULL导致的神坑,让人防不胜防

    这是Mysql系列第13篇. 环境:mysql5.7.25,cmd命令中进行演示. 当数据的值为NULL的时候,可能出现各种意想不到的效果,让人防不胜防,我们来看看NULL导致的各种神坑,如何避免? ...

  2. MySQL 不用 Null 的理由

    Null 貌似在哪里都是个头疼的问题,比如 Java 里让人头疼的 NullPointerException,为了避免猝不及防的空指针异常,千百年来程序猿们不得不在代码里小心翼翼的各种 if 判断,麻 ...

  3. mysql 将null转代为0

    mysql 将null转代为0 分类: Mysql2012-12-15 11:56 6447人阅读 评论(1) 收藏 举报 1.如果为空返回0 select ifnull(null,0) 2.如果为空 ...

  4. Mysql的NULL和Empty String

    本文基于Mysql5.7版本的参考资料: https://dev.mysql.com/doc/refman/5.7/en/working-with-null.html https://dev.mysq ...

  5. MySQL字符集不一致导致性能下降25%,你敢信?

    故事是这样的: 我在对MySQL进行性能测试时,发现CPU使用率接近100%,其中80%us, 16%sys,3%wa,iostat发现磁盘iops2000以下,avgqu-sz不超过3,%util最 ...

  6. Mysql is null 索引

    看到很多网上谈优化mysql的文章,发现很多在谈到mysql的null是不走索引的,在此我觉得很有必要纠正下这类结论.mysql is null是有索引的,而且是很高效的,(版本:mysql5.5)表 ...

  7. MySQL编码不一致导致查询结果为空

    升级数据库后(5.1到8.0),发现一个奇怪的问题,某些页面在升级前可以正常查询,但升级后什么也查不出来了,有时候还会查出错误的结果.经过一整天的排查,终于发现由两个原因导致,现记录如下. 第一是数据 ...

  8. MySQL中NULL与空字符串

    一些刚刚接触MySQL的孩子,经常会错误的认为NULL与空字符串’  ’是相同的.这看似是一件不重要的事情,但是在MySQL中,这两者是完全不同的.NULL是指没有值,而”则表示值是存在的,只不过是个 ...

  9. 《MySQL》一次MySQL慢查询导致的故障

    本文转载自 http://www.jb51.net/article/70955.htm 我们知道分析MySQL语句查询性能的方法除了使用EXPLAIN 输出执行计划,还可以让MySQL记录下查询超过指 ...

随机推荐

  1. Apache AB(1) - 快速使用

    前言 Apache AB的优缺点 十分快捷.简单 只适用HTTP协议 该工具更加适用于单接口性能压测 参数化实现麻烦:被测接口没有太多参数化 不支持场景化,不能将上下文串联起来 适用于快速开发小的场景 ...

  2. Linux系列(39) - nohup

    nohup 英文全称 no hang up(不挂起),用于在系统后台不挂断地运行命令,退出终端不会影响程序的运行. nohup 命令,在默认情况下(非重定向时),会输出一个名叫 nohup.out 的 ...

  3. 第一次接触linux系统的你,必须要知道的概念

    linux系统一切皆为文件 linux系统一个多用户系统 没有消息就是好消息 linux系统目录结构 Linux文件系统采用带链接的树形目录结构,即只有一个根目录(通常用"/"表示 ...

  4. cannot connect to chrome at 127.0.0.1:9222

    window10系统,先cmd打开chrome, chrome --remote-debugging-port=9222 执行脚本 from selenium import webdriver fro ...

  5. dubbo微服务架构

    架构 节点角色说明 调用关系说明 服务容器负责启动,加载,运行服务提供者. 服务提供者在启动时,向注册中心注册自己提供的服务. 服务消费者在启动时,向注册中心订阅自己所需的服务. 注册中心返回服务提供 ...

  6. Linux C语言 取得MTU (最大传输单元)

    参照这篇博客: http://www.geekpage.jp/programming/linux-network/book/04/4-21.php * 查看主机当前网卡,哪块在使用. ifconfig ...

  7. PyCharm取消波浪线

    步骤:settings->Editor->Color Scheme->General->(右侧)Errors and Warnings->Weak Warning-> ...

  8. UE4技术总结——委托

    UE4技术总结--委托 目录 UE4技术总结--委托 一.定义 二.用法 2.1 声明与调用委托 2.1.1 单播委托 2.1.1.a 声明 2.1.1.b 绑定 2.1.1.c 执行委托 2.1.1 ...

  9. dg create datafile auto failed 排除处理

    1.Environment:11.2.0.4 dg 2.Symptoms:告警描述:Wed Sep 22 14:29:15 2021Errors in file /data/app/oracle/di ...

  10. PHP审计之PHP反序列化漏洞

    PHP审计之PHP反序列化漏洞 前言 一直不懂,PHP反序列化感觉上比Java的反序列化难上不少.但归根结底还是serialize和unserialize中的一些问题. 在此不做多的介绍. 魔术方法 ...