You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MySQL中STR_TO_DATE()返回上月日期,是否为Bug?

MySQL STR_TO_DATE()转换'%M-%YY'格式返回上月日期的问题

问题场景

处理表中类似'October-21'的字符串格式日期时,在MySQL 5.9(SQLFiddle环境)中使用STR_TO_DATE('%M-%YY')转换出现异常:

  • 转换结果返回上月最后一天
  • 直接将转换结果传入DATE_ADD()会返回null,仅转为数值日期后调用DATE_ADD()才正常

测试SQL

SELECT monthname(STR_TO_DATE('October','%M')), 
STR_TO_DATE('October-21','%M-%YY'), 
STR_TO_DATE('November-21','%M-%YY'), 
STR_TO_DATE('October-21','%M-%YY') + 1, 
STR_TO_DATE('November-21','%M-%YY') + 1, 
STR_TO_DATE('November-21','%M-%YY') - 1, 
DATE_ADD(STR_TO_DATE('October-21','%M-%YY'), INTERVAL 1 MONTH), 
DATE_ADD(STR_TO_DATE('October-21','%M-%YY')+1, INTERVAL 1 MONTH),
DATE_ADD(STR_TO_DATE('November-21','%M-%YY')+1, INTERVAL -1 MONTH),
STR_TO_DATE('Oct','%b'), 
STR_TO_DATE('Sep','%b');

测试输出

monthname(STR_TO_DATE('October','%M'))  
October      

STR_TO_DATE('October-21','%M-%YY')
2021-09-30  
    
STR_TO_DATE('November-21','%M-%YY')
2021-10-31  
    
STR_TO_DATE('October-21','%M-%YY') + 1  
20211001    

STR_TO_DATE('November-21','%M-%YY') + 1 
20211101        

STR_TO_DATE('November-21','%M-%YY') - 1 
20211099

STR_TO_DATE('Oct','%b')     
0001-09-30  

STR_TO_DATE('Sep','%b')
0001-08-31

DATE_ADD(STR_TO_DATE('October-21','%M-%YY'), INTERVAL 1 MONTH)
null   

DATE_ADD(STR_TO_DATE('October-21','%M-%YY')+1, INTERVAL 1 MONTH)
2021-11-01

DATE_ADD(STR_TO_DATE('November-21','%M-%YY')+1, INTERVAL -1 MONTH)
2021-10-01

原因分析

  1. 日期回退逻辑:当STR_TO_DATE()使用的格式串仅指定月份(%M/%b)和年份(%YY)、未包含日期部分时,MySQL会默认将日期设为00。但MySQL不存在日为00的合法日期,因此会自动回退到上月的最后一天。
    • 例如'October-21'会被解析为2021-10-00,因无效自动调整为2021-09-30;'November-21'解析为2021-11-00,调整为2021-10-31。
  2. DATE_ADD返回null的原因:虽然调整后的日期显示为合法的上月最后一天,但该日期是从无效的"零日"转换而来,内部被标记为无效日期,导致DATE_ADD()等日期函数无法正常处理,返回null。而将转换结果转为数值(如20210930)后加1,得到的20211001是合法的2021-10-01,因此能被DATE_ADD()正常处理。

版本兼容性

该问题并非MySQL 5.9独有,在MySQL 5.x系列的多个版本(如5.6、5.7)中都存在,这是STR_TO_DATE()处理无日期部分格式时的默认行为。MySQL 8.0中核心逻辑未变,仍会出现日期回退的情况,但部分日期函数对无效日期的处理略有优化。

解决方案

若需要得到目标月份的第一天(而非上月最后一天),可以通过以下方式处理:

  • 拼接日期部分后转换:
    STR_TO_DATE(CONCAT('October-21', '-01'), '%M-%YY-%d')
    
  • 转换后格式化获取当月第一天:
    DATE_FORMAT(STR_TO_DATE('October-21', '%M-%YY'), '%Y-%m-01')
    
  • 对转换结果加1天(跳过无效的零日逻辑):
    ADDDATE(STR_TO_DATE('October-21', '%M-%YY'), 1)
    

内容的提问来源于stack exchange,提问作者bonCodigo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 23:04:57