date_add单位须用小写单数,否则静默返回null;datediff仅算整数天差,跨时区或需高精度时应改用timestampdiff;时区不一致会导致结果飘移;where中对字段用date_add会失效索引,应改写为范围查询。

DATE_ADD 用错单位会直接算错时间
MySQL 的 DATE_ADD 不是“加几天”那么简单,它对单位敏感且不校验拼写错误。比如把 'day' 写成 'days' 或 'DAY'(大小写在某些模式下也报错),函数会静默返回 NULL,而你可能还在查数据为什么变少了。
实操建议:
- 单位必须严格用小写单数形式:
'year'、'month'、'day'、'hour'、'minute'、'second' - 避免用字符串拼接构造 interval,例如不要写
DATE_ADD(NOW(), INTERVAL '3' DAY)(引号里的数字会被当字符串处理) - 真正安全的写法是:
DATE_ADD(NOW(), INTERVAL 3 DAY) - 如果要动态加减,优先用变量传数值,别拼 SQL 字符串
DATEDIFF 只算天数,跨月/年会丢失精度
DATEDIFF 返回两个日期之间的**整数天差**,它会自动截断时间部分('2024-03-15 23:59:59' 和 '2024-03-16 00:00:01' 算出来是 1 天,但实际只差 2 秒)。如果你本意是算“是否超过 24 小时”,用它就错了。
常见错误现象:
- 订单超时判断用
DATEDIFF(NOW(), create_time) > 1,结果凌晨下单、上午取消也被判超时 - 和
DATE_ADD混用时,误以为DATEDIFF能反向还原原时间(它不能)
替代方案:
- 需要小时/分钟级判断,改用
TIMESTAMPDIFF(HOUR, create_time, NOW()) > 24 - 注意
TIMESTAMPDIFF参数顺序是(unit, start, end),和DATEDIFF(end, start)相反
时区不一致会让 DATE_ADD 和 DATEDIFF 结果飘移
MySQL 默认用系统时区解析 datetime 字面量,但如果你的字段是 DATETIME 类型(无时区信息),而客户端连接设了 SET time_zone = '+08:00',同一句 DATE_ADD('2024-01-01', INTERVAL 1 DAY) 在不同连接下可能返回不同结果。
使用场景提示:
- 线上数据库统一用 UTC 存储时间,应用层做时区转换 —— 这样
DATE_ADD计算才稳定 - 如果必须用本地时区,确保所有连接都显式设置
SET time_zone = '+08:00',别依赖默认值 -
DATEDIFF对TIMESTAMP类型字段会自动转为当前时区再计算,而DATETIME不会 —— 同一查询换字段类型结果可能突变
WHERE 中滥用 DATE_ADD 可能导致索引失效
写 WHERE DATE_ADD(create_time, INTERVAL 7 DAY) 看似合理,但 MySQL 无法用上 <code>create_time 上的索引,因为函数作用于列本身。等价的高效写法是把函数移到右边。
性能影响明显:
- 100 万行表,上述写法可能走全表扫描;改成
WHERE create_time 就能命中索引 -
DATE_SUB(NOW(), INTERVAL 7 DAY)是常量表达式,优化器可提前计算 - 同理,
DATEDIFF(NOW(), create_time) > 7也应改为create_time
复杂点在于:不是所有函数都能简单挪动,比如带变量或子查询的表达式,就得考虑加生成列或改查询逻辑。










