切换语言为:繁体

SQL中隐式转换 where 值=0 引发的问题

  • 爱糖宝
  • 2024-09-13
  • 2048
  • 0
  • 0

一.问题重现

1.问题模拟

🌰举例

一个person表,假设其中有sex性别字段类型为varchar,0代表女,1代表男,建表如下

SQL中隐式转换 where 值=0 引发的问题

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;

插入模拟数据

SQL中隐式转换 where 值=0 引发的问题

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的问题数据

SQL中隐式转换 where 值=0 引发的问题

SELECT * FROM person WHERE sex = 0;

执行结果

SQL中隐式转换 where 值=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会查到所有非数字开头的字符串,用其他数字查则会匹配到与之对应数字开头的字符串

SQL中隐式转换 where 值=0 引发的问题

SQL中隐式转换 where 值=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 会尝试将字符串转换为数字。

  • 显式类型转换更安全:显式地进行类型转换可以确保查询结果符合预期。

0条评论

您的电子邮件等信息不会被公开,以下所有项均必填

OK! You can skip this field.