DATE_FORMAT()是MySQL中唯一用于日期格式化的函数,需用%前缀(如%Y、%m、%d),避免漏写%导致空字符串;中文格式需确保字符集为utf8mb4;配合STR_TO_DATE()解析字符串日期;WHERE中使用会失效索引,应改用范围查询。

DATE_FORMAT函数的基本用法和常见错误
MySQL里想把日期转成“2024-05-20”或“2024年05月20日”这类格式,DATE_FORMAT() 是唯一靠谱的选择。别试 CAST() 或 CONVERT(),它们只负责类型转换,不处理格式化。
常见错误是直接写 DATE_FORMAT(NOW(), 'Y-m-d')——漏了百分号,结果返回空字符串。所有格式符必须带 % 前缀,比如 %Y、%m、%d。
-
%Y:4位年份(2024),%y是2位(24),别混用 -
%m:补零月份数字(01–12),%c是不补零版本(1–12),用错会导致排序错乱 -
%d:补零日期(01–31),%e不补零,但某些旧版MySQL对%e支持不稳定
中文格式输出要注意字符集和引号嵌套
想输出“2024年05月20日”,不能直接写 DATE_FORMAT(NOW(), '%Y年%m月%d日')——如果客户端或连接字符集不是 utf8mb4,中文会变问号或乱码。
更隐蔽的问题是单引号嵌套:SQL里字符串用单引号包裹,而格式串里的中文也要在单引号内,所以得用两个单引号表示一个字面单引号,但中文本身不用转义。正确写法就是:DATE_FORMAT(NOW(), '%Y年%m月%d日'),只要确保连接层字符集设对就行。
- 检查当前连接字符集:
SHOW VARIABLES LIKE 'character_set_client'; - 临时修复方法:
SET NAMES utf8mb4;(执行查询前先运行) - 避免用
%M(英文全月名)混搭中文,比如'%Y年%M月'会输出 “2024年May月”
与STR_TO_DATE的配合使用场景
DATE_FORMAT() 只负责“输出格式化”,不负责“解析输入”。如果你拿到的是字符串如 '2024/05/20',想先转成日期再格式化,得先用 STR_TO_DATE() 转成 DATE 类型。
典型错误是跳过这步直接格式化字符串:DATE_FORMAT('2024/05/20', '%Y-%m-%d'),结果原样返回字符串,不报错但毫无意义。
- 正确链式写法:
DATE_FORMAT(STR_TO_DATE('2024/05/20', '%Y/%m/%d'), '%Y年%m月%d日') -
STR_TO_DATE()的格式串必须和输入字符串**严格匹配**,'2024-05-20'对应'%Y-%m-%d',多一个空格或斜杠都会返回NULL - 注意时区:
STR_TO_DATE()解析不带时间的字符串,默认时间为00:00:00,且按系统时区解释
性能和索引失效风险
在 WHERE 条件里对字段用 DATE_FORMAT(),比如 WHERE DATE_FORMAT(create_time, '%Y-%m') = '2024-05',会导致该字段无法走索引——MySQL没法把函数结果反推回原始值。
真正要查某年某月的数据,应该用范围查询:
WHERE create_time >= '2024-05-01' AND create_time < '2024-06-01'
这种写法能命中 create_time 上的索引,速度差几倍到几十倍不等。
-
DATE_FORMAT()适合用在SELECT列表或ORDER BY(非关键路径) - 如果必须按格式分组统计(如按“年月”汇总),优先考虑生成计算列+索引,而不是在查询里实时算
- 函数调用本身开销小,但阻断优化器路径才是大问题
最常被忽略的一点:格式化结果是字符串,不是日期类型。后续如果拿这个结果再去和其他日期做比较或加减,得先转回来,否则隐式转换可能出错或慢。


















