主流SQL数据库(MySQL、SQL Server、Oracle、PostgreSQL、SQLite)

2026年01月20日/ 浏览 8

下面详细对比五大主流SQL数据库(MySQL、SQL Server、Oracle、PostgreSQL、SQLite)字符串转日期函数的基础语法,仅供参考。

一、字符串转日期:需求场景与处理难点概述

1. 为什么需要字符串转日期?

数据清洗:处理CSV导入、API接口返回的非标准日期数据动态筛选:WHERE条件中的日期范围过滤(2023-07-05 → 标准日期)类型转换:确保时间计算函数正确执行(如DATE_ADD())格式归一化:统一不同来源的日期表达形式

2. 面临的挑战

格式兼容:07/05/2023是7月5日还是5月7日?容错处理:2023-02-30该如何处理?时区陷阱:2023-07-05T14:30+08:00如何解析?性能差异:函数与隐式转换的效率对比

二、主流SQL数据库字符串转日期函数基础语法解析

1. MySQL

基础语法

STR_TO_DATE(str, format) 参数str:日期字符串(VARCHAR/CHAR)format:格式模板(与DATE_FORMAT()兼容)返回值:成功返回DATE/DATETIME;失败返回NULL特点:严格匹配格式模板,支持自定义文本

格式符对照表

占位符

含义

输入示例

%Y

四位数年份

2023

%y

两位数年份

23

%m

月(01-12)

07

%c

月(1-12)

7

%d

日(01-31)

05

%H

时(00-23)

14

%i

分(00-59)

30

%p

AM/PM

PM

模拟示例

-- 创建用户输入表 CREATE TABLE user_events ( event_id INT PRIMARY KEY AUTO_INCREMENT, raw_date VARCHAR(50) NOT NULL COMMENT 原始日期字符串, event_desc VARCHAR(100) ); INSERT INTO user_events (raw_date, event_desc) VALUES (20230705, 基础数字格式), (Jul 5, 2023 2:30 PM, 英文文本格式), (2023年7月5日, 中文格式), (05-07-2023, 日-月-年格式); -- 转换字符串为日期 SELECT event_id, raw_date AS original, STR_TO_DATE(raw_date, %Y%m%d) AS fmt1, -- 20230705 → 2023-07-05 STR_TO_DATE(raw_date, %b %d, %Y %l:%i %p) AS fmt2, -- Jul 5, 2023 → 2023-07-05 14:30:00 STR_TO_DATE(raw_date, %Y年%m月%d日) AS fmt3, -- 中文 → 2023-07-05 STR_TO_DATE(raw_date, %d-%m-%Y) AS fmt4 -- 05-07-2023 → 2023-07-05 FROM user_events;

输出结果

event_id | original | fmt1 | fmt2 | fmt3 | fmt4 --------|----------------------|--------------|-----------------------|--------------|------------- 1 | 20230705 | 2023-07-05 | NULL | NULL | NULL 2 | Jul 5, 2023 2:30 PM | NULL | 2023-07-05 14:30:00 | NULL | NULL 3 | 2023年7月5日 | NULL | NULL | 2023-07-05 | NULL 4 | 05-07-2023 | NULL | NULL | NULL | 2023-07-05

2. SQL Server

基础语法

-- 方案1:CONVERT + 样式代码 CONVERT(DATETIME, string, style_code) -- 方案2:PARSE + 区域文化 PARSE(string AS DATETIME USING culture) 参数style_code:预定义数字编码(见下表)culture:区域设置(如en-US)返回值:DATETIME类型,格式错误报错特点:CONVERT性能较优,PARSE支持多语言

常用样式代码

代码

格式

示例字符串

101

mm/dd/yyyy

07/05/2023

103

dd/mm/yyyy

05/07/2023

112

yyyymmdd

20230705

120

ISO8601

2023-07-05 14:30

模拟示例

-- 创建国际订单表 CREATE TABLE global_orders ( order_id INT IDENTITY PRIMARY KEY, raw_date VARCHAR(50), country_code CHAR(2) ); INSERT INTO global_orders (raw_date, country_code) VALUES (2023-07-05, US), (05/07/2023, FR), -- 法式日/月/年 (07/05/2023, US), -- 美式月/日/年 (20230705, CN); -- 多方案转换 SELECT order_id, raw_date, -- 自动识别格式 TRY_CAST(raw_date AS DATETIME) AS auto_cast, -- 指定区域解析 PARSE(raw_date AS DATETIME USING en-US) AS parse_us, PARSE(raw_date AS DATETIME USING fr-FR) AS parse_fr, -- 传统转换 CONVERT(DATETIME, raw_date, 120) AS fmt_iso, CONVERT(DATETIME, raw_date, 103) AS fmt_european -- dd/mm/yyyy FROM global_orders;

输出结果

