直接比较 TIME(NOW()) 更可靠:对不跨日时段用 BETWEEN '09:00:00' AND '18:00:00',跨日则用 OR 拆分条件;需校准时区、避免隐式转换、慎用 HOUR() 以防精度丢失。
用
或直接比较
更可靠
MySQL 的
函数本身不能直接判断“是否在工作时间段”,它只是提取时间部分;真正做区间比对,得靠比较操作符(
、
)或
配合字符串时间字面量。常见错误是把
当成数值参与运算,或忽略时区导致比对结果漂移。
实际场景中,工作时间通常是固定时段(如 09:00–18:00),不跨日,所以直接用
提取当前时间点,再与字符串时间字面量比较最简洁高效:
是闭区间,包含起止时间点,符合多数“9点开始上班”的语义
字符串时间字面量必须是
格式,且长度固定,否则可能触发隐式转换失败
如果数据库时区和业务时区不一致(比如服务器在 UTC,业务在中国),需先用
校准
跨日工作时段(如夜班 22:00–06:00)不能用
当工作时段跨越午夜(比如 22:00 到次日 06:00),
永远为
,因为字符串比较中
成立,
要求左值 ≤ 右值。
此时必须拆成两个条件并用
连接:
MySQL(Linux)
MySQL 9.6.0是面向Linux平台的2026年创新版本,核心架构迎来重大革新。其将外键约束与级联操作从InnoDB引擎层上移至SQL层,确保所有数据变更均被完整记录至Binlog,彻底解决了CDC(变更数据捕获)与主从复制中的数据不一致难题。此外,该版本引入container_aware启动选项以原生适配容器环境,并对审计日志进行了组件化重构,为追求极致数据一致性与云原生体验的开发者提供了全新选择。
下载
逻辑上等价于“当前时间在 22:00 之后,或在 06:00 之前”,覆盖了跨日区间
注意是
,不是
,否则 06:00:00 这一刻会被排除
若还需排除午休(如 12:00–13:00),就得叠加
和
在精度和可读性上的取舍
有人倾向用
判断 9–17 点,看似简单,但会漏掉边界分钟秒(比如 17:30:00 被算作“下班后”)。而
返回完整时间类型,支持精确到秒的比对。
只返回整数小时,适合粗粒度判断(如“是否在白天”),不适合“是否在 09:00–18:00 工作时间内”这类需求
返回的是
类型,能直接和
这类字面量比较,无需类型转换
如果字段存的是
或
,别写
—— 这会导致该列无法走索引,应考虑提前计算好时间范围再查
在 WHERE 条件里用时间比对要警惕隐式类型转换
写
看似合理,但 MySQL 在某些版本中会对
结果做隐式转换,尤其当
是
或格式异常时,可能返回
导致整行被过滤掉,而你根本没意识到。
更稳妥的方式是先确保字段非空:
如果查询频次高,建议在表里加一个生成列:
,再在该列建索引
线上环境务必验证时区:执行
,确认三者符合预期
实际业务中,“工作时间段”往往还关联节假日、调休、部门差异等,纯 SQL 判断很快会力不从心。真正需要动态规则时,别硬撑在 SQL 层做复杂逻辑——把时间判断下沉到应用层,SQL 只负责取原始时间数据,反而更可控。
TIMESTAMPDIFFTIME(NOW())TIME()>=<=TIMESTAMPDIFF'09:00:00'TIME(NOW())SELECT TIME(NOW()) BETWEEN '09:00:00' AND '18:00:00';BETWEEN'HH:MM:SS'CONVERT_TZ(NOW(), '+00:00', '+08:00')BETWEENBETWEEN '22:00:00' AND '06:00:00'FALSE'22:00:00' > '06:00:00'BETWEENORSELECT TIME(NOW()) >= '22:00:00' OR TIME(NOW()) <= '06:00:00';<= '06:00:00'< '06:00:00'NOT (TIME(NOW()) BETWEEN '12:00:00' AND '13:00:00')TIME()HOUR()HOUR(NOW()) BETWEEN 9 AND 17TIME()HOUR()TIME(NOW())TIME'09:00:00'DATETIMETIMESTAMPTIME(datetime_col) >= '09:00:00'WHERE TIME(created_at) >= '09:00:00'TIME()created_atNULLNULLWHERE created_at IS NOT NULL AND TIME(created_at) >= '09:00:00'ADD COLUMN work_time TIME AS (TIME(created_at)) STOREDSELECT NOW(), TIME(NOW()), @@time_zone;