游乐游手机版
首页/数据库/文章详情

SQL如何将日期转换为特定格式?DATE_FORMAT函数详解

时间:2026-04-29 11:20
SQL如何将日期转换为特定格式?DATE_FORMAT函数详解 MySQL里DATE_FORMAT函数怎么用? 开门见山,DATE_FORMAT是MySQL的“独家”函数。如果你在PostgreSQL、SQL Server或者SQLite里直接调用它,系统报错可不是因为你写错了,而是它压根就不存在—

SQL如何将日期转换为特定格式?DATE_FORMAT函数详解

SQL如何将日期转换为特定格式?DATE_FORMAT函数详解

MySQL里DATE_FORMAT函数怎么用?

开门见山,DATE_FORMAT是MySQL的“独家”函数。如果你在PostgreSQL、SQL Server或者SQLite里直接调用它,系统报错可不是因为你写错了,而是它压根就不存在——这是数据库方言的差异,迁移代码时尤其要留心。

这个函数的核心任务很明确:把DATEDATETIMETIMESTAMP这类日期时间值,按照你指定的“模板”,转换成一个格式规整的字符串。这里有个关键点必须强调:转换结果是字符串,不再是日期类型。这意味着,它不能直接拿去做日期计算或者比较,除非你再把它转换回去。

它的基本语法相当直观:DATE_FORMAT(date, format)。其中,date就是你要处理的日期表达式,而format则是一个包含特定占位符的字符串模板,比如我们最熟悉的‘%Y-%m-%d’

常用格式符有哪些?哪些容易写错?

使用DATE_FORMAT时,格式符是重中之重,而且这里有几个“坑”新手很容易掉进去。首先,MySQL的格式符是大小写敏感的,大小写不同,含义天差地别。最经典的混淆就是把%y(两位年份)和%Y(四位年份)搞混,或者在需要24小时制的时候误用了%h(12小时制)。