order_id | raw_date | auto_cast | parse_us | parse_fr | fmt_iso | fmt_european --------|----------------|----------------------|----------------------|----------------------|----------------------|------------------- 1 | 2023-07-05 | 2023-07-05 00:00:00 | 2023-07-05 00:00:00 | 2023-07-05 00:00:00 | 2023-07-05 00:00:00 | NULL 2 | 05/07/2023 | NULL | 2023-05-07 00:00:00 | 2023-07-05 00:00:00 | NULL | 2023-07-05 00:00:00 3 | 07/05/2023 | NULL | 2023-07-05 00:00:00 | 2023-05-07 00:00:00 | NULL | NULL 4 | 20230705 | NULL | NULL | NULL | NULL | NULL

3. Oracle

基础语法

TO_DATE(string, format [, nls_params]) 参数format:格式模板(与TO_CHAR()兼容)nls_params:语言参数(如NLS_DATE_LANGUAGE=JAPANESE)返回值:DATE类型,错误报错特点:直接处理时区,支持复杂文本格式

关键格式符

占位符

含义

输入示例

YYYY

四位数年份

2023

MONTH

月份全名

JULY

MON

月份缩写

JUL

DD

日期(01-31)

05

HH24

24小时制

14

模拟示例

-- 创建多语言日期表 CREATE TABLE multilingual_dates ( record_id NUMBER GENERATED ALWAYS AS IDENTITY PRIMARY KEY, raw_date VARCHAR2(50), lang VARCHAR2(20) ); INSERT INTO multilingual_dates (raw_date, lang) VALUES (2023年7月5日, zh), (5 Juillet 2023, fr), (2023-07-05 14:30:45, iso), (July 5, 2023, en); -- 多语言转换 SELECT record_id, raw_date, TO_DATE(raw_date, YYYY"年"MM"月"DD"日") AS fmt_chinese, TO_DATE(raw_date, DD Month YYYY, NLS_DATE_LANGUAGE=FRENCH) AS fmt_french, TO_DATE(raw_date, YYYY-MM-DD HH24:MI:SS) AS fmt_iso, TO_DATE(raw_date, Month DD, YYYY, NLS_DATE_LANGUAGE=AMERICAN) AS fmt_english FROM multilingual_dates;

输出结果

record_id | raw_date | fmt_chinese | fmt_french | fmt_iso | fmt_english ---------|-----------------------|----------------|----------------|----------------------|-------------- 1 | 2023年7月5日 | 2023-07-05 | NULL | NULL | NULL 2 | 5 Juillet 2023 | NULL | 2023-07-05 | NULL | NULL 3 | 2023-07-05 14:30:45 | NULL | NULL | 2023-07-05 14:30:45 | NULL 4 | July 5, 2023 | NULL | NULL | NULL | 2023-07-05

4. PostgreSQL

基础语法

TO_DATE(string, format) 参数format:类似Oracle的模板返回值:DATE类型,错误报错特点:兼容ISO8601时区,需单独处理时间部分

特殊格式符

占位符

含义

输入示例

IYYY

ISO年

2023

IDDD

ISO年日

186

TZ

时区缩写

PST

模拟示例

-- 创建带时区数据表 CREATE TABLE event_logs ( log_id SERIAL PRIMARY KEY, raw_timestamp VARCHAR(50), timezone VARCHAR(20) ); INSERT INTO event_logs (raw_timestamp, timezone) VALUES (20230705, UTC), (2023-07-05T14:30:45Z, UTC), (July 5, 2023 10:30 AM EST, America/New_York); -- 转换含时区字符串 SELECT log_id, raw_timestamp, TO_DATE(raw_timestamp, YYYYMMDD) AS date_only, -- 拆解带时区字符串 (TO_TIMESTAMP(raw_timestamp, YYYY-MM-DD"T"HH24:MI:SS"Z"))::DATE AS iso_date, (TO_TIMESTAMP( SPLIT_PART(raw_timestamp, , 1) || || SPLIT_PART(raw_timestamp, , 2), Month DD, YYYY HH:MI AM ) AT TIME ZONE SPLIT_PART(raw_timestamp, , 5))::DATE AS tz_date FROM event_logs;

输出结果

log_id | raw_timestamp | date_only | iso_date | tz_date ------|----------------------------|-------------|--------------|------------ 1 | 20230705 | 2023-07-05 | NULL | NULL 2 | 2023-07-05T14:30:45Z | NULL | 2023-07-05 | NULL 3 | July 5, 2023 10:30 AM EST | NULL | NULL | 2023-07-05

5. SQLite

基础语法

-- 隐式转换 DATE(timestring) -- 显式格式化 STRFTIME(%Y-%m-%d, timestring) 参数timestring:支持ISO8601/Julian等格式返回值:TEXT类型(SQLite无原生日期类型)特点:自动识别有限格式,需手动处理复杂字符串

支持格式类型

格式

示例

YYYY-MM-DD

