在 MySQL 中,若要更新 DATETIME 或 TIMESTAMP 字段的日期部分(年月日),同时保持时间部分(时分秒)不变,主要有以下几种常用且高效的方法。

这是最经典且兼容性最好的写法。其逻辑是:提取原字段的时间部分,将其加到指定的新日期上。
语法结构:
UPDATE 表名 SET 时间字段 = ADDTIME(DATE('指定新日期') + INTERVAL 0 HOUR, TIME(时间字段)) WHERE 条件;示例:
假设表名为 orders,字段为 create_time原值为 2023-01-01 14:30:00,想将日期改为 2023-05-20,时间保持 14:30:00` 不变。
UPDATE orders SET create_time = ADDTIME(DATE('2023-05-20') + INTERVAL 0 HOUR, TIME(create_time)) WHERE id = 1;DATE('2023-05-20'):获取指定日期的日期部分。+ INTERVAL 0 HOUR:确保结果被视为 datetime 类型而非纯 date 类型(在某些 MySQL 版本中必需)。TIME(create_time):提取原记录中的时分秒部分。ADDTIME(...):将新日期与原时间相加,得到最终的 datetime。通过字符串拼接的方式,将新的日期字符串与原时间字符串组合,MySQL 会自动将其转换为 DATETIME 类型。
语法结构:
UPDATE 表名 SET 时间字段 = CONCAT('指定新日期', ' ', TIME(时间字段)) WHERE 条件;示例:
UPDATE orders SET create_time = CONCAT('2023-05-20', ' ', TIME(create_time)) WHERE id = 1;优点:写法直观,易于理解。
注意:确保 '指定新日期' 和 TIME(时间字段) 之间的空格格式正确。
如果你希望将日期更新为今天的日期,但保留原来的时间点(例如用于修正数据录入时的日期错误),可以使用 CURDATE()。
示例:
UPDATE orders SET create_time = ADDTIME(CURDATE() + INTERVAL 0 HOUR, TIME(create_time)) WHERE id = 1;
使用拼接法:
UPDATE orders SET create_time = CONCAT(CURDATE(), ' ', TIME(create_time)) WHERE id = 1;
如果只需要修改年份,而月、日、时间都不变,可以使用 DATE_FORMAT 进行格式化重组。
示例:将年份统一改为 2024 年
UPDATE orders SET create_time = STR_TO_DATE(CONCAT('2024-', DATE_FORMAT(create_time, '%m-%d %H:%i:%s')), '%Y-%m-%d %H:%i:%s')WHERE id = 1;注意事项
数据类型:上述方法适用于 DATETIME 和 TIMESTAMP 类型。如果是 DATE 类型,本身就没有时间部分,直接赋值即可。
自动更新陷阱:如果表中有一个字段定义为 TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,当你执行 UPDATE 语句修改其他字段时,该时间字段会自动变为当前时间。
解决方案:如果不想让某个时间字段自动更新,请在建表或改表时去掉 ON UPDATE CURRENT_TIMESTAMP 属性,或者在 UPDATE 语句中显式地给该字段赋原值(如 SET update_time = update_time)。
性能:对于大批量数据更新,建议分批执行,避免长时间锁表。
通用推荐:ADDTIME(DATE('新日期') + INTERVAL 0 HOUR, TIME(原字段))
简洁写法:CONCAT('新日期', ' ', TIME(原字段))
更新为今天:将 '新日期' 替换为 CURDATE()