STR_TO_DATE 是什么
把字符串按指定格式解析成日期或时间值,用于导入外部数据与清洗脏日期列。MySQL 用 STR_TO_DATE(str, fmt),解析失败返回 NULL 并产生告警;PostgreSQL 用 to_date 与 to_timestamp,遇到非法输入直接抛错,整条语句失败。
基本信息
| MySQL 语法 | STR_TO_DATE(str, 格式串),格式串用 %Y-%m-%d 这类占位符 |
|---|---|
| MySQL 常用占位 | %Y 四位年、%m 月、%d 日、%H 时、%i 分、%s 秒 |
| MySQL 失败行为 | 返回 NULL 并产生 warning,不中断语句 |
| PostgreSQL 语法 | to_date(str,'YYYY-MM-DD')、to_timestamp(str,'YYYY-MM-DD HH24:MI') |
| PostgreSQL 失败行为 | 直接抛错,语句中断 |
| 返回类型 | 格式串是否含时间部分决定得到 DATE 还是 DATETIME |
MySQL 解析示例
MySQL 解析示例
SELECT STR_TO_DATE('06/01/2024', '%m/%d/%Y'); -- 2024-06-01
SELECT STR_TO_DATE('2024-06-01 09:30', '%Y-%m-%d %H:%i'); -- 带时间的 DATETIME
SELECT STR_TO_DATE('20240601', '%Y%m%d'); -- 无分隔符也能解析
-- 解析失败返回 NULL 并产生 warning,不会报错
SELECT STR_TO_DATE('2024-13-01', '%Y-%m-%d'); -- NULL
-- 导入后务必统计 NULL 数量,确认没有静默丢数据PostgreSQL 解析示例
PostgreSQL 解析示例
SELECT to_date('06/01/2024', 'MM/DD/YYYY'); -- 2024-06-01
SELECT to_timestamp('2024-06-01 09:30', 'YYYY-MM-DD HH24:MI'); -- 带时间
-- 非法输入直接报错:invalid value "2024-13-01" for "MM"
SELECT to_date('2024-13-01', 'YYYY-MM-DD');
-- 需要容错时先过滤,例如 WHERE raw ~ '^\d{4}-\d{2}-\d{2}$'两库对照
| 项 | MySQL 8 | PostgreSQL |
|---|---|---|
| 日期解析 | STR_TO_DATE(str, fmt) | to_date(str, fmt) |
| 时间戳解析 | STR_TO_DATE 或 CAST | to_timestamp(str, fmt) |
| 格式占位 | %Y %m %d %H %i %s | YYYY MM DD HH24 MI SS |
| 非法输入 | 返回 NULL 并产生告警 | 抛错并中止语句 |
| 严格程度 | 相对宽松,可能解析出前缀 | 严格,格式必须匹配 |
典型使用场景
- 导入 CSV 或 Excel 导出的文本日期列
- 清洗历史数据里格式混乱的日期字段
- 对接外部系统:把 20240601 这类紧凑格式转成标准日期
- 数据校验:把可解析与不可解析的行分开核对
- 做区间查询前,先把字符串列规范成日期列
- 迁移预演:先在新库验证格式串是否都能解析
- 把日志里的时间字符串统一解析成标准时间列,便于后续按时间聚合
- 历史数据修复:先解析出正确值,再回写覆盖原来格式错误的列
MySQL 的宽松解析是双刃剑:'2024-13-01' 返回 NULL,而 '2024-06-01abc' 这类带尾巴的字符串可能被解析成功。导入之后既要统计 NULL 数量,也要抽样人工核对。
解析结果落在哪一列要匹配:格式串里带时分秒就得到 DATETIME,只写年月日得到 DATE。写进目标列之前确认字段类型,避免落库时被隐式截断掉时间部分。
不要在过滤条件里解析列:WHERE STR_TO_DATE(day_str, '%Y%m%d') = '2024-06-01' 会导致全表扫描。导入阶段先把字符串落成日期列,查询时直接过滤日期列。