MySQL查询库存3个月内到期物品问题求助(expire_date为m/Y格式)
问题分析与解决方案
核心问题:日期格式转换错误
你的代码中STR_TO_DATE的格式符使用错误,导致无法正确解析日期字符串,最终查询不到数据。
原代码里,CONCAT('01/', expire_date)会生成类似01/01/2024的字符串(假设expire_date为01/2024),但你使用的格式符%d%m/%Y要求日期部分是无分隔符的日和月(比如0101/2024),和实际生成的带斜杠的字符串不匹配,导致日期转换失败。
修正后的代码方案
方案1:修复日期格式符
调整STR_TO_DATE的格式符为%d/%m/%Y,同时优化日期计算逻辑:
// 获取当前日期(YYYY-MM-DD格式) $currentDate = date('Y-m-d'); // 计算三个月后的日期 $threeMonthsLater = date('Y-m-d', strtotime('+3 months')); // 修正后的SQL语句 $sql = "SELECT `medicine`.*, `supplier`.`s_id`, `s_name` FROM `medicine` LEFT JOIN `supplier` ON `medicine`.`supplier_id` = `supplier`.`s_id` WHERE STR_TO_DATE(CONCAT('01/', `expire_date`), '%d/%m/%Y') BETWEEN ? AND ?"; // 使用预处理语句避免SQL注入(强烈推荐) $stmt = $pdo->prepare($sql); $stmt->execute([$currentDate, $threeMonthsLater]); $expiringItems = $stmt->fetchAll(PDO::FETCH_ASSOC);
方案2:按年月字符串直接比较(更高效)
既然expire_date是MM/YYYY格式,我们可以跳过日期转换,直接通过字符串拼接实现逻辑比较,性能更优:
// 获取当前年月(YYYYMM格式) $currentYearMonth = date('Ym'); // 计算三个月后的年月(YYYYMM格式) $threeMonthsLaterYearMonth = date('Ym', strtotime('+3 months')); $sql = "SELECT `medicine`.*, `supplier`.`s_id`, `s_name` FROM `medicine` LEFT JOIN `supplier` ON `medicine`.`supplier_id` = `supplier`.`s_id` WHERE CONCAT(RIGHT(`expire_date`, 4), LEFT(`expire_date`, 2)) BETWEEN ? AND ?"; // 预处理执行 $stmt = $pdo->prepare($sql); $stmt->execute([$currentYearMonth, $threeMonthsLaterYearMonth]); $expiringItems = $stmt->fetchAll(PDO::FETCH_ASSOC);
这个方案把expire_date的MM/YYYY转换成YYYYMM格式的字符串(比如01/2024转为202401),直接和当前、三个月后的年月字符串比较,避免了日期转换的开销,逻辑也更可靠。
额外注意事项
- SQL注入风险:原代码直接将变量拼入SQL语句,存在严重注入漏洞,必须使用预处理语句。
- 字段类型优化:建议把
expire_date字段从varchar改为date或yearmonth类型,后续日期操作会更高效且不易出错。
内容的提问来源于stack exchange,提问作者Chamssoudine Bacar
相关产品推荐
相关产品推荐

