日期与时间函数
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())
);
读法:
- 出生月已经比当前月小 → 肯定已过
- 或者:月相同,且出生日 ≤ 今天 → 本月已到生日
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。
小结
- 现在:
now/curdate/curtime;分量:year~second,可嵌套now()。 - 辅助:
week、weekday(0=周一)、dayofyear。 - 表里:
year(birthday)、month(birthday)写进WHERE很常用。 - 业务写库时用
now()记录时间;生日类条件要 月 + 日 一起判断。 - 下一篇进入 聚合与分组:
count/sum/avg、group by、having。