DATE_FORMAT是MySQL中唯一能直接控制日期显示样式的内置函数,仅用于格式化输出、不改变数据类型,且需正确传入日期值和单引号包裹的格式模板,大小写敏感,WHERE中使用会导致索引失效。

DATE_FORMAT 是 MySQL 中唯一能直接控制日期显示样式的内置函数,但它不是万能的“日期转换器”——它只做格式化输出,不改变数据类型,也不能替代解析逻辑。
DATE_FORMAT(date, format) 的参数到底怎么填
第一个参数 date 必须是合法的日期类型值(DATE、DATETIME 或 TIMESTAMP),不能是任意字符串;第二个参数 format 是纯字符串模板,必须用单引号包裹,且所有格式符都以 % 开头。
-
DATE_FORMAT('2024-03-15', '%Y-%m-%d')可行,MySQL 会尝试隐式转换字符串为日期 -
DATE_FORMAT('15/03/2024', '%Y-%m-%d')返回NULL,因为格式不匹配,隐式转换失败 -
DATE_FORMAT(created_at, '%Y年%c月%e日')正确,前提是created_at是DATE类型字段 - 别写
DATE_FORMAT(NOW(), %Y-%m-%d)——漏了单引号,语法错误
常见格式符大小写敏感,且行为差异大
同一个字母大小写不同,含义完全不同,比如 %H 和 %h、%M 和 %m,混用会导致结果出人意料。
-
%H:24 小时制小时(00–23),%h或%I:12 小时制小时(01–12) -
%M:英文全月名(January),%m:两位数字月份(01) -
%W:星期全名(Wednesday),%w:数字星期(3,周日为0) - 对
DATE类型字段用%H,结果恒为00,不是NULL,容易被忽略
WHERE 里用 DATE_FORMAT 就等于放弃索引
只要 DATE_FORMAT 出现在 WHERE 子句左侧(如 WHERE DATE_FORMAT(create_time, '%Y-%m') = '2024-03'),MySQL 就无法使用 create_time 上的索引,强制全表扫描。
- 正确做法是改用范围查询:
WHERE create_time >= '2024-03-01' AND create_time < '2024-04-01' - 真要按格式分组统计,
GROUP BY DATE_FORMAT(create_time, '%Y-%m')可以用,但注意结果是字符串排序,'2024-1'会排在'2024-10'前面 - 如果字段是
TIMESTAMP,还要留意会话时区影响输出,同一时间在不同时区会显示不同字符串
DATE_FORMAT 和 STR_TO_DATE 是单向搭档,不能互换
DATE_FORMAT 只负责“日期 → 字符串”,STR_TO_DATE 负责“字符串 → 日期”,两者方向相反,不能用错场景。
-
DATE_FORMAT(STR_TO_DATE('15/03/2024', '%d/%m/%Y'), '%Y-%m-%d')才能得到'2024-03-15' -
STR_TO_DATE(DATE_FORMAT(NOW(), '%Y-%m-%d'), '%Y-%m-%d')看似绕一圈,但多此一举,且可能因时区或精度丢失出问题 - 把
DATE_FORMAT结果当日期参与运算(如+ INTERVAL 1 DAY)会报Invalid date - 字段存的是
VARCHAR类型的“日期”,先得用STR_TO_DATE转成日期类型,再用DATE_FORMAT格式化,不能跳步


















