主流SQL数据库日期转字符串的语法(MySQL、SQL Server、Oracle等
wptr33 2025-10-14 06:13 20 浏览
下面对主流SQL数据库(MySQL、SQL Server、Oracle、PostgreSQL、SQLite)日期转字符串的方法进行详细对比拆解,包含基础语法结构、参数解析、返回值说明及完整模拟示例,仅供参考。
一、基本概念
1. 作用
将日期(DATE)、时间(TIME)或日期时间(DATETIME/TIMESTAMP)类型的值按照指定的格式转换为字符串。这在生成报表、数据导出、日志记录、API接口响应、日期部分提取等场景中比较常见。
2. 差异点
- 函数命名差异:各数据库使用不同的函数名(如DATE_FORMAT、TO_CHAR、CONVERT等)
- 格式字符串定义:各数据库使用不同的占位符(如%Y、YYYY、yyyy等代表四位年份)
- 返回值类型:通常为字符串类型(VARCHAR、TEXT等)
二、语法对比解析
1. MySQL
基础语法
DATE_FORMAT(date, format)
- 参数
- date:日期/时间值(DATE/DATETIME/TIMESTAMP)
- format:格式字符串(使用%前缀的占位符)
- 返回值:格式化后的字符串(VARCHAR)
格式符拆解
占位符 | 含义 | 示例输出 |
%Y | 四位年份 | 2023 |
%y | 两位年份 | 23 |
%m | 两位月份(01-12) | 07 |
%c | 月份(1-12) | 7 |
%d | 两位日期(01-31) | 05 |
%e | 日期(1-31) | 5 |
%H | 24小时制小时 | 14 |
%h | 12小时制小时 | 02 |
%i | 分钟(00-59) | 05 |
%s | 秒(00-59) | 30 |
%p | AM/PM | PM |
%W | 完整星期名 | Monday |
%a | 缩写星期名 | Mon |
%M | 完整月份名 | July |
%b | 缩写月份名 | Jul |
模拟示例
-- 创建订单表
CREATE TABLE orders (
order_id INT PRIMARY KEY AUTO_INCREMENT,
order_date DATETIME NOT NULL,
amount DECIMAL(10,2)
);
-- 插入测试数据
INSERT INTO orders (order_date, amount) VALUES
('2023-07-05 14:30:45', 99.99),
('2023-12-25 09:15:30', 149.50),
(NOW(), 75.25); -- 当前时间
-- 格式化日期输出
SELECT
order_id,
DATE_FORMAT(order_date, '%Y-%m-%d') AS order_date_short,
DATE_FORMAT(order_date, '%W, %M %e, %Y %h:%i %p') AS order_date_long,
DATE_FORMAT(order_date, '订单日期:%Y年%m月%d日') AS order_date_cn
FROM orders;
输出结果:
order_id | order_date_short | order_date_long | order_date_cn
---------|------------------|------------------------------|-------------------
1 | 2023-07-05 | Wednesday, July 5, 2023 02:30 PM | 订单日期:2023年07月05日
2 | 2023-12-25 | Monday, December 25, 2023 09:15 AM | 订单日期:2023年12月25日
3 | 2023-08-15 | Tuesday, August 15, 2023 10:45 AM | 订单日期:2023年08月15日
2. SQL Server
基础语法
-- 传统方法
CONVERT(VARCHAR, date, style_code)
-- 现代方法(2012+)
FORMAT(date, format [, culture])
- 参数
- date:日期值
- format:.NET风格格式字符串
- culture(可选):区域设置(如'zh-CN')
- VARCHAR:目标类型
- date:日期值
- style_code:预定义格式代码
- CONVERT:
- FORMAT:
- 返回值:格式化字符串(NVARCHAR)
CONVERT样式代码:
代码 | 格式 | 示例 |
101 | mm/dd/yyyy | 07/05/2023 |
102 | yyyy.mm.dd | 2023.07.05 |
103 | dd/mm/yyyy | 05/07/2023 |
104 | dd.mm.yyyy | 05.07.2023 |
105 | dd-mm-yyyy | 05-07-2023 |
112 | yyyymmdd | 20230705 |
114 | hh:mi:ss:mmm(24h) | 14:30:45:000 |
120 | yyyy-mm-dd hh:mi:ss | 2023-07-05 14:30:45 |
FORMAT格式符:
占位符 | 含义 | 示例 |
yyyy | 四位年份 | 2023 |
MM | 两位月份 | 07 |
dd | 两位日期 | 05 |
HH | 24小时制小时 | 14 |
hh | 12小时制小时 | 02 |
mm | 分钟 | 30 |
ss | 秒 | 45 |
tt | AM/PM | PM |
dddd | 完整星期名 | Wednesday |
MMMM | 完整月份名 | July |
模拟示例
-- 创建日志表
CREATE TABLE server_logs (
log_id INT IDENTITY PRIMARY KEY,
log_time DATETIME,
message NVARCHAR(200)
);
INSERT INTO server_logs (log_time, message) VALUES
('2023-07-05T14:30:45', 'Server started'),
(GETDATE(), 'User login');
-- 传统CONVERT方法
SELECT
log_id,
CONVERT(VARCHAR, log_time, 120) AS iso_format,
CONVERT(VARCHAR, log_time, 106) AS text_format -- dd mon yyyy
FROM server_logs;
-- 现代FORMAT方法
SELECT
log_id,
FORMAT(log_time, 'yyyy-MM-dd HH:mm:ss') AS iso_format,
FORMAT(log_time, 'dddd, MMMM dd, yyyy hh:mm tt') AS long_format,
FORMAT(log_time, 'yyyy年MM月dd日 HH时mm分', 'zh-CN') AS cn_format
FROM server_logs;
输出结果:
log_id | iso_format | long_format | cn_format
-------|----------------------|----------------------------------|-------------------
1 | 2023-07-05 14:30:45 | Wednesday, July 05, 2023 02:30 PM | 2023年07月05日 14时30分
2 | 2023-08-15 10:45:30 | Tuesday, August 15, 2023 10:45 AM | 2023年08月15日 10时45分
3. Oracle
基础语法
TO_CHAR(date, format [, nls_params])
- 参数
- date:DATE/TIMESTAMP值
- format:格式字符串
- nls_params(可选):语言设置(如'NLS_DATE_LANGUAGE=FRENCH')
- 返回值:格式化字符串(VARCHAR2)
格式符拆解:
占位符 | 含义 | 示例 |
YYYY | 四位年份 | 2023 |
YEAR | 年份英文拼写 | TWENTY-THREE |
MM | 两位月份 | 07 |
MON | 缩写月份名 | JUL |
MONTH | 完整月份名 | JULY |
DD | 两位日期 | 05 |
DDD | 年内的天数 | 186 |
HH24 | 24小时制小时 | 14 |
HH12 | 12小时制小时 | 02 |
MI | 分钟 | 30 |
SS | 秒 | 45 |
AM | AM/PM | PM |
DAY | 完整星期名 | WEDNESDAY |
DY | 缩写星期名 | WED |
模拟示例
-- 创建员工表
CREATE TABLE employees (
emp_id NUMBER PRIMARY KEY,
hire_date DATE,
salary NUMBER
);
INSERT INTO employees VALUES
(101, TO_DATE('2023-07-05', 'YYYY-MM-DD'), 5000),
(102, SYSDATE, 6000); -- 当前日期
-- 基础格式化
SELECT
emp_id,
TO_CHAR(hire_date, 'YYYY-MM-DD') AS iso_date,
TO_CHAR(hire_date, 'DD/MM/YYYY HH24:MI') AS eu_format
FROM employees;
-- 高级格式化(带语言参数)
SELECT
emp_id,
TO_CHAR(hire_date, 'YEAR-MONTH-DD') AS text_date, -- TWENTY-THREE-JULY-05
TO_CHAR(hire_date, 'Day, DD Month YYYY', 'NLS_DATE_LANGUAGE=FRENCH') AS french_date,
TO_CHAR(hire_date, '"入职日期:"YYYY"年"MM"月"DD"日"') AS cn_custom
FROM employees;
输出结果:
emp_id | iso_date | eu_format | text_date | french_date | cn_custom
-------|-------------|-------------------|-------------------------|------------------------------|-------------------
101 | 2023-07-05 | 05/07/2023 00:00 | TWENTY-THREE-JULY-05 | Mercredi, 05 Juillet 2023 | 入职日期:2023年07月05日
102 | 2023-08-15 | 15/08/2023 00:00 | TWENTY-THREE-AUGUST-15 | Mardi, 15 Ao^ut 2023 | 入职日期:2023年08月15日
4. PostgreSQL
基础语法
TO_CHAR(timestamp, format)
- 参数
- timestamp:DATE/TIMESTAMP/TIMESTAMPTZ值
- format:格式字符串(类似Oracle)
- 返回值:格式化字符串(TEXT)
格式符(与Oracle高度兼容):
占位符 | 含义 | 示例 |
YYYY | 四位年份 | 2023 |
MM | 两位月份 | 07 |
DD | 两位日期 | 05 |
HH24 | 24小时制小时 | 14 |
MI | 分钟 | 30 |
SS | 秒 | 45 |
AM | AM/PM | PM |
Day | 完整星期名 | Wednesday |
Mon | 缩写月份名 | Jul |
FMDay | 无空格星期名 | Wednesday |
"文本" | 原样输出文本 | "Date:" |
模拟示例
-- 创建事件表
CREATE TABLE events (
event_id SERIAL PRIMARY KEY,
event_name VARCHAR(100),
event_time TIMESTAMPTZ
);
INSERT INTO events (event_name, event_time) VALUES
('Conference', '2023-07-05 14:30:45+00'),
('Workshop', NOW());
-- 基础格式化
SELECT
event_id,
TO_CHAR(event_time, 'YYYY-MM-DD HH24:MI:SS') AS iso_format,
TO_CHAR(event_time, 'FMDay, FMMonth DD, YYYY') AS long_date -- FM去除填充空格
FROM events;
-- 时区转换+格式化
SELECT
event_id,
TO_CHAR(event_time AT TIME ZONE 'Asia/Shanghai',
'YYYY-MM-DD HH24:MI:SS TZ') AS shanghai_time
FROM events;
输出结果:
event_id | iso_format | long_date | shanghai_time
---------|----------------------|-----------------------------|-------------------------
1 | 2023-07-05 14:30:45 | Wednesday, July 5, 2023 | 2023-07-05 22:30:45 CST
2 | 2023-08-15 03:45:10 | Tuesday, August 15, 2023 | 2023-08-15 11:45:10 CST
5. SQLite
基础语法
STRFTIME(format, timestring [, modifier...])
- 参数
- format:格式字符串(%前缀)
- timestring:日期字符串(ISO8601格式)
- modifier:时间修饰符(如'+1 day')
- 返回值:格式化字符串(TEXT)
格式符拆解:
占位符 | 含义 | 示例 |
%Y | 四位年份 | 2023 |
%m | 两位月份 | 07 |
%d | 两位日期 | 05 |
%H | 24小时制小时 | 14 |
%M | 分钟 | 30 |
%S | 秒 | 45 |
%w | 星期数字(0-6) | 3(周三) |
%j | 年内的天数 | 186 |
%W | 年内的周数 | 27 |
%s | Unix时间戳 | 1688567445 |
模拟示例
-- 创建会议表
CREATE TABLE meetings (
meeting_id INTEGER PRIMARY KEY,
title TEXT,
start_time TEXT, -- ISO8601格式存储
end_time TEXT
);
INSERT INTO meetings VALUES
(1, 'Q3 Planning', '2023-07-05 14:30:00', '2023-07-05 16:00:00'),
(2, 'Team Sync', datetime('now'), datetime('now', '+1 hour'));
-- 基础格式化
SELECT
meeting_id,
STRFTIME('%Y-%m-%d', start_time) AS short_date,
STRFTIME('%H:%M', start_time) AS start_time_only
FROM meetings;
-- 高级格式化
SELECT
title,
STRFTIME('%Y年%m月%d日 %H时%M分', start_time) AS cn_start,
STRFTIME('会议时长:%H小时%M分钟',
STRFTIME('%s', end_time) - STRFTIME('%s', start_time),
'unixepoch') AS duration -- 计算持续时间
FROM meetings;
输出结果:
title | cn_start | duration
------------|-----------------------|-------------------
Q3 Planning | 2023年07月05日 14时30分 | 会议时长:01小时30分钟
Team Sync | 2023年08月15日 11时45分 | 会议时长:01小时00分钟
三、跨数据库对比总结表
特性 | MySQL | SQL Server | Oracle | PostgreSQL | SQLite |
主要函数 | DATE_FORMAT | CONVERT/FORMAT | TO_CHAR | TO_CHAR | STRFTIME |
格式前缀 | % | 无/.NET格式 | 无 | 无 | % |
语言本地化 | 有限 | FORMAT支持 | TO_CHAR支持 | 有限 | 无 |
时区处理 | 无 | 有限 | 有 | 完善 | 无 |
数字填充 | 自动补零 | 自动补零 | 自动补零 | 自动补零 | 自动补零 |
文本输出 | 支持 | 支持 | 支持 | 支持 | 支持 |
Unix时间戳 | 不支持 | 不支持 | 不支持 | 不支持 | 支持 |
(表格可左右滚动)
四、进阶应用示例
场景:生成多语言报表
-- Oracle示例(支持多语言切换)
SELECT
employee_id,
TO_CHAR(hire_date, 'YYYY"年"MM"月"DD"日"', 'NLS_DATE_LANGUAGE=TRADITIONAL CHINESE') AS zh_date,
TO_CHAR(hire_date, 'Month DD, YYYY', 'NLS_DATE_LANGUAGE=JAPANESE') AS jp_date,
TO_CHAR(hire_date, 'DD Month YYYY', 'NLS_DATE_LANGUAGE=FRENCH') AS fr_date
FROM employees;
场景:动态SQL生成
-- SQL Server示例(根据参数动态格式化)
DECLARE @formatStyle INT = 103; -- dd/mm/yyyy
SELECT
order_id,
CONVERT(VARCHAR, order_date, @formatStyle) AS formatted_date
FROM orders;
五、避坑指南
- 时区陷阱-- PostgreSQL错误示例(忽略时区)
SELECT TO_CHAR('2023-07-05 14:30:45+00'::TIMESTAMP, 'YYYY-MM-DD HH24:MI:SS');
-- 输出:2023-07-05 14:30:45(丢失时区信息)
-- 正确做法
SELECT TO_CHAR('2023-07-05 14:30:45+00'::TIMESTAMPTZ AT TIME ZONE 'Asia/Tokyo', 'YYYY-MM-DD HH24:MI:SS');
-- 输出:2023-07-05 23:30:45 - 性能陷阱-- MySQL错误示例(在WHERE中使用格式化)
SELECT * FROM logs
WHERE DATE_FORMAT(log_time, '%Y-%m-%d') = '2023-07-05';
-- 导致全表扫描
-- 正确做法(使用范围查询)
SELECT * FROM logs
WHERE log_time >= '2023-07-05'
AND log_time < '2023-07-06'; - 本地化陷阱-- Oracle月份填充问题
SELECT TO_CHAR(SYSDATE, 'Month') FROM dual;
-- 输出:'August '(带空格)
-- 解决方案
SELECT TRIM(TO_CHAR(SYSDATE, 'Month')) FROM dual;
-- 或
SELECT TO_CHAR(SYSDATE, 'FMMonth') FROM dual; -- FM抑制填充
六、最佳实践建议
- 存储标准化
- 始终以UTC时间存储时间戳
- 使用数据库原生时间类型(非字符串)
- 格式化分层处理graph TD
A[数据库层] -->|返回标准时间| B[应用层]
B --> C{展示需求}
C -->|简单格式化| D[前端处理]
C -->|复杂本地化| E[后端处理] - 格式复用策略-- PostgreSQL示例(创建格式化函数)
CREATE FUNCTION fmt_cn_date(TIMESTAMPTZ) RETURNS TEXT AS $
SELECT TO_CHAR($1 AT TIME ZONE 'Asia/Shanghai', 'YYYY"年"MM"月"DD"日" HH24"时"MI"分"');
$ LANGUAGE SQL IMMUTABLE;
SELECT fmt_cn_date(event_time) FROM events; - 安全注意事项-- 防止SQL注入(动态格式)
-- 错误做法
EXECUTE 'SELECT TO_CHAR(SYSDATE, ''' || user_input || ''') FROM dual';
-- 正确做法(白名单校验)
IF user_input IN ('YYYY-MM-DD', 'DD/MM/YYYY') THEN
EXECUTE '...' USING user_input;
END IF;
通过以上详细对比和示例,我们可以清晰地看到各数据库在日期转字符串功能上的异同。在实际应用中,根据数据库类型和业务需求选择合适的函数和格式,同时注意性能和国际化问题,可以高效地完成日期格式化任务。
相关推荐
- oracle数据导入导出_oracle数据导入导出工具
-
关于oracle的数据导入导出,这个功能的使用场景,一般是换服务环境,把原先的oracle数据导入到另外一台oracle数据库,或者导出备份使用。只不过oracle的导入导出命令不好记忆,稍稍有点复杂...
- 继续学习Python中的while true/break语句
-
上次讲到if语句的用法,大家在微信公众号问了小编很多问题,那么小编在这几种解决一下,1.else和elif是子模块,不能单独使用2.一个if语句中可以包括很多个elif语句,但结尾只能有一个else解...
- python continue和break的区别_python中break语句和continue语句的区别
-
python中循环语句经常会使用continue和break,那么这2者的区别是?continue是跳出本次循环,进行下一次循环;break是跳出整个循环;例如:...
- 简单学Python——关键字6——break和continue
-
Python退出循环,有break语句和continue语句两种实现方式。break语句和continue语句的区别:break语句作用是终止循环。continue语句作用是跳出本轮循环,继续下一次循...
- 2-1,0基础学Python之 break退出循环、 continue继续循环 多重循
-
用for循环或者while循环时,如果要在循环体内直接退出循环,可以使用break语句。比如计算1至100的整数和,我们用while来实现:sum=0x=1whileTrue...
- Python 中 break 和 continue 傻傻分不清
-
大家好啊,我是大田。今天分享一下break和continue在代码中的执行效果是什么,进一步区分出二者的区别。一、continue例1:当小明3岁时不打印年龄,其余年龄正常循环打印。可以看...
- python中的流程控制语句:continue、break 和 return使用方法
-
Python中,continue、break和return是控制流程的关键语句,用于在循环或函数中提前退出或跳过某些操作。它们的用途和区别如下:1.continue(跳过当前循环的剩余部分,进...
- L017:continue和break - 教程文案
-
continue和break在Python中,continue和break是用于控制循环(如for和while)执行流程的关键字,它们的作用如下:1.continue:跳过当前迭代,...
- 作为前端开发者,你都经历过怎样的面试?
-
已经裸辞1个月了,最近开始投简历找工作,遇到各种各样的面试,今天分享一下。其实在职的时候也做过面试官,面试官时,感觉自己问的问题很难区分候选人的能力,最好的办法就是看看候选人的github上的代码仓库...
- 面试被问 const 是否不可变?这样回答才显功底
-
作为前端开发者,我在学习ES6特性时,总被const的"善变"搞得一头雾水——为什么用const声明的数组还能push元素?为什么基本类型赋值就会报错?直到翻遍MDN文档、对着内存图反...
- 2023金九银十必看前端面试题!2w字精品!
-
导文2023金九银十必看前端面试题!金九银十黄金期来了想要跳槽的小伙伴快来看啊CSS1.请解释CSS的盒模型是什么,并描述其组成部分。答案:CSS的盒模型是用于布局和定位元素的概念。它由内容区域...
- 前端面试总结_前端面试题整理
-
记得当时大二的时候,看到实验室的学长学姐忙于各种春招,有些收获了大厂offer,有些还在苦苦面试,其实那时候的心里还蛮忐忑的,不知道自己大三的时候会是什么样的一个水平,所以从19年的寒假放完,大二下学...
- 由浅入深,66条JavaScript面试知识点(七)
-
作者:JakeZhang转发链接:https://juejin.im/post/5ef8377f6fb9a07e693a6061目录由浅入深,66条JavaScript面试知识点(一)由浅入深,66...
- 2024前端面试真题之—VUE篇_前端面试题vue2020及答案
-
添加图片注释,不超过140字(可选)1.vue的生命周期有哪些及每个生命周期做了什么?beforeCreate是newVue()之后触发的第一个钩子,在当前阶段data、methods、com...
- 今年最常见的前端面试题,你会做几道?
-
在面试或招聘前端开发人员时,期望、现实和需求之间总是存在着巨大差距。面试其实是一个交流想法的地方,挑战人们的思考方式,并客观地分析给定的问题。可以通过面试了解人们如何做出决策,了解一个人对技术和解决问...
- 一周热门
- 最近发表
- 标签列表
-
- 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)
