MySQL

日期与时间函数

MySQL 日期时间:now/curdate、年月日时分秒、week/weekday/dayofyear,以及用 birthday 做生日与区间查询。

业务里到处是时间:交易日、生日、下单时刻、统计「本月/今年」。今天练 MySQL 日期时间函数,并做几道生日条件综合题。

系列:MySQL 入门到查询 · 第 10 / 17 篇(第 10 天 · 4 月 30 日)
上一篇:常用字符串函数
下一篇:聚合与分组
总目录:系列索引

环境说明

  • 库:train
  • 本篇专用 stu 表(请先执行):
use train;

drop table if exists stu;
create table stu(
    id int,
    name varchar(20),
    gender char(1),
    birthday date
);

insert into stu(id, name, gender, birthday) values
    (1, '张三', 'F', '1999-05-12'),
    (2, '李四', 'M', '2000-08-20'),
    (3, '王五', 'F', '2001-04-30'),
    (4, '赵六', 'M', '1998-12-01'),
    (5, '小七', 'F', '2000-04-10');

「今年是否已过生日」等结果会随你执行 SQL 的当天变化,这是正常的。练习数据以本篇 seed 为准。

1. 先看「现在」:now / curdate / curtime

select now();
select curdate();
select curtime();
函数格式例子
now()年-月-日 时:分:秒2026-04-30 10:15:00
curdate()年-月-日2026-04-30
curtime()时:分:秒10:15:00

结果随机器时间变化;以你本机 now() 为准。

2. 拆时间分量:year / month / day / hour / minute / second

select year('2023-12-21 15:30:20');
select month('2023-12-21 15:30:20');
select day('2023-12-21 15:30:20');
select hour('2023-12-21 15:30:20');
select minute('2023-12-21 15:30:20');
select second('2023-12-21 15:30:20');
函数取什么示例结果
year年2023
month月12
day日21
hour时15
minute分30
second秒20

取「现在」的年月日(嵌套)

select year(now());
select month(now());
select day(now());
select hour(curtime());

只要日期部分 / 时间部分

select date('2023-10-01 10:05:28');  -- 2023-10-01
select time('2023-10-01 10:05:28');  -- 10:05:28
select date(now());
select time(now());

3. week / weekday / dayofyear

select week('2023-12-21');
select week(now());

week:该日期是当年的第几周(周起始规则与系统设置有关,练习记住「会返回周序号」即可)。

select weekday('2023-12-21');
select weekday(now());
select weekday(now()) + 1;
点说明
weekday 返回范围0~6
含义0 = 周一,1 = 周二,……,6 = 周日
和习惯差一天有人把周一当 1;全组可约定 weekday(...)+1
select dayofyear('2024-01-01');   -- 1
select dayofyear('2024-12-31');   -- 366(2024 闰年)
select dayofyear('2025-12-31');   -- 365
select dayofyear('2024-02-29');   -- 60
select dayofyear('2025-02-29');   -- 无效日期 → NULL

闰年:2 月有 29 日;平年 2 月只有 28 日。不存在的日期,函数可能返回 NULL。

4. 用函数查表:出生年、生日月

select name, birthday from stu;
select name, year(birthday) from stu;
select name, month(birthday) from stu;
select name, day(birthday) from stu;
-- 2000 年出生
select * from stu where year(birthday) = 2000;

-- 8 月过生日
select * from stu where month(birthday) = 8;

-- 4 月过生日
select name, birthday from stu where month(birthday) = 4;

也可以用字符串截取 substring(birthday,1,4) 等写法;日期列用 year()/month() 更清晰。

5. 插入 / 更新时记录「现在」

5.1 交易时间表小案例

drop table if exists bank;
create table bank(
    id int,
    name varchar(20),
    money double,
    utime datetime
);

insert into bank values
    (1, 'zs', 5000, '2024-12-10 14:20:38'),
    (2, 'ls', 4000, '2024-11-11 09:30:51');

select * from bank;

-- 新行:交易时间 = 现在
insert into bank values(3, 'ww', 6000, now());

-- 给 zs 存 500,并刷新时间
update bank set money = money + 500, utime = now() where name = 'zs';
select * from bank;

5.2 按时间范围筛(预告/复习)

select * from bank where utime < '2025-01-01';
select * from bank where utime >= '2024-12-01' and utime < '2025-01-01';

日期比较时,值加引号。底层按日期先后比较,越新越大。

6. 粗略年龄:今年年份 − 出生年份

select name, birthday,
       year(now()) - year(birthday) as approx_age
