BETWEEN在SQL中本质是闭区间筛选,等价于>=和

BETWEEN 在 SQL 中本质是闭区间筛选,等价于 >= 和 的组合,不是语法糖,但行为固定且不可配置。
为什么 BETWEEN 查不到预期数据?
常见错误是误以为 BETWEEN 包含 NULL 或自动处理类型隐式转换:
-
BETWEEN两端值必须与字段类型兼容,比如用字符串'10'和'2'查询数字列,可能因字典序导致'2' > '10',结果为空 - 若字段含 NULL,
WHERE age BETWEEN 18 AND 60自动跳过所有age IS NULL行,不会报错也不会提示 - 日期场景下,
BETWEEN '2023-01-01' AND '2023-12-31'实际覆盖到2023-12-31 00:00:00,若字段含时间部分(如DATETIME),则'2023-12-31 14:30:00'不会被包含
BETWEEN 和手写 >= ... AND 有区别吗?
语义一致,但执行层面存在细微差异:
- 多数数据库(如 PostgreSQL、SQL Server)对两者生成相同执行计划;MySQL 8.0+ 也基本无差别
- 唯一实际影响是可读性:
BETWEEN更紧凑,但无法单独对左/右边界加函数或表达式,例如score BETWEEN MIN(score) AND MAX(score)是非法的,必须用子查询或 CTE 拆开 - 当需要半开区间(如
[start, end)),必须弃用BETWEEN,改用col >= start AND col
日期范围查询最容易踩的坑
用 BETWEEN 做日期查询时,别只看日期字面值:
- 确认字段类型:是
DATE还是TIMESTAMP/DATETIME?前者忽略时间,后者默认带00:00:00 - 避免硬写
BETWEEN '2023-01-01' AND '2023-01-31'查整月数据——如果字段是DATETIME,会漏掉 1 月 31 日全天其他时间点的数据 - 更稳妥写法:
created_at >= '2023-01-01' AND created_at ,既明确又利于索引使用 - PostgreSQL 中
DATE类型字段用BETWEEN安全;MySQL 的DATE也安全,但一旦混用NOW()就可能触发隐式转换
真正麻烦的是边界类型不一致和时区隐含转换,比如把 UTC 时间存进字段,却用本地时间字符串查 BETWEEN,结果看似合理实则偏移数小时。

















