MySQL 日期加一天完全指南
一、基础日期加法
1. 使用 DATE_ADD() 函数
```sql
-- 当前日期加一天
SELECT DATE_ADD(CURDATE(), INTERVAL 1 DAY);
-- 指定日期加一天
SELECT DATE_ADD('2024-01-15', INTERVAL 1 DAY);
-- 日期时间加一天
SELECT DATE_ADD('2024-01-15 14:30:00', INTERVAL 1 DAY);
```
2. 使用 INTERVAL 简写
```sql
-- 当前日期加一天
SELECT CURDATE() + INTERVAL 1 DAY;
-- 指定日期加一天
SELECT '2024-01-15' + INTERVAL 1 DAY;
```
3. 使用 ADDDATE() 函数
```sql
-- ADDDATE 与 DATE_ADD 功能相同
SELECT ADDDATE(CURDATE(), INTERVAL 1 DAY);
SELECT ADDDATE('2024-01-15', 1); -- 第二个参数直接写数字
```
二、实战应用场景
场景1:查询明天的数据
```sql
-- 查询明天到期的订单
SELECT * FROM orders
WHERE expire_date = CURDATE() + INTERVAL 1 DAY;
-- 查询未来24小时内的活动
SELECT * FROM events
WHERE start_time BETWEEN NOW() AND NOW() + INTERVAL 1 DAY;
```
场景2:数据统计和报表
```sql
-- 统计最近7天每天的数据(包括明天)
SELECT
CURDATE() + INTERVAL (ones.n + 10*tens.n) DAY as stat_date,
COUNT(orders.id) as order_count
FROM
(SELECT 0 n UNION SELECT 1 UNION SELECT 2 UNION SELECT 3
UNION SELECT 4 UNION SELECT 5 UNION SELECT 6) ones
CROSS JOIN
(SELECT 0 n UNION SELECT 1) tens
LEFT JOIN orders ON DATE(orders.created_at) = CURDATE() + INTERVAL (ones.n + 10*tens.n) DAY
WHERE (ones.n + 10*tens.n) BETWEEN 0 AND 6
GROUP BY stat_date;
```
场景3:自动设置默认日期
```sql
-- 创建表时设置默认过期时间为明天
CREATE TABLE temporary_data (
id INT PRIMARY KEY AUTO_INCREMENT,
data_content TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
expire_date DATE DEFAULT (CURDATE() + INTERVAL 1 DAY)
);
-- 插入数据,自动设置明天过期
INSERT INTO temporary_data (data_content) VALUES ('临时数据');
```
三、时间单位大全
MySQL 支持的各种时间间隔单位:
| 单位 | 说明 | 示例 |
||||
| `MICROSECOND` | 微秒 | `INTERVAL 1000 MICROSECOND` |
| `SECOND` | 秒 | `INTERVAL 30 SECOND` |
| `MINUTE` | 分钟 | `INTERVAL 15 MINUTE` |
| `HOUR` | 小时 | `INTERVAL 2 HOUR` |
| `DAY` | 天 | `INTERVAL 1 DAY` |
| `WEEK` | 周 | `INTERVAL 1 WEEK` |
| `MONTH` | 月 | `INTERVAL 1 MONTH` |
| `QUARTER` | 季度 | `INTERVAL 1 QUARTER` |
| `YEAR` | 年 | `INTERVAL 1 YEAR` |
复杂时间计算示例
```sql
-- 加1天2小时30分钟
SELECT NOW() + INTERVAL '1 2:30' DAY_MINUTE;
-- 加1年6个月
SELECT CURDATE() + INTERVAL '1-6' YEAR_MONTH;
-- 精确时间计算
SELECT '2024-01-15 14:30:00' + INTERVAL '1 02:30:45' DAY_SECOND;
```
四、日期减法
使用 DATE_SUB() 函数
```sql
-- 当前日期减一天
SELECT DATE_SUB(CURDATE(), INTERVAL 1 DAY);
-- 指定日期减一天
SELECT DATE_SUB('2024-01-15', INTERVAL 1 DAY);
```
使用 INTERVAL 负数
```sql
-- 日期减一天(推荐)
SELECT CURDATE() + INTERVAL -1 DAY;
-- 等同于
SELECT CURDATE() - INTERVAL 1 DAY;
```
五、处理边界情况
1. 月末日期处理
```sql
-- 自动处理月末(2024-01-31 加一天 → 2024-02-01)
SELECT DATE_ADD('2024-01-31', INTERVAL 1 DAY);
-- 闰年处理(2024-02-28 加一天 → 2024-02-29)
SELECT DATE_ADD('2024-02-28', INTERVAL 1 DAY);
```
2. 时间戳处理
```sql
-- 时间戳加一天
SELECT FROM_UNIXTIME(UNIX_TIMESTAMP() + (24 * 60 * 60));
-- 指定时间戳加一天
SELECT FROM_UNIXTIME(1705303845 + (24 * 60 * 60));
```
3. 时区处理
```sql
-- 考虑时区的日期计算
SELECT
CONVERT_TZ(NOW(), '+00:00', '+08:00') as beijing_time,
CONVERT_TZ(NOW(), '+00:00', '+08:00') + INTERVAL 1 DAY as beijing_tomorrow;
```
六、性能优化技巧
1. 避免在 WHERE 条件中使用函数
```sql
-- ❌ 不推荐:无法使用索引
SELECT * FROM orders
WHERE DATE_ADD(created_date, INTERVAL 1 DAY) = '2024-01-16';
-- ✅ 推荐:可以使用索引
SELECT * FROM orders
WHERE created_date = '2024-01-15';
```
2. 使用预计算的值
```sql
-- 在应用层计算好日期
SET @tomorrow = CURDATE() + INTERVAL 1 DAY;
SELECT * FROM schedule
WHERE schedule_date = @tomorrow;
```
3. 创建函数索引(MySQL 8.0+)
```sql
-- 创建虚拟列并建立索引
ALTER TABLE orders
ADD COLUMN expire_date_virtual DATE
GENERATED ALWAYS AS (created_date + INTERVAL 30 DAY) VIRTUAL;
CREATE INDEX idx_expire_date ON orders(expire_date_virtual);
```
七、实际业务案例
案例1:会员到期提醒
```sql
-- 查询明天到期的会员
SELECT
user_id,
username,
expire_date,
expire_date + INTERVAL 1 DAY as grace_period_end
FROM members
WHERE expire_date = CURDATE() + INTERVAL 1 DAY;
-- 批量续费一个月
UPDATE members
SET expire_date = expire_date + INTERVAL 1 MONTH
WHERE expire_date < CURDATE();
```
案例2:活动日程管理
```sql
-- 生成未来7天的活动日历
SELECT
CURDATE() + INTERVAL n DAY as activity_date,
CASE DAYOFWEEK(CURDATE() + INTERVAL n DAY)
WHEN 1 THEN '周日'
WHEN 7 THEN '周六'
ELSE '工作日'
END as day_type
FROM (
SELECT 0 n UNION SELECT 1 UNION SELECT 2 UNION SELECT 3
UNION SELECT 4 UNION SELECT 5 UNION SELECT 6
) days;
```
案例3:数据保留策略
```sql
-- 删除30天前的数据
DELETE FROM user_logs
WHERE created_at < CURDATE() - INTERVAL 30 DAY;
-- 归档明天之前的数据
INSERT INTO logs_archive
SELECT * FROM user_logs
WHERE created_at < CURDATE() + INTERVAL 1 DAY;
```
八、日期格式化输出
格式化日期结果
```sql
-- 基础格式化
SELECT DATE_FORMAT(CURDATE() + INTERVAL 1 DAY, '%Y-%m-%d') as tomorrow;
-- 中文格式
SELECT DATE_FORMAT(CURDATE() + INTERVAL 1 DAY, '%Y年%m月%d日') as chinese_tomorrow;
-- 完整日期时间格式
SELECT DATE_FORMAT(NOW() + INTERVAL 1 DAY, '%Y-%m-%d %H:%i:%s') as tomorrow_datetime;
```
业务场景格式化
```sql
-- 邮件模板中的日期
SELECT
CONCAT(
'您的试用期将于 ',
DATE_FORMAT(CURDATE() + INTERVAL 1 DAY, '%M %D, %Y'),
' 到期'
) as reminder_message;
-- 报表中的日期显示
SELECT
DATE_FORMAT(event_date, '%W, %b %d') as display_date,
event_name
FROM events
WHERE event_date BETWEEN CURDATE() AND CURDATE() + INTERVAL 7 DAY;
```
九、错误处理与验证
1. 无效日期处理
```sql
-- 安全日期计算(避免无效日期)
SELECT
DATE_ADD('2024-01-32', INTERVAL 1 DAY) as invalid_result, -- 返回 NULL
COALESCE(DATE_ADD('2024-01-32', INTERVAL 1 DAY), CURDATE()) as safe_result;
```
2. 日期验证函数
```sql
-- 验证日期是否有效
SELECT
'2024-02-30' as test_date,
CASE
WHEN DATE('2024-02-30') IS NULL THEN '无效日期'
ELSE '有效日期'
END as validation_result;
```
3. 边界测试
```sql
-- 测试各种边界情况
SELECT
DATE_ADD('9999-12-31', INTERVAL 1 DAY) as max_date,
DATE_ADD('1000-01-01', INTERVAL -1 DAY) as min_date,
DATE_ADD('2024-12-31', INTERVAL 1 DAY) as year_end,
DATE_ADD('2024-02-28', INTERVAL 1 DAY) as leap_year;
```
十、实用函数速查
| 需求 | 推荐写法 | 说明 |
||-||
| **当前日期加一天** | `CURDATE() + INTERVAL 1 DAY` | 最简洁 |
| **指定日期加一天** | `DATE_ADD('2024-01-15', INTERVAL 1 DAY)` | 最清晰 |
| **日期时间加一天** | `NOW() + INTERVAL 1 DAY` | 包含时间 |
| **批量更新日期** | `UPDATE table SET date_col = date_col + INTERVAL 1 DAY` | 批量操作 |
| **条件日期计算** | `CASE WHEN condition THEN date_col + INTERVAL 1 DAY ELSE date_col END` | 条件计算 |
总结
**核心要点:**
1. **推荐写法**:`CURDATE() + INTERVAL 1 DAY`(最简洁直观)
2. **函数选择**:`DATE_ADD()` 和 `+ INTERVAL` 功能相同,后者更简洁
3. **边界处理**:MySQL自动处理月末、闰年等特殊情况
4. **性能注意**:避免在WHERE条件中对字段使用日期函数
**记住这个万能公式:**
```sql
日期/时间 + INTERVAL 数字 时间单位
```
通过掌握这些日期计算方法,你可以轻松处理各种业务场景中的日期逻辑!另外搭配便捷的80kmMYSQL备份工具,可定时备份、异地备份,MYSQL导出导入。可本地连接LINUX里的MYSQL,简单便捷。可以大大地提高工作效率喔。