一.问题重现
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 会尝试将字符串转换为数字。
显式类型转换更安全:显式地进行类型转换可以确保查询结果符合预期。