对于mysql中数据为NULL引发的一些问题和思考
首先创建测试表
CREATE TABLE `temp_person` (
`id` int NOT NULL AUTO_INCREMENT,
`name` varchar(5) COLLATE utf8mb4_bin DEFAULT NULL,
`phone` varchar(20) COLLATE utf8mb4_bin DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
填充测试数据
INSERT INTO `mz_order`.`temp_person`(`id`, `name`, `phone`) VALUES (1, '张三', '159xxx001');
INSERT INTO `mz_order`.`temp_person`(`id`, `name`, `phone`) VALUES (2, '李四', '159xxx002');
INSERT INTO `mz_order`.`temp_person`(`id`, `name`, `phone`) VALUES (3, '王五', '159xxx003');
INSERT INTO `mz_order`.`temp_person`(`id`, `name`, `phone`) VALUES (4, '马六', '159xxx004');
INSERT INTO `mz_order`.`temp_person`(`id`, `name`, `phone`) VALUES (5, '王一', '159xxx005');
INSERT INTO `mz_order`.`temp_person`(`id`, `name`, `phone`) VALUES (6, '王二', '159xxx006');
INSERT INTO `mz_order`.`temp_person`(`id`, `name`, `phone`) VALUES (7, '', '159xxx007');
INSERT INTO `mz_order`.`temp_person`(`id`, `name`, `phone`) VALUES (8, NULL, '159xxx008');
查一下数据
问题1:count数据
select count(1),count(id),count(`name`),count(phone) from temp_person;
执行结果如下:
结论:当某列存在null值时,例如name列可能会有空值,使用count(name)会丢失数据。
解决方案:当需要使用count时,可以使用count(1)或count(主键)进行统计。
问题2:distinct 数据
SELECT
count( DISTINCT `name`, phone ),
count( DISTINCT phone, `name` )
FROM
temp_person;
执行结果如下:
第二列也不存重复值,实际列为8,但查询结果为7。
结论:当使用count(distinct 列1,列2)查询时,如果其中一列(不分顺序)为null,那么即使另一列有值,查询结果也会丢失。
问题3:select数据
查询非等于 <>或!=,会导致数据为Null值的结果丢失。
SELECT
*
FROM
temp_person
where `name`<>'张三'
例如:查询出名字不等于'张三'的数据
执行结果如下:
结论:使用非等于,会使数据为Null的数据丢失。
解决方法:只需要在查询结果后面加上为Null值的结果即可。执行sql如下:
SELECT
*
FROM
temp_person
where `name`!='张三'
or isnull(`name`)
问题4:空指针异常
如果某列存在null值,可能会导致sum(column)的返回结果为null,而非0.
改造测试表,增加列age。
ALTER TABLE `mz_order`.`temp_person`
ADD COLUMN `age` smallint(6) NULL COMMENT '年龄' AFTER `phone`;
手动赋值
开始查询
SELECT
sum( age )
FROM
temp_person
WHERE
id >6
结论:当查询的数据为null时,使用sum函数会返回null而不是0,就可能会导致程序空指针。
解决方法:增加判空即可
SELECT
ifnull(sum( age ) ,0)
FROM
temp_person
WHERE
id >6
问题5:查询如果某列为空给默认值
场景:比如说传输数据,需要name不为空的数据传输过去。如果name为空,则给一个默认值。
例如:
SELECT
`name` as '原始数据',
ifnull( NAME, '默认' ) AS name1,
IF( NAME IS NULL, '默认', NAME ) AS name2 ,
if(name='','默认',name) as name3
FROM
temp_person;
可以发现,列出的3种方式对于null或空都会存在空值,那么如何避免呢?
解决方法:
SELECT
`name` AS '原始数据',
IFNULL( IF ( `name` = '', '默认', `name` ), '默认' ) AS name1
FROM
temp_person;