
本文详解 CodeIgniter 中按年月精确筛选数据库记录时 like 操作失效的原因,并提供基于 DATE_FORMAT 的可靠替代方案,确保按指定年月(如 2022-01)完整匹配所有当月数据。
本文详解 codeigniter 中按年月精确筛选数据库记录时 `like` 操作失效的原因,并提供基于 `date_format` 的可靠替代方案,确保按指定年月(如 2022-01)完整匹配所有当月数据。
在 CodeIgniter 中使用 $this->db->like('date', $stotal) 进行日期模糊匹配,本质上是执行 SQL 的 LIKE '%2022-01%' 查询。这种方式存在严重隐患:若 date 字段为 DATETIME 或包含时分秒(如 '2022-01-15 14:30:22'),LIKE 可能因格式不一致而漏匹配;更危险的是,它可能误匹配跨月数据——例如 stotal = '2022-01' 时,'2022-01-31 23:59:59' 虽属 1 月,但若数据库存储格式含毫秒或时区偏移,LIKE 匹配稳定性极差;此外,LIKE 无法利用 date 字段上的索引,导致全表扫描,性能随数据量增长急剧下降。
✅ 正确做法是使用 MySQL 原生日期函数进行标准化比对。推荐使用 DATE_FORMAT(date, '%Y-%m') 将日期统一格式化为 YYYY-MM 字符串,再与 $stotal(如 '2022-01')严格等值比较:
public function searchbilling($stotal) {
$this->db->select('*, SUM(quantity) as quantity');
$this->db->from('delivered');
// ✅ 使用 DATE_FORMAT 确保语义精准匹配整月
$this->db->where("DATE_FORMAT(date, '%Y-%m') =", $stotal);
$this->db->group_by('YEAR(date), MONTH(date), customer');
$query = $this->db->get();
return $query->result();
}⚠️ 注意事项:
- 字段类型校验:确认 delivered.date 字段类型为 DATE 或 DATETIME,避免字符串类型存储日期(如 '2022/01/15'),否则 DATE_FORMAT 将返回 NULL;
-
SQL 注入防护:$stotal 由可控的下拉菜单生成(仅含 YYYY-MM 格式),但仍建议增加验证:
if (!preg_match('/^\d{4}-\d{2}$/', $stotal)) { return []; } -
性能优化:若查询频繁,可在 date 字段上建立函数索引(MySQL 8.0+):
CREATE INDEX idx_date_ym ON delivered (DATE_FORMAT(`date`, '%Y-%m'));
-
兼容性备选方案:若需兼容低版本 MySQL 或避免函数索引限制,可改用范围查询:
$start = $stotal . '-01'; $end = date('Y-m-t', strtotime($stotal . '-01')); // 当月最后一天 $this->db->where('date >=', $start); $this->db->where('date <=', $end . ' 23:59:59');
通过 DATE_FORMAT 替代 like,不仅解决了结果遗漏问题,还提升了查询准确性与数据库性能,是 CodeIgniter 日期搜索场景下的最佳实践。


















