STR_TO_DATE格式不匹配时静默返回NULL而非报错;需严格匹配年份大小写、月份缩写/全称、12小时制加%p、分隔符一致;无万能模板,不同输入需对应不同格式;避免在WHERE/INSERT中直接使用以防索引失效或NULL问题。

STR_TO_DATE 用错格式符就返回 NULL
MySQL 的 STR_TO_DATE 不会报错,但只要格式字符串和输入不严格匹配,就静默返回 NULL。比如把 '2023-05-12' 用 '%Y/%m/%d' 去解析,结果就是 NULL,而不是报错提醒你写错了。
常见踩坑点:
-
'%Y-%m-%d'对应'2023-05-12','%y-%m-%d'(小写 y)只认两位年份,如'23-05-12' - 英文月份缩写必须用
'%b'(如'May'),全称用'%M'(如'May'不等于'may',大小写敏感) - 12 小时制时间必须带
'%p'('AM'或'PM'),漏掉就解析失败 - 空格、横线、斜杠这些分隔符要一字不差——
'%Y.%m.%d'解析不了'2023-05-12'
不同日期字符串得配不同格式模板
没有万能格式串。实际业务里常见几种输入,得分别处理:
-
'20230512'→STR_TO_DATE('20230512', '%Y%m%d') -
'12/05/2023'(日/月/年)→STR_TO_DATE('12/05/2023', '%d/%m/%Y'),注意顺序不是美式 -
'05-May-2023'→STR_TO_DATE('05-May-2023', '%d-%b-%Y') -
'2023-05-12 14:30:00'→STR_TO_DATE('2023-05-12 14:30:00', '%Y-%m-%d %H:%i:%s'),%i是分钟,%s是秒,别写成%S(那是毫秒)
在 WHERE 或 INSERT 中直接用 STR_TO_DATE 容易出隐性问题
函数本身没问题,但放在查询条件或插入值里时,容易触发隐式类型转换或索引失效:
- 如果对字段用
STR_TO_DATE(date_str_col, '%Y-%m-%d')做比较,MySQL 无法走date_str_col上的索引,哪怕它存的是标准格式字符串 - 插入前没校验,
STR_TO_DATE返回NULL,可能意外写入空日期或触发 NOT NULL 报错 - 时区不参与解析——输入是
'2023-05-12 15:00:00',无论服务器时区如何,都按本地时间存为2023-05-12 15:00:00,不会自动转 UTC
替代方案:优先存 DATE 类型,少用 STR_TO_DATE 做运行时转换
真正健壮的做法不是靠 STR_TO_DATE 救火,而是从源头控制:
- 入库前在应用层(Python/Java/PHP)做日期解析和校验,失败直接拦截,不传给 SQL
- 数据库字段类型尽量用
DATE或DATETIME,而非VARCHAR存日期字符串 - 如果必须解析字符串字段,先用
IS NULL或COALESCE包一层,避免NULL导致整个表达式失效,例如:COALESCE(STR_TO_DATE(date_str, '%Y-%m-%d'), '1970-01-01')
格式符记不全没关系,查 MySQL 官方文档的 STR_TO_DATE 页面就行;但得记住:它不报错,也不提醒,只默默给你一个 NULL。

















