date_format是mysql中唯一可定制日期字符串输出的内置函数,仅格式化显示而不修改数据;基本语法为date_format(date, format),常用格式符包括%y、%m、%d等,需注意大小写敏感、时区影响、索引失效及不可逆向解析等关键限制。

DATE_FORMAT 是 MySQL 中唯一能按需定制日期字符串输出的内置函数,它不修改数据本身,只控制查询结果的显示格式。
DATE_FORMAT 函数的基本用法和常见格式符
调用形式为 DATE_FORMAT(date, format),第一个参数是日期类型字段或表达式(如 NOW()、created_at),第二个是格式化模板字符串。
常用格式符必须用百分号开头:%Y(4位年)、%y(2位年)、%m(01–12月)、%c(1–12月,无前导零)、%d(01–31日)、%e(1–31日)、%H(24小时制时)、%h 或 %I(12小时制时)、%i(分)、%s(秒)。
注意:%M 输出英文全月名(如 "January"),%b 输出英文缩写(如 "Jan"),它们在中文环境默认不可用,除非系统 locale 支持且字段值本身是 DATE/DATETIME 类型。
处理 DATETIME 和 TIMESTAMP 字段时的隐式截断风险
如果对 TIMESTAMP 或 DATETIME 字段仅用日期格式符(如 '%Y-%m-%d'),MySQL 会自动忽略时间部分,但不会报错 —— 这容易掩盖本应保留时间信息的业务逻辑。
- 需要同时展示日期和时间时,务必显式包含时间格式符,例如
'%Y-%m-%d %H:%i:%s' - 若字段实际存的是
TIMESTAMP且时区敏感,DATE_FORMAT输出基于当前会话时区,不是存储时区 - 对
DATE类型字段使用%H等时间符,结果恒为00,不是 NULL
与 STR_TO_DATE 的方向性区别:别把格式化当解析用
DATE_FORMAT 只能从日期转字符串,不能反向解析。试图用它“转换字符串为日期”会失败:
SELECT DATE_FORMAT('2024-03-15', '%Y%m%d'); -- 返回 '20240315'(字符串),不是日期类型
真正需要类型转换时,该用 STR_TO_DATE('2024-03-15', '%Y-%m-%d') 得到 DATE 值;而 DATE_FORMAT(NOW(), '%Y年%c月%e日') 才是合法的中文风格展示。
常见误用场景:
- 在 WHERE 条件里对字段套
DATE_FORMAT(created_at, '%Y-%m')做比较 → 导致索引失效 - 用
DATE_FORMAT结果参与日期运算(如 + INTERVAL 1 DAY)→ 报错 “Invalid date” - 把格式化结果当作排序依据(如按月份字符串排序)→ 字典序而非时间序,'2024-1' 会排在 '2024-10' 前面
性能与可维护性提醒
DATE_FORMAT 是逐行计算函数,无法利用索引加速。高频查询中频繁使用它,尤其在大表 SELECT 列表里,会显著拖慢响应。
更稳妥的做法:
- 前端或应用层做格式化,数据库只传原始日期值
- 如必须数据库端输出,考虑用生成列(GENERATED COLUMN)预计算并建索引(MySQL 5.7+)
- 避免在 ORDER BY 或 GROUP BY 中直接嵌套
DATE_FORMAT,改用DATE(created_at)或YEAR(created_at)等原生日期函数
格式符大小写敏感,%Y 和 %y 含义不同,拼错会导致输出异常但无提示 —— 最容易被忽略的是月份和日的前导零控制(%m vs %c,%d vs %e),线上查出“1月5日”还是“01月05日”,得看这里。











