DATETIME/TIMESTAMP 字段用 BETWEEN AND 会隐式截断右边界为 00:00:00,导致漏数据;DATE 类型安全,而 DATETIME/TIMESTAMP 必须显式指定时间或改用 >= 与 <。

BETWEEN AND 用于 DATETIME/TIMESTAMP 字段时,默认右边界会被截断为 00:00:00,不显式补全时间就必然漏数据——这不是配置问题,是 MySQL 的隐式转换规则。
DATE 类型能用 BETWEEN,但 DATETIME/TIMESTAMP 不行
DATE 字段(如 order_date DATE)本身无时间部分,BETWEEN '2026-09-28' AND '2026-09-29' 是安全的,语义就是“28日整日到29日整日”。但只要字段是 DATETIME 或 TIMESTAMP,同样的写法就会变成:create_time >= '2026-09-28 00:00:00' AND create_time ,结果 29 日 00:00:01 之后的所有记录全被过滤掉。
- 查“2026-09-28 当天”数据,错误写法:
create_time BETWEEN '2026-09-28' AND '2026-09-28'→ 实际只匹配'2026-09-28 00:00:00'这一秒 - 查“2026-09-28 至 2026-09-29”,错误写法:
create_time BETWEEN '2026-09-28' AND '2026-09-29'→ 实际范围是 28 日 00:00:00 到 29 日 00:00:00,漏掉 29 日全天 - DATE 类型字段若后期改成 DATETIME,原 SQL 会静默失效,建议从一开始就规避混合用法
显式补全时间不如改用左闭右开
有人会写 BETWEEN '2026-09-28 00:00:00' AND '2026-09-29 23:59:59',这看似完整,但仍有风险:MySQL 5.6.4+ 支持微秒,'2026-09-29 23:59:59.999999' 才算真正覆盖全天;而手写微秒容易出错、可读性差、参数化也难对齐。
- 推荐统一用:
create_time >= '2026-09-28' AND create_time (查 28 日全天) - 查“最近7天”(含今天):
create_time >= DATE_SUB(CURDATE(), INTERVAL 6 DAY) AND create_time - 该写法天然兼容所有精度(秒/微秒),优化器能更好下推索引,且逻辑直白:左包含、右不包含
BETWEEN 反序或 NULL 会导致静默空结果
MySQL 不校验 BETWEEN A AND B 中 A 是否 ≤ B,如果传入 start_date = '2026-09-29'、end_date = '2026-09-28',语句不会报错,但返回空集。同样,字段值为 NULL 时,NULL BETWEEN '2026-09-28' AND '2026-09-29' 返回 UNKNOWN,整行被过滤——这是 SQL 三值逻辑的正常行为,不是 bug。
- 参数化查询时,务必在应用层校验:
if start_date > end_date { throw error } - 若业务需包含 NULL 记录,得额外加:
OR create_time IS NULL - 复合条件中混用
OR必须加括号,例如:WHERE status = 'done' AND (create_time >= '2026-09-28' AND create_time ,否则优先级可能拉垮整个逻辑
真正麻烦的从来不是语法,而是 DATETIME 隐式补零和 NULL 的三值逻辑——这两点在线上查不到数据时,最容易让人反复检查索引、怀疑数据丢失,却忽略最基础的边界表达是否成立。


















