mysql对null值如何理解(MySQL为Null会导致5个问题个个致命)
mysql对null值如何理解
MySQL为Null会导致5个问题个个致命目录
- 1.count 数据丢失
- 解决方案
- 2.distinct 数据丢失
- 3.select 数据丢失
- 解决方案
- 4.导致空指针异常
- 5.增加了查询难度
- 总结
正式开始之前,我们先来看下 mysql 服务器的配置和版本号信息,如下图所示:
“兵马未动粮草先行”,看完了相关的配置之后,我们先来创建一张测试表和一些测试数据。
|
-- 如果存在 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; |
构建的测试数据,如下图所示:
有了数据之后,我们就来看当列中存在 null
值时,究竟会导致哪些问题?
1.count 数据丢失
当某列存在 null
值时,再使用 co
unt
查询该列,就会出现数据“丢失”问题,如下 sql 所示:
|
select count (*), count ( name ) from person; |
查询执行结果如下:
从上述结果可以看出,当使用的是 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; |
查询执行结果如下:
数据库的原始数据如下:
从上述结果可以看出手机号一列的 10 条数据都是不同的,但查询的结果却为 8。
3.select 数据丢失
如果某列存在 null
值时,如果执行非等于查询(<>/!=)会导致为 null
值的结果丢失。比如以下这个数据:
我需要查询除 name 等于“java”以外的所有数据,预期返回的结果是 id 从 2 到 10 的数据,但当执行以下查询时:
|
select * from person where name <> 'java' order by id; -- 或 select * from person where name != 'java' order by id; |
查询结果均为以下内容:
可以看出为 null
的两条数据凭空消失了,这个结果并不符合我们的正常预期。
解决方案
要解决以上的问题,只需要在查询结果中拼加上为 null
值的结果即可,执行 sql 如下:
|
select * from person where name <> 'java' or isnull ( name ) order by id; |
最终的执行结果如下:
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; |
表中原始数据如下:
接下来我们使用 sum
查询,执行以下 sql:
|
select sum (num) from goods where id>4; |
查询执行结果如下:
当查询的结果为 null
而非 0 时,就可以能导致空指针异常。
解决空指针异常
可以使用以下方式来避免空指针异常:
|
select ifnull( sum (num), 0) from goods where id>4; |
查询执行结果如下:
5.增加了查询难度
当某列值中有 null
值时,在进行 null
值或者非 null
值的查询难度就增加了。
所谓的查询难度增加指的是当进行 null
值查询时,必须使用 null
值匹配的查询方法,比如 is null
或者 is not null
又或者是 ifnull(cloumn)
这样的表达式进行查询,而传统的 =、!=、<>...
等这些表达式就不能使用了,这就增加了查询的难度,尤其是对小白程序员来说,接下来我们来演示一下这些问题。
还是以 person
表为例,它的原始数据如下:
错误用法 1:
|
select * from person where name <> null ; |
执行结果为空,并没有查询到任何数据,如下图所示:
错误用法 2:
|
select * from person where name != null ; |
执行结果也为空,没有查询到任何数据,如下图所示:
正确用法 1:
|
select * from person where name is not null ; |
执行结果如下:
正确用法 2:
|
select * from person where ! isnull ( name ); |
执行结果如下:
推荐用法
阿里巴巴《java开发手册》推荐我们使用 isnull(cloumn)
来判断 null
值,原因是在 sql 语句中,如果在 null 前换行,影响可读性;而 isnull(column)
是一个整体,简洁易懂。从性能数据上分析 isnull(column)
执行效率也更快一些。
扩展知识:null 不会影响索引
细心的朋友可能发现了,我在创建 person
表的 name
字段时,为其创建了一个普通索引,如下图所示:
然后我们用 explain
来分析查询计划,看当 name
中有 null
值时是否会影响索引的选择。
explain
的执行结果如下图所示:
从上述结果可以看出,即使 name
中有 null
值也不会影响 mysql 使用索引进行查询。
总结
本文我们讲了当某列为 null
时可能会导致的 5 种问题:丢失查询结果、导致空指针异常和增加了查询的难度。因此在最后提倡大家在创建表的时候尽量设置 is not null
的约束,如果某列确实没有值,可以设置空值('')或 0 作为其默认值。
到此这篇关于mysql为null会导致5个问题(个个致命)的文章就介绍到这了,更多相关mysql为null导致问题内容请搜索开心学习网以前的文章或继续浏览下面的相关文章希望大家以后多多支持开心学习网!
原文链接:https://blog.csdn.net/weixin_44742132/article/details/112057814
- python怎样读取mysql数据(使用Python将Mysql的查询数据导出到文件的方法)
- mysql常见错误提示及解决办法(MYSQL 无法识别中文的永久解决方法)
- mysql错误代码之1064的解决方案(mysql错误代码之1064的解决方案)
- mysql中如何进行模糊查询(MySQL模糊查询用法大全正则、通配符、内置函数)
- mybatis为什么还用mysql(关于MyBatis连接MySql8.0版本的配置问题)
- 在php中与数据库连接的技术(PHP7.0连接DB操作实例分析基于mysqli)
- mysql分组函数入门(详解MySQL 数据分组)
- mysql读写分离同步策略(Mysql主从复制与读写分离图文详解)
- mysql查看执行慢的sql(系统隐形杀手——阻塞与等待SQL)
- mysql数据库事务处理(MySQL数据库事务与锁深入分析)
- phpstudy的mysql无法启动(Windows系统下解决PhPStudy MySQL启动失败问题)
- mysql乐观锁一定比悲观锁性能高(mysql居然还能实现分布式锁的方法)
- php实现redis核心代码(PHP结合Redis+MySQL实现冷热数据交换应用案例详解)
- mysql 高级用法(MySQL实现replace函数的几种实用场景)
- Mysql中CONCAT、CONCAT_WS字符串拼接函数
- mysql的sql语句优化5种方式(MySQL:五个常见优化SQL的技巧)
- 没钱只能吃土(没钱要吃土了幽默短信发朋友圈)
- 今年考高会很难吗(今年高考会考试吗)
- 盘古开天地 他创造了世界,谁创造了盘古 盘古是伏羲吗(盘古开天地他创造了世界)
- 关于队徽 你了解这些么 二(关于队徽你了解这些么)
- 冬天来了手脚冰凉 真不是因为上辈子你是折翼的天使(冬天来了手脚冰凉)
- 0 1 岁婴儿最强作息指南,照着做养出天使宝宝(01岁婴儿最强作息指南)
热门推荐
- 如何禁止按回车键提交表单
- 制作共用的头部和底部html5界面(html5移动端价格输入键盘的实现)
- docker创建容器使用教程(Docker容器连接实现步骤解析)
- ubuntu18.04更换软件源(ubuntu20.04 LTS系统默认源sources.list文件的修改)
- javascript的执行顺序
- mysql事件教程(关于MySQL报警的一次分析处理详解)
- navicat15.0.28注册码(Navicat for MySQL 11注册码激活码汇总)
- 私有云需要企业自己买服务器吗(企业如何对私有云主机进行管理?)
- html5 固定图片(HTML5拖放API实现自动生成相框功能)
- Extjs updateProgress进度条的应用
排行榜
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9