between and 的闭区间语义正确,但易被误读为覆盖完整自然日;实际因隐式类型转换导致仅匹配 00:00:00 精确时刻,需显式指定时间范围或改用 >= 与

BETWEEN AND 的闭区间语义本身没错,但“包含边界”在实际场景中常被误读为“覆盖完整自然单位”
比如查“2024-05-01当天所有订单”,写成 order_date BETWEEN '2024-05-01' AND '2024-05-01',结果只返回 '2024-05-01 00:00:00' 这一条——因为 MySQL 把字符串 '2024-05-01' 隐式转成 DATETIME 时补了 00:00:00,而 BETWEEN 真的只包这个精确时间点。这不是它错了,是你以为“同一天”是自然语义,而数据库只认字面闭区间。
日期字段类型不一致放大边界误差
当字段是 TIMESTAMP 或 DATETIME,而你用纯日期字符串做 BETWEEN,MySQL 会按规则补零,但业务上想覆盖的是“从 00:00:00 到 23:59:59.999999”这一整段。问题在于:
-
BETWEEN '2024-05-01' AND '2024-05-31'实际等价于order_date >= '2024-05-01 00:00:00' AND order_date ,末尾 23 小时 59 分钟全丢了 - 硬补
'23:59:59'仍可能漏掉微秒级数据(MySQL 5.6.4+ 支持 6 位微秒) -
DATE(order_date) = '2024-05-01'虽语义清晰,但函数包裹导致索引失效
数值比较中隐式转换让边界“漂移”
字段是 DECIMAL(10,2),却传入整数 100 或字符串 '100',MySQL 会做类型转换,但精度对齐过程可能引入不可见偏差。更隐蔽的是浮点型:
-
amount BETWEEN 0.1 AND 0.3可能不包含0.2,因为0.2在二进制中无法精确表示 - 用
amount >= 0.1 AND amount 同样有这问题,但显式写法至少让你意识到该换 <code>DECIMAL或用整数分(如以“分”为单位存) - 边界值类型不一致时,优化器可能放弃使用索引,导致全表扫描
NULL 和三值逻辑让“包含”变成“消失”
BETWEEN 对 NULL 值一律返回 UNKNOWN,整行被过滤。这不是 bug,是 SQL 三值逻辑的必然结果。但开发者常误以为“没查到数据=没匹配上”,其实可能是字段本身为 NULL:
-
price BETWEEN 100 AND 500不会命中price IS NULL的行,哪怕业务上希望把 NULL 当作“未定价”纳入统计 - 若需包含 NULL,必须显式加
OR price IS NULL,且注意括号优先级 - 复合条件如
status = 'active' OR price BETWEEN 100 AND 500若不加括号,实际执行顺序可能偏离预期
真正难处理的不是“是否包含边界”,而是“你定义的边界,在数据库眼里是不是你心里想的那个边界”。类型、精度、隐式转换、NULL、时区、微秒——这些细节堆叠起来,让一个看似简单的 BETWEEN 成了差一错误的温床。











