STR_TO_DATE()需严格匹配格式符与字符串,否则静默返回NULL;如%Y(4位年)误写为%y、%m(补零月)混用%c均导致失败,须用TRIM()预处理空格并配合COALESCE兜底。

MySQL 中用 STR_TO_DATE() 解析字符串日期
MySQL 不支持直接把 '2023-10-05' 这类字符串当日期用,必须显式转换。最可靠的是 STR_TO_DATE(),它按指定格式从字符串提取日期值。
常见错误是格式符写错:比如把 %Y(4位年)写成 %y(2位年),或把 %m(补零月)和 %c(无补零月)混用。一旦格式不匹配,函数返回 NULL,且不报错,容易漏查。
-
STR_TO_DATE('2023/10/05', '%Y/%m/%d')→ 正确解析为2023-10-05 -
STR_TO_DATE('05-OCT-2023', '%d-%b-%Y')→ 注意%b是英文缩写,oct必须小写才匹配(取决于系统 locale) - 若原始字段是
varchar且含空格或异常值(如' '或'N/A'),先用TRIM()和条件过滤,否则整行转成NULL
PostgreSQL 中用 TO_DATE() 处理非标准字符串
PostgreSQL 的 TO_DATE() 更严格,格式模板必须与输入完全一致,且不自动忽略前后空格。它也不接受模糊格式(比如 'YYYYMMDD' 不能简写成 'YYYYMD')。
典型陷阱是误用 CAST('20231005' AS DATE) —— 这会失败,因为 PostgreSQL 默认只认 ISO 格式('2023-10-05')或带分隔符的变体。
-
TO_DATE('20231005', 'YYYYMMDD')→ 返回2023-10-05,注意模板字母必须大写 -
TO_DATE('5-Oct-2023', 'DD-Mon-YYYY')→Mon匹配英文缩写,大小写敏感;中文环境需改用to_date(..., 'DD-TMmon-YYYY')并确保 lc_time 设置正确 - 如果数据中混有不同格式(如部分是
'YYYY/MM/DD',部分是'DD.MM.YYYY'),没法单条 SQL 统一转换,得先分类或用CASE WHEN分支处理
SQL Server 里靠 CONVERT() 或 TRY_CONVERT() 防止报错
SQL Server 的 CONVERT() 需要 style 参数(如 120 对应 yyyy-mm-dd hh:mi:ss),但对非标准格式支持弱。更安全的是 TRY_CONVERT(date, ...):转换失败时返回 NULL 而非中断查询。
很多人直接用 CAST(col AS date),但它在遇到 '2023/10/05'(斜杠分隔)时可能因语言设置(DATEFORMAT)出错——比如设成 dmy 时,'10/05/2023' 会被当成 10日5月,而非10月5日。
-
TRY_CONVERT(date, '2023-10-05')→ 安全,推荐用于清洗阶段 -
CONVERT(date, '05/10/2023', 103)→103表示dd/mm/yyyy格式,避免依赖当前 session 的DATEFORMAT - 若原始字符串含时间(如
'2023-10-05 14:30')且只要日期部分,用CAST(TRY_CONVERT(datetime2, col) AS date)比截字符串更可靠
跨数据库可移植性差,别硬套同一写法
没有一种语法能在 MySQL、PostgreSQL、SQL Server 里通用。STR_TO_DATE()、TO_DATE()、TRY_CONVERT() 各自绑定引擎,连参数顺序和占位符都不同。试图写“一次编写、到处运行”的日期转换逻辑,基本会翻车。
真正该做的是:在 ETL 或应用层统一清洗,或者在 SQL 层明确标注方言依赖。比如视图里写 /* pg */ TO_DATE(...) 或加注释说明适用环境。临时查数据时,宁可多花半分钟查对应文档,也别凭印象改格式符。

















