主流SQL数据库(MySQL、SQL Server、Oracle、PostgreSQL、SQLite)
wptr33 2025-10-14 06:14 2 浏览
下面详细对比五大主流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适用于高频转换
实战应用中应根据:
- 数据来源的格式多样性
- 系统多语言支持需求
- 时区敏感度
选择适合的转换方案,并在应用层增加格式校验逻辑,从源头上减少非法日期输入。
相关推荐
- 深度剖析 MySQL 数据库索引失效场景与优化策略
-
在互联网软件开发领域,MySQL数据库凭借其开源、高效等特性被广泛应用。而索引,作为提升MySQL查询性能的关键利器,能大幅加速数据检索。然而,在实际开发中,即便精心创建了索引,却常常遭遇索引失...
- 15分钟,带你了解indexedDB,这个前端存储方案很重要!
-
原文来源于:程序员成长指北;作者:Django强哥如有侵权,联系删除最近在给前端班授课,在这次之前的最后一次课已经是在2年前,2年的时间,前端的变化很大,也是时候要更新课件了。整理客户端存储篇章时模糊...
- MySQL 面试总被问到的那些问题,你都懂了吗?
-
事务的四大特性是什么?首先得提一下ACID,这可是数据库事务的灵魂所在:原子性(Atomicity):要么全部成功,要么全部失败回滚。一致性(Consistency):确保数据在事务前后都处于一致状态...
- Java 字符串常见的操作_java字符串总结
-
在Java当中,为字符串类提供了丰富的操作方法,对于字符串,我们常见的操作就是:字符串的比较、查找、替换、拆分、截取以及其他的一些操作。在Java中,有String,StringBuffer和St...
- java学习分享:Java截取(提取)子字符串(substring())
-
在String中提供了两个截取字符串的方法,一个是从指定位置截取到字符串结尾,另一个是截取指定范围的内容。下面对这两种方法分别进行介绍。1.substring(intbeginIndex)形...
- 你必须知道的 7 个杀手级 JavaScript 单行代码
-
1.如果你需要一个临时的唯一ID,请生成随机字符串。这个例子将为你生成一个随机字符串:constrandomString=Math.random().toString(36).slice(2)...
- MySQL 索引失效:原因、场景与解决方案
-
在互联网软件开发领域,MySQL作为一款广泛使用的关系型数据库,其性能优化至关重要。而索引,作为提升MySQL查询性能的关键手段,一旦失效,会导致查询效率大幅下降,影响整个系统的性能。今天,就来...
- Axure9 教程:可模糊搜索的多选效果
-
一、交互效果说明1.点击话题列表中的话题选项,上方输入框内显示选择的话题标签,最多可选择5个标签,超出将有文字提示。2.点击输入框内已选择的话题标签的删除按钮,可以删除已选择的话题标签,并且该标签返回...
- JavaScript字符串操作方法大全,包含ES6方法
-
一、charAt()返回在指定位置的字符。...
- 为什么MySQL索引不生效?来看看这8个原因
-
在数据库优化中,最让人头疼的事情之一莫过于精心设计的索引没有发挥作用。为什么会出现这种情况?这篇文章带大家一起探讨一些常见原因,方便大家更好地理解MySQL查询优化器是如何选择索引的,以及在出现类...
- Kettle实现rabbitMQ的生产与消费_rabbitmq不支持顺序消费
-
文章目录一、Kettle为什么可以读取流数据?...
- MySQL高频函数Top10!数据分析效率翻倍,拒绝无效加班!
-
引言:为什么你的SQL代码又臭又长?“同事3行代码搞定的事,你写了30行?”“每次处理日期、字符串都抓狂,疯狂百度?”——不是你不努力,而是没掌握这些高频函数!本文精炼8年数据库开发经验,总结出10个...
- mysql的截取函数用法详解_mysql截取指定字符
-
substring()函数测试数据准备:用法:以下语法是mysql自动提示的1:substirng(str,pos):从指定位置开始截取一直到数据完成str:需要截取的字段的pos:开始截取的位置。从...
- MySQL函数:字符串如何截取_mysql 字符串截取函数
-
练习截取字符串函数(五个)mysql索引从1开始...
- 数据集成产品分析(一)_数据集成工具有哪些
-
编辑导语:数据集成产品是数据中台建设的第一环节,在构建数据中台或大数据系统时,首先要将企业内部各个业务系统的数据实现互联互通,从物理上打破数据孤岛。本文作者对数据集成产品进行了分析,一起来看一下吧。数...
- 一周热门
-
-
C# 13 和 .NET 9 全知道 :13 使用 ASP.NET Core 构建网站 (1)
-
程序员的开源月刊《HelloGitHub》第 71 期
-
详细介绍一下Redis的Watch机制,可以利用Watch机制来做什么?
-
如何将AI助手接入微信(打开ai手机助手)
-
SparkSQL——DataFrame的创建与使用
-
假如有100W个用户抢一张票,除了负载均衡办法,怎么支持高并发?
-
Java面试必考问题:什么是乐观锁与悲观锁
-
redission YYDS spring boot redission 使用
-
如何利用Redis进行事务处理呢? 如何利用redis进行事务处理呢英文
-
一文带你了解Redis与Memcached? redis与memcached的区别
-
- 最近发表
- 标签列表
-
- git pull (33)
- git fetch (35)
- mysql insert (35)
- mysql distinct (37)
- concat_ws (36)
- java continue (36)
- jenkins官网 (37)
- mysql 子查询 (37)
- python元组 (33)
- mybatis 分页 (35)
- vba split (37)
- redis watch (34)
- python list sort (37)
- nvarchar2 (34)
- mysql not null (36)
- hmset (35)
- python telnet (35)
- python readlines() 方法 (36)
- munmap (35)
- docker network create (35)
- redis 集合 (37)
- python sftp (37)
- setpriority (34)
- c语言 switch (34)
- git commit (34)