2023-07-05

YYYYMMDD HH:MM

20230705 14:30

now

当前时间

模拟示例

-- 创建混合格式表 CREATE TABLE mixed_formats ( id INTEGER PRIMARY KEY, raw_date TEXT ); INSERT INTO mixed_formats VALUES (1, 2023-07-05), (2, 20230705), (3, 07/05/2023), -- 美式格式 (4, Jul 5, 2023); -- 转换尝试 SELECT id, raw_date, DATE(raw_date) AS auto_date, -- 只能识别标准格式 -- 手动处理美式日期 CASE WHEN raw_date GLOB */*/* THEN DATE( SUBSTR(raw_date, 7, 4) || - || SUBSTR(raw_date, 1, 2) || - || SUBSTR(raw_date, 4, 2) ) ELSE NULL END AS manual_us_format, -- 文本格式需预先转换 REPLACE(REPLACE(REPLACE( raw_date, Jan, 01), Jul, 07) AS text_to_iso FROM mixed_formats;

输出结果

id | raw_date | auto_date | manual_us_format | text_to_iso ---|----------------|--------------|------------------|------------ 1 | 2023-07-05 | 2023-07-05 | NULL | 2023-07-05 2 | 20230705 | NULL | NULL | 20230705 3 | 07/05/2023 | NULL | 2023-07-05 | 07/05/2023 4 | Jul 5, 2023 | NULL | NULL | 07 5, 2023

三、跨数据库对比总结表

能力

MySQL

SQL Server

Oracle

PostgreSQL

SQLite

核心函数

STR_TO_DATE

CONVERT/PARSE

TO_DATE

TO_DATE

DATE()

自定义格式

支持

仅PARSE

支持

支持

不支持

多语言支持

有限

PARSE支持

完善

依赖locale

时区处理能力

有限

原生支持

完善

容错机制

返回NULL

TRY_CAST

异常报错

异常报错

返回NULL

存储类型

DATE/DATETIME

DATETIME

DATE

DATE

TEXT

性能表现

较优

CONVERT较优

较优

中等

较低

(表格可左右滚动)

四、实战避坑指南

陷阱1:隐式转换的数据库差异

-- SQL Server 能自动转换 SELECT * FROM orders WHERE order_date > 2023-07-01 -- Oracle 需要显式转换 SELECT * FROM orders WHERE order_date > TO_DATE(2023-07-01,YYYY-MM-DD)

陷阱2:闰年特殊日期处理

-- 所有数据库均无法直接转换不存在的日期 SELECT STR_TO_DATE(2023-02-30, %Y-%m-%d); -- MySQL → NULL SELECT TO_DATE(20230230, YYYYMMDD); -- Oracle → 报错 -- 防御性写法 SELECT CASE WHEN ISDATE(2023-02-30) = 1 THEN CONVERT(DATE, 2023-02-30) ELSE NULL END;

陷阱3:时区丢失问题

-- PostgreSQL中忽略时区转换 SELECT TO_DATE(2023-07-05T14:30:45+08:00, YYYY-MM-DD); -- 输出:2023-07-05(丢失时区) -- 正确方案 SELECT (TO_TIMESTAMP(2023-07-05T14:30:45+08:00, YYYY-MM-DD"T"HH24:MI:SSOF) AT TIME ZONE UTC)::DATE;

五、可靠实践方案

方案1:输入层验证前置

graph LR A[原始字符串] --> B{格式预校验} B -->|合法| C[DB层转换] B -->|非法| D[应用层拦截]

方案2:统一转换函数封装

-- PostgreSQL示例:创建安全转换函数 CREATE OR REPLACE FUNCTION safe_to_date(str TEXT, fmt TEXT) RETURNS DATE AS $$ BEGIN RETURN TO_DATE(str, fmt); EXCEPTION WHEN others THEN RETURN NULL; END; $$ LANGUAGE plpgsql;

方案3:区域格式显式声明

-- SQL Server多语言安全解析 SELECT PARSE(raw_date AS DATE USING en-US) FROM international_data

方案4:存储时区原始数据

-- 数据库设计建议 CREATE TABLE global_events ( event_id INT PRIMARY KEY, event_utc TIMESTAMP, -- 存UTC时间 raw_timezone VARCHAR(10) -- 存原始时区 );

总结

字符串转日期是SQL数据处理的高频操作,各SQL数据库的核心差异在于:

灵活性:Oracle/PostgreSQL支持复杂文本,SQLite依赖固定格式安全性:TRY_CAST/PARSE优于直接转换扩展性:多语言场景优先考虑Oracle/PARSE性能:CONVERT/STR_TO_DATE适用于高频转换

实战应用中应根据:

数据来源的格式多样性系统多语言支持需求时区敏感度

选择适合的转换方案,并在应用层增加格式校验逻辑,从源头上减少非法日期输入。

picture loss