str_to_date要求格式字符串与输入字符串严格匹配,分隔符、年份位数、补零规则等必须一致,否则静默返回null;需清洗杂字符、避免索引失效、注意类型与时区影响。

STR_TO_DATE 用法和格式字符串必须严格匹配
STR_TO_DATE 不是模糊解析函数,它要求输入字符串和格式模板完全对齐。比如 '2023-05-12' 不能用 '%Y-%m-%d %H:%i:%s' 解析,因为字符串里没有时间部分,多出来的 %H:%i:%s 会导致返回 NULL。
常见错误现象:STR_TO_DATE('2023/05/12', '%Y-%m-%d') 返回 NULL —— 因为分隔符是 /,但格式写了 -。
- 日期分隔符(
-、/、.、空格)必须和字符串中的一致 - 年份用
%Y(4位)或%y(2位),混用会失败,比如'23-05-12'配%Y-%m-%d就不行 - 月份和日必须补零才匹配
%m和%d;非补零格式要用%c(月)、%e(日),例如STR_TO_DATE('2023-5-12', '%Y-%c-%e')
处理带中文或不规则字符串时先清洗再转换
MySQL 的 STR_TO_DATE 不识别“2023年5月12日”这类中文日期。直接传入会返回 NULL,且不会报错,容易被忽略。
使用场景:从日志或旧系统导出的字段含中文、括号、空格等杂字符。
- 用
REPLACE()或正则REGEXP_REPLACE()(MySQL 8.0+)清理:例如REGEXP_REPLACE(col, '[^0-9/-: ]', '')去掉非数字和基本分隔符 - 中文年月日可分步替换:
REPLACE(REPLACE(REPLACE(col, '年', '-'), '月', '-'), '日', '')→ 得到'2023-5-12',再配'%Y-%c-%e' - 注意:MySQL 5.7 不支持
REGEXP_REPLACE,只能靠嵌套REPLACE或在应用层处理
NULL 输入或解析失败时结果为 NULL,需主动判断
STR_TO_DATE 对任何不匹配的输入都静默返回 NULL,不像某些语言抛异常。这会让问题藏得深,尤其在 WHERE 或 JOIN 条件里误判数据存在性。
- 检查是否成功转换:用
IS NOT NULL判断,例如WHERE STR_TO_DATE(date_str, '%Y-%m-%d') IS NOT NULL - 避免在索引字段上直接套
STR_TO_DATE做查询条件——无法走索引,全表扫描风险高 - 如果字段长期用于日期过滤,建议新增一个
DATE类型列,用UPDATE ... SET new_date_col = STR_TO_DATE(old_str_col, '%Y-%m-%d')批量转换并建索引
时区和默认时间部分的影响常被忽略
STR_TO_DATE 解析结果是 DATE、DATETIME 或 TIME 类型值,但不带时区信息。更重要的是:它不会自动补全缺失的时间部分,而是设为 00:00:00(DATETIME)或 0000-00-00(DATE)。
- 输入
'2023-05-12'+ 格式'%Y-%m-%d'→ 结果是DATE类型的2023-05-12 - 输入
'2023-05-12'+ 格式'%Y-%m-%d %H:%i:%s'→ 结果是DATETIME类型的2023-05-12 00:00:00(不是报错) - 如果原字符串只有时间(如
'14:30:00'),用'%H:%i:%s'解析后得到TIME类型,参与日期运算前要小心类型隐式转换
SELECT STR_TO_DATE(...) 单独试一两条典型数据,别等到 UPDATE 或 INSERT SELECT 时才发现整批变 NULL。











