cast和convert在mysql中对非法日期格式(如'2025/01/01')转换会直接报错,因mysql先校验字符串是否符合'yyyy-mm-dd'字面量规范,再执行转换;真正可靠的是str_to_date()配合格式模板。

MySQL里用CAST/CONVERT转日期根本不管用
直接说结论:CAST 和 CONVERT 在 MySQL 中对非法日期字符串做类型转换,**不会修复格式或逻辑错误,只会触发校验失败**。比如 CAST('2025/01/01' AS DATE) 仍会报 Truncated incorrect date value: '2025/01/01',因为 MySQL 在类型转换前就按严格模式拒绝了斜杠分隔符。
这不是函数写错了,是执行顺序问题:MySQL 先校验字符串是否为合法日期字面量(要求必须是 'YYYY-MM-DD'),再走转换逻辑。斜杠、点、空格、零值等,全在第一步就被拦下。
- 常见错误现象:
INSERT INTO t(d) VALUES (CAST('2025.01.01' AS DATE));→ 报错 - 真正能过的形式只有:
CAST('2025-01-01' AS DATE)、CONVERT('2025-01-01', DATE) - 即使源字段是
VARCHAR,只要存的是'2025/01/01',CAST(vcol AS DATE)依然失败 - 性能影响:这类转换本身不慢,但失败时会中断整个语句,还可能引发事务回滚
PostgreSQL中CONVERT不是标准函数,别乱套用
PostgreSQL 没有 CONVERT 函数,也没有 CAST(... AS DATE) 对非法字符串的容错能力。它更严格——连 TO_DATE() 都要求显式指定格式,否则直接报错 invalid input syntax for type date。
你看到的“加 ::timestamp 就行”,其实是 PostgreSQL 的类型强制转换语法,本质是告诉解析器:“我确认这个文本可转成 timestamp”,但它**不负责修正格式**。
- 正确写法:
'2025-01-01'::date、TO_DATE('01/01/2025', 'DD/MM/YYYY') - 错误写法:
'2025/01/01'::date→ 报错;CAST('2025/01/01' AS DATE)→ 同样报错 - 容易踩的坑:MyBatis 或 JDBC 里用了
#{xxx,jdbcType=DATE},但传入的是"2025/01/01"字符串,PostgreSQL 会拒收,不因 JDBC Type 声明而自动标准化
真正该用STR_TO_DATE而不是CAST
当输入是不可控格式(如前端送来的 "2025/01/01"、"01-01-2025"、"2025.01.01")时,MySQL 唯一靠谱的函数是 STR_TO_DATE(),它明确接受格式模板,把字符串按规则解析成日期。
- 能成功:
STR_TO_DATE('2025/01/01', '%Y/%m/%d')→2025-01-01 - 也能处理零值:
STR_TO_DATE('0000-00-00', '%Y-%m-%d')(前提是 SQL Mode 允许) - 注意:返回
NULL而不是报错,所以插入前最好加IS NOT NULL判断 - 性能提示:比
CAST略慢,但这是格式清洗的合理代价;别在 WHERE 条件里对大字段反复调用它
应用层不预处理,数据库层永远救不了格式乱码
所有 STR_TO_DATE、TO_DATE、CAST 都解决不了编码污染、截断、空格混入、BOM 头等问题。比如从 Excel 导出的 CSV 里实际是 "\ufeff2025/01/01",任何日期函数都先报错。
- 真实场景中,90% 的“日期插入失败”根源不在 SQL 写法,而在上游数据没清洗
- Java 侧建议:用
LocalDate.parse(str, DateTimeFormatter.ofPattern("..."))提前校验并标准化 - Python 侧建议:用
dateutil.parser.parse()+.strftime('%Y-%m-%d')统一输出 - 最易被忽略的一点:MySQL 客户端连接参数
character_set_client若非utf8mb4,某些带 Unicode 分隔符的日期字符串会变成乱码再参与解析










