MySQL中BETWEEN操作符针对DATETIME列不生效问题排查
为啥MySQL的BETWEEN在你这两个查询里结果不一样?
这个坑我之前在MySQL 5.7里踩过好多次,核心原因基本都是数据类型不匹配导致的隐式转换,或者是字符串字典序和数字数值比较的逻辑差异。我给你拆解最可能的情况:
最常见的触发场景:字符串vs数字的混合比较
我猜你的两个查询大概是类似这样的(完全符合你说的一个返回1、一个返回0的情况):
- 返回1的查询:
SELECT 1 WHERE 5 BETWEEN 1 AND 10; - 返回0的查询:
SELECT 1 WHERE '5' BETWEEN '1' AND '10';
为啥结果差这么多?
- 第一个查询全是数字类型,BETWEEN是按数值大小来判断的:5当然在1到10之间,所以返回1(真)。
- 第二个查询全是字符串,MySQL就会按**字典序(字符的ASCII码值)**来对比了:
字符串比较是从左到右逐个字符比的,'5'的第一个字符是'5'(ASCII码53),而'10'的第一个字符是'1'(ASCII码49)。因为53比49大,所以MySQL会认为'5'比'10'还大,自然不在'1'到'10'的字符串范围内,返回0(假)。
另一种可能:表字段类型和查询值不匹配
如果你的查询是针对表字段的,比如:
- 假设表的
id字段是VARCHAR类型,但你用数字查:SELECT 1 WHERE id BETWEEN 1 AND 5;
这时MySQL会把所有id的字符串值自动转成数字(转失败的会变成0),要是id是'10',转成数字10就不在1-5之间;但如果是'5',转成5就会被命中。 - 反过来,如果
id是INT类型,你用字符串查:SELECT 1 WHERE id BETWEEN '1' AND '10';
MySQL会把字符串转成数字,这时候逻辑就和纯数字比较一样了,返回符合数值范围的结果。
怎么验证这个问题?
你可以用CAST函数强制转类型来测试:
- 把字符串转成数字再比:
SELECT 1 WHERE CAST('5' AS UNSIGNED) BETWEEN '1' AND '10';这个会返回1 - 把数字转成字符串再比:
SELECT 1 WHERE CAST(5 AS CHAR) BETWEEN '1' AND '10';这个会返回0
总结
解决这类问题的核心就是:确保比较两边的类型一致,要么全用数字,要么全用字符串(如果是存成字符串的数值,最好显式转成数字后再做范围比较)。
内容的提问来源于stack exchange,提问作者Martin Heralecký
相关产品推荐
相关产品推荐