from stu;
说明
这是粗算,未判断「今年生日是否已过」
精确周岁需要更完整的日期运算(进阶)

7. 今年生日过了没有?(综合 and / or)

约定:生日当天算已过。

7.1 已过生日

select * from stu where
    month(birthday) < month(now())
    or (
        month(birthday) = month(now())
        and day(birthday) <= day(now())
    );

读法:

  1. 出生月已经比当前月小 → 肯定已过
  2. 或者:月相同,且出生日 ≤ 今天 → 本月已到生日

7.2 还未过生日

select * from stu where
    month(birthday) > month(now())
    or (
        month(birthday) = month(now())
        and day(birthday) > day(now())
    );

易错:只写 month(birthday)=month(now()) 会把本月所有生日都算成「已过」或「未过」,忽略「日」比较。

8. 更多条件例句

-- 99 年或 00 年出生
select * from stu where year(birthday) in (1999, 2000);

-- 生日在 4 月或 8 月
select * from stu where month(birthday) in (4, 8);

-- 生日不在 12 月
select * from stu where month(birthday) != 12;

-- 显示姓名、生日、粗算年龄,并只保留 2000 年后出生
select name, birthday, year(now())-year(birthday) as age
from stu
where year(birthday) >= 2000;

9. 完整跟练脚本

use train;

drop table if exists stu;
create table stu(id int, name varchar(20), gender char(1), birthday date);
insert into stu values
    (1,'张三','F','1999-05-12'),
    (2,'李四','M','2000-08-20'),
    (3,'王五','F','2001-04-30'),
    (4,'赵六','M','1998-12-01'),
    (5,'小七','F','2000-04-10');

select now(), curdate(), curtime();
select year(now()), month(now()), day(now());
select year('2023-12-21 15:30:20');
select week('2023-12-21');
select weekday('2023-12-21');
select dayofyear('2024-02-29');

select name, year(birthday), month(birthday) from stu;
select * from stu where year(birthday)=2000;
select * from stu where month(birthday)=4;
select name, year(now())-year(birthday) as age from stu;

drop table if exists bank;
create table bank(id int, name varchar(20), money double, utime datetime);
insert into bank values
    (1,'zs',5000,'2024-12-10 14:20:38'),
    (2,'ls',4000,'2024-11-11 09:30:51');
insert into bank values(3,'ww',6000,now());
update bank set money=money+500, utime=now() where name='zs';
select * from bank;
select * from bank where utime < '2025-01-01';

select * from stu where
  month(birthday) < month(now())
  or (month(birthday)=month(now()) and day(birthday)<=day(now()));

select * from stu where
  month(birthday) > month(now())
  or (month(birthday)=month(now()) and day(birthday)>day(now()));

10. 速查表

目标写法
当前日期时间now()
当前日期 / 时间curdate() / curtime()
取年月日year / month / day
取时分秒hour / minute / second
只要日期/时间部分date(...) / time(...)
第几周week(...)
周几(0=周一)weekday(...)(+1 可作习惯调整)
年第几天dayofyear(...)
插入当前时间insert ... values(..., now())
更新当前时间update ... set utime=now()
某年出生where year(birthday)=2000
某月生日where month(birthday)=8
时间之前where utime < '2025-01-01'

11. 今天的练习清单

  • now() / curdate() / curtime()
  • year/month/day(now())
  • weekday 与 weekday+1 对比
  • dayofyear 对比 2024/2025 年末
  • 查 2000 年出生、4 月过生日
  • 粗算年龄
  • bank 表:insert now()、update now()、按 utime 过滤
  • 「已过生日 / 未过生日」两句 SQL,并对照今天日期解释结果

常见错误

易错:日期字面量忘加引号。
易错:把 weekday 的 0 当成周日(本篇约定 0=周一)。
易错:用 year(now())-year(birthday) 却当成精确周岁。
易错:生日条件只比月不比日。
易错:datetime 与 date 混用时比较精度不同(含时分秒 vs 仅日期)。
易错:书写不存在的日期(如平年 2 月 29 日)导致 NULL。

小结

  1. 现在:now / curdate / curtime;分量:year~second,可嵌套 now()。
  2. 辅助:week、weekday(0=周一)、dayofyear。
  3. 表里:year(birthday)、month(birthday) 写进 WHERE 很常用。
  4. 业务写库时用 now() 记录时间;生日类条件要 月 + 日 一起判断。
  5. 下一篇进入 聚合与分组:count/sum/avg、group by、having。

系列导航:总目录 · 上一篇:常用字符串函数 · 下一篇:聚合与分组

相关阅读

全部文章 →
← 返回列表更多「MySQL」