使用INTERVAL递增TIMESTAMP列生成无效日期时间值的问题
解答
你的判断是对的,确实发生了时区相关的转换。虽然TIMESTAMP在底层是存储UTC纪元秒数,但当你使用+ INTERVAL这类时间运算时,MariaDB会先把存储的UTC秒数转换为当前会话时区(这里是Europe/London)的datetime时间值,再执行加法操作,最后还要把运算结果转换回当前时区的合法datetime值——而2022-03-27 01:30:00在伦敦时区不存在(当天凌晨1点直接跳转为2点),所以触发了无效时间的错误。
如果要保留现有设置和INTERVAL语法,有两种简洁的改写方案:
- 方案1:转UTC计算后再转回本地时区
先把TIMESTAMP值转换为UTC时间,完成加一年的操作后,再转回系统时区。这种方式绕开了本地时区的夏令时问题,逻辑直观:
UPDATE test_table SET updated_at = CONVERT_TZ( CONVERT_TZ(updated_at, @@session.time_zone, '+00:00') + INTERVAL 1 YEAR, '+00:00', @@session.time_zone );
- 方案2:直接操作底层秒数
利用TIMESTAMP的存储特性,取出其对应的UTC秒数,加上一年的秒数后再转回TIMESTAMP。这里用INTERVAL 1 YEAR对应的秒数来保证准确性(自动处理闰年):
UPDATE test_table SET updated_at = FROM_UNIXTIME( UNIX_TIMESTAMP(updated_at) + TIMESTAMPDIFF(SECOND, '1970-01-01', '1970-01-01' + INTERVAL 1 YEAR) );
两种方案里,方案1的可读性更强,更易维护。
内容的提问来源于stack exchange,提问作者Arth
相关产品推荐
相关产品推荐

