前言
🍊缘由
线上问题把我坑,一查数据让我蒙
🐣闪亮主角
大家好,我是JavaDog程序狗
今天跟大家分享一个本狗造成的线上事故, 一个简单的SQL查询语句导致的bug
😈你想听的故事
最近狗哥有点飘,但是bug从来不会放过任何一个摸鱼的人…
一个阳光明媚的下班点,发现组长表情凝重,愁眉不展,遂狗哥上来询问,原来是之前狗哥写的迭代线上出了问题!
暴露的问题是本不该出现的数据,竟然被查出来了!
从一脸愁容,到两脸蒙蔽,通过分析发现代码并没有问题,最后只能定位到SQL查询中…
发现 select * from 表 where value = 0 ,竟然没有过滤出想要的数据,最终定位到问题。
遂跟大家分享一个从业8年第一次遇到的神奇bug,SQL中隐式转换 where 值=0 引发的问题
正文
🎯主要目标
1.问题重现
2.MySQL隐式转换
🍪目标讲解
一.问题重现
1.问题模拟
🌰举例
一个person表,假设其中有sex性别字段类型为varchar,0代表女,1代表男,建表如下
CREATE TABLE `person` (
`id` bigint(20) NOT NULL COMMENT 'id',
`name` varchar(255) NOT NULL COMMENT '名称',
`age` int(10) NOT NULL COMMENT '年龄',
`sex` varchar(2) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '性别(男;女)',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
插入模拟数据
INSERT INTO `demo`.`person` (`id`, `name`, `age`, `sex`) VALUES (1, '张三', 20, '男');
INSERT INTO `demo`.`person` (`id`, `name`, `age`, `sex`) VALUES (2, '李四', 30, '女');
INSERT INTO `demo`.`person` (`id`, `name`, `age`, `sex`) VALUES (3, '小姐姐', 18, '0');
INSERT INTO `demo`.`person` (`id`, `name`, `age`, `sex`) VALUES (4, '王五', 20, '男');
2.查询语句
现在我们要查询性别为0的问题数据
SELECT * FROM person WHERE sex = 0;
执行结果
结果是不是出人意料,竟然将所有数据都查出,是不是失效出bug了?
其实这就是MySQL的隐式特性,而不是什么bug,别急后面慢慢详解…
二.MySQL隐式转换
1.隐式转换是什么?
MySQL中的隐式类型转换是指当执行某些操作时,如比较操作或其他需要特定数据类型参数的操作时,如果参与操作的表达式或列的数据类型不匹配,MySQL将会自动进行数据类型转换以适应预期的数据类型。
👽人话解释
就是字段类型不匹配,mysql会自动转,如果你以数字0为条件,mysql就会将字段内容转成数字进行处理
2.示例问题分析
在MySQL中,当你尝试用整数 0 作为条件去查询一个 VARCHAR 类型的字段时,MySQL 会尝试将 VARCHAR 字段的内容转换为数字进行比较。
这种情况下,MySQL 会检查字符串的开始部分是否可以解析为一个数字。如果可以,它将使用这个数字值进行比较;如果不能解析为数字,则默认使用 0 进行比较。
也就是说
SELECT * FROM person WHERE sex = 0; 和 SELECT * FROM person WHERE sex = ‘0’;
两个表达的意思完全不一样,用0会查到所有非数字开头的字符串,用其他数字查则会匹配到与之对应数字开头的字符串
总结
1.问题重现:
- 创建 person 表,sex 字段为 VARCHAR 类型。
- 插入数据,包括 sex 为 ‘男’、‘女’、‘0’ 等。
- 查询 SELECT * FROM person WHERE sex = 0; 返回所有数据,而非仅 ‘0’。
2.原因分析:
- MySQL 尝试将 VARCHAR 字段内容转换为数字进行比较。
- 如果字符串可以解析为数字,则使用该数字;否则默认使用 0。
3.解决方法:
- 显式类型转换:SELECT * FROM person WHERE CAST(sex AS SIGNED) = 0;
- 直接使用字符串比较:SELECT * FROM person WHERE sex = ‘0’;
4.结论
- 隐式转换会导致意外结果:使用整数 0 查询 VARCHAR 字段时,MySQL 会尝试将字符串转换为数字。
- 显式类型转换更安全:显式地进行类型转换可以确保查询结果符合预期。
🍈猜你想问
如何与狗哥联系进行探讨
关注公众号【JavaDog程序狗】
公众号回复【入群】或者【加入】,便可成为【程序员学习交流摸鱼群】的一员,问题随便问,牛逼随便吹,目前群内已有超过300+个小伙伴啦!!!
2.踩踩狗哥博客
里面有狗哥的私密联系方式呦 😘
大家可以在里面留言,随意发挥,有问必答
🍯猜你喜欢
文章推荐
【实操】Spring Cloud Alibaba AI,阿里AI这不得玩一下(含前后端源码)
【项目实战】SpringBoot+uniapp+uview2打造H5+小程序+APP入门学习的聊天小项目