下面这些是日常开发中最常用、也最需要仔细区分的格式符:

  • %Y → 四位年份(例如 2024),%y → 两位年份(例如 24
  • %m → 补零的两位月份(0112),%c → 不补零的月份(112
  • %d → 补零的两位日期(0131),%e → 不补零的日期(131
  • %H → 24小时制的小时(0023),%h%I → 12小时制(0112
  • %i → 分钟(0059),千万别写成 %m(那是月份)
  • %s → 秒(0059),它代表秒数,不是字符串的缩写

举个例子:DATE_FORMAT(NOW(), ‘%Y年%m月%d日 %H:%i’) 会返回像 “2024年04月22日 15:30” 这样的中文字符串,非常适合报表展示。

DATE_FORMAT能处理NULL或非法日期吗?

很遗憾,它不能“智能”处理异常值。如果传入的日期是NULL,那么结果也是NULL。如果传入一个非法日期,比如‘2024-02-30’,事情就有点棘手了:在MySQL的严格SQL模式下,它会直接报错Incorrect date value;而在非严格模式下,它可能会先被转换成‘0000-00-00’这样的零值,再进行格式化,最终结果自然是不可靠的。

因此,在生产环境中,更安全的做法是加上条件判断:

SELECT
  CASE
    WHEN order_date IS NULL THEN ‘未知日期’
    WHEN order_date = ‘0000-00-00’ THEN ‘日期无效’
    ELSE DATE_FORMAT(order_date, ‘%Y/%m/%d’)
  END AS formatted_date
FROM orders;

另外,还有一个容易被忽略的特性:DATE_FORMAT 对时区不敏感。它只会按照字段里存储的原始值进行格式化,不会自动转换为当前会话的时区。如果你的数据库里存的是UTC时间,但希望按北京时间显示,正确的步骤是先用CONVERT_TZ函数转换时区,然后再进行格式化。

替代方案:其他数据库怎么实现类似功能?

既然DATE_FORMAT是MySQL专属,那在其他数据库里该怎么办呢?答案是各有各的“方言”。

PostgreSQL使用的是TO_CHAR(date, ‘YYYY-MM-DD HH24:MI’);SQL Server(2012及以上版本)推荐使用FORMAT(date, ‘yyyy-MM-dd HH:mm’),老版本则常用CONVERT函数配合风格码;SQLite则用strftime(‘%Y-%m-%d’, date)。这些函数的名称、占位符语法乃至大小写规则都完全不同,跨数据库迁移时,这部分代码基本都需要重写。

最后,再提一个更隐蔽的陷阱:当你把DATE_FORMAT的结果用于GROUP BYORDER BY子句时,实际上是在对格式化后的字符串进行排序。如果格式像‘2024-01’这样本身具有顺序性,那可能没问题;但如果格式是‘一月2024’,排序结果很可能不符合你的日期逻辑预期。

所以,记住一个最佳实践:凡是涉及到排序、筛选或分组的逻辑,尽量使用原生的日期时间字段进行操作。DATE_FORMAT这类函数,最好只用在最终的结果展示层。

来源:https://www.php.cn/faq/2318623.html
上一篇MySQL自增主键不连续的原因及解决过程 下一篇MySQL如何实现在不停止服务的情况下修改表结构_利用Online DDL
本站内容用于信息整理与展示,如有侵权或内容问题请及时联系处理。

相关推荐

补充同频道和同主题内容,方便继续浏览更多相关内容。

同类最新

继续查看同栏目最近更新的文章。

更多
金仓数据库逻辑备份实战:全库导出与模式替换全流程
数据库 · 2026-07-03

金仓数据库逻辑备份实战:全库导出与模式替换全流程

在长期的运维实践中,我越来越体会到,备份就像一份保险——平时看似无用,但关键时刻却是唯一的救命稻草。逻辑备份看似简单,可真正执行恢复时,各种陷阱接连浮现:表名大小写不一致、Schema 未正确切换、Owner 属性未同步修改……任何一个环节处理不当,最终恢复出的数据库就会与预期相去甚远。 本文将深入

金仓数据库sys_rman物理备份全流程演练与误覆盖恢复
数据库 · 2026-07-03

金仓数据库sys_rman物理备份全流程演练与误覆盖恢复

干运维这行,逻辑备份和物理备份我都接触过,但说句实在话,真正能在生产环境里扛住事儿的,还得是物理备份。逻辑备份导出的是 SQL 语句,数据量一大,那速度慢得让人抓狂,而且最关键的是,它没法做时间点恢复。物理备份不一样,它直接拷贝数据文件,再配上 WAL 归档日志,想恢复到过去哪一秒都行,这是它最硬核

Windows下将MySQL注册为系统自启服务教程
数据库 · 2026-07-03

Windows下将MySQL注册为系统自启服务教程

先说一个关键前提:务必以管理员身份运行终端,否则 mysqld --install 这条命令几乎不可能成功。问题不在于命令写错,而是 Windows 系统的用户账户控制(UAC)机制会在中途拦截——在普通 CMD 或 PowerShell 窗口执行这条命令,要么直接提示 Access is deni

Mac版Navicat中快速对比两个数据库的表结构异同
数据库 · 2026-07-03

Mac版Navicat中快速对比两个数据库的表结构异同

直接说结论:Mac 版 Navicat 和 Windows 版在表结构比对逻辑上完全一致。但默认配置下,它确实无法承受“全库一键比对上万张表”的压力。要想避免卡死、内存溢出、进度条永远停在 0%,你必须手动将表分批处理,或者利用前缀过滤来控制扫描范围。 为什么 Mac 上点击「结构同步」后界面会卡住

MySQL中UNION操作推荐用UNION ALL的原因
数据库 · 2026-07-03

MySQL中UNION操作推荐用UNION ALL的原因

MySQL中UNION与UNION ALL性能对比:别再被“保险”迷惑,差距远超预期 先给出核心结论:UNION ALL 的性能通常比 UNION 高出不止一个数量级。原因在于,UNION 在合并结果集后会自动触发去重操作,这往往伴随着隐式排序,进而产生临时表和文件排序。而 UNION ALL 则直