BETWEEN是闭区间操作符,包含左右端点,WHERE id BETWEEN 10 AND 20等价于id >= 10 AND id <= 20,不可误写为> 10 AND < 20。

WHERE子句里用BETWEEN查数值区间,别漏掉边界值
MySQL的BETWEEN是闭区间操作符,包含左右两个端点。很多人写WHERE id BETWEEN 10 AND 20却误以为它等价于>= 10 AND ——其实语义完全一致,但理解偏差容易导致边界逻辑出错。
常见错误现象:SELECT * FROM orders WHERE amount BETWEEN 100 AND 500本意是查100到500元订单,但如果字段amount是DECIMAL(10,2),而传入的参数没对齐精度(比如用500.0和500混用),可能因隐式类型转换丢精度;更隐蔽的是,当字段允许NULL时,NULL BETWEEN 10 AND 20永远返回NULL,整行被过滤掉——这不是bug,是三值逻辑的必然结果。
- 务必确认字段类型与边界值类型一致:数值字段配数字字面量,别用字符串如
'100' - 如果业务上需要包含NULL,得额外加
OR amount IS NULL,BETWEEN本身不处理NULL - 复合条件慎用括号:例如
WHERE status = 'paid' AND amount BETWEEN 100 AND 500没问题,但WHERE status = 'paid' OR amount BETWEEN 100 AND 500必须加括号,否则优先级可能导致意外结果
日期范围用BETWEEN要小心时分秒截断
对DATETIME或TIMESTAMP字段用BETWEEN '2024-01-01' AND '2024-12-31',实际查的是'2024-01-01 00:00:00'到'2024-12-31 00:00:00',末尾一整天的数据全丢了。这是最常踩的坑。
使用场景:报表统计某月销量、导出某天日志、筛选“最近7天”记录——都依赖精确的时间边界。
- 查完整一天,显式写满时间:
BETWEEN '2024-01-01 00:00:00' AND '2024-01-01 23:59:59',但注意MySQL 5.6.4+支持微秒,更稳妥是用 - 推荐替代方案:用开区间避开截断问题,例如
WHERE create_time >= '2024-01-01' AND create_time ,既清晰又利于索引下推 - 如果字段是
DATE类型(无时间部分),BETWEEN '2024-01-01' AND '2024-01-31'是安全的,但依然建议统一用>= AND 写法,避免类型混淆
BETWEEN在索引上的表现不如显式比较稳定
理论上BETWEEN能走范围索引,但实际执行计划里偶尔会退化成全表扫描,尤其当边界值来自参数或子查询时。优化器有时无法准确估算选择率,转而放弃索引。
性能影响:百万级表上,走索引和全表扫描的耗时可能差两个数量级;兼容性影响:MariaDB和Percona Server对BETWEEN的索引选择策略略有差异,线上环境需实测。
- 确保字段上有单列索引或联合索引的最左前缀,例如
INDEX (status, create_time),那么WHERE status = 'done' AND create_time BETWEEN ...才能高效利用 - 避免在
BETWEEN左侧用函数或表达式:YEAR(create_time) BETWEEN 2023 AND 2024必然无法走索引 - 用
EXPLAIN验证执行计划,重点看type是否为range、key是否命中预期索引、rows是否显著小于总行数
字符串字段慎用BETWEEN,排序规则决定结果
对VARCHAR字段如user_code执行WHERE user_code BETWEEN 'A001' AND 'Z999',结果高度依赖列的排序规则(collation)。如果是utf8mb4_0900_as_cs(大小写敏感),'a001'就不在范围内;如果是utf8mb4_general_ci,还可能因忽略重音符号导致意外匹配。
常见错误现象:测试库查出10条记录,生产库只查出2条——八成是排序规则不一致。
- 先查字段排序规则:
SHOW FULL COLUMNS FROM users LIKE 'user_code';,关注Collation列 - 字符串范围查询更推荐用前缀匹配+长度控制,例如
WHERE user_code >= 'A001' AND user_code - 如果必须用
BETWEEN,确保开发、测试、生产环境的字符集和排序规则完全一致,不要依赖默认值
边界值类型、时间精度、索引有效性、排序规则——这四个点只要一个没对齐,BETWEEN就可能查出意料之外的结果。尤其是跨环境部署时,别假设“本地跑得通,线上就一定对”。










