DATE_FORMAT函数用于将MySQL日期转为指定字符串格式,需传入合法日期类型和带%前缀的格式符(如%Y、%m),WHERE中滥用会导致索引失效,应改用范围查询。

DATE_FORMAT 能把 MySQL 里的日期转成你想要的字符串格式,但直接套模板容易出错——比如时区没对齐、格式符写错、或者在 WHERE 里滥用导致索引失效。
DATE_FORMAT 的基本用法和常见格式符
它接收两个参数:DATE_FORMAT(date, format),第一个是日期值(DATE、DATETIME 或 TIMESTAMP),第二个是格式字符串。注意:格式符必须用百分号开头,比如 %Y 是 4 位年份,%y 是 2 位年份,%m 是补零月份数字,%c 是不补零月份(MySQL 5.7+ 支持)。
-
SELECT DATE_FORMAT('2023-08-15', '%Y年%m月%d日')→2023年08月15日 -
SELECT DATE_FORMAT(NOW(), '%H:%i:%s')→ 当前时间的时分秒(14:23:05) -
%W返回英文星期全名(Monday),%w返回数字(周日=0),中文需配合SET lc_time_names = 'zh_CN'才生效
WHERE 条件中误用 DATE_FORMAT 导致索引失效
如果在查询条件里对字段用 DATE_FORMAT(created_at, '%Y-%m') 做匹配,MySQL 无法走 created_at 上的索引——因为函数改变了原始列值,优化器没法下推。
- ❌ 错误写法:
WHERE DATE_FORMAT(created_at, '%Y-%m') = '2023-08' - ✅ 正确替代:
WHERE created_at >= '2023-08-01' AND created_at - 如果真要按年月查且字段无索引,考虑加生成列 + 索引:
ALTER TABLE t ADD COLUMN ym CHAR(7) AS (DATE_FORMAT(created_at, '%Y-%m')) STORED,再对ym建索引
与 STR_TO_DATE 的配合使用场景
DATE_FORMAT 是“日期 → 字符串”,反过来要把字符串转日期就得用 STR_TO_DATE。两者格式符基本一致,但方向相反,容易混淆。
- 从字符串解析:
STR_TO_DATE('2023/08/15', '%Y/%m/%d')→2023-08-15 - 如果格式不匹配会返回
NULL,比如用%Y-%m-%d去解析'2023/08/15'就失败 - 注意 MySQL 默认日期分隔符是
-,斜杠或点需要显式指定格式符,不能依赖隐式转换
真正麻烦的不是记格式符,而是混用 DATE_FORMAT 和业务逻辑——比如前端要“昨天”“今天”这类相对时间,硬塞进 SQL 里拼字符串,不如在应用层处理;还有时区问题,NOW() 返回的是服务器时区时间,UTC_TIMESTAMP() 才是 UTC,别忘了确认字段存的是哪种时区。


















