MySQL 8 中 DATE 类型字段无法使用 LIKE 通配符的解决方案

MySQL 8 中 DATE 类型字段无法使用 LIKE 通配符的解决方案

mysql 8.0 严格校验 date 值,不再允许对 date 字段直接使用 `’2020-02%’` 这类含通配符的字符串比较;应改用 `date_format()`、`year()`/`month()` 函数或范围查询实现按年月模糊筛选。

在 MySQL 5.7 中,部分宽松模式下允许将字符串 ‘2020-02%’ 隐式转换为 DATE 进行比较(尽管语义不严谨),但 MySQL 8.0 默认启用严格 SQL 模式(STRICT_TRANS_TABLES),明确拒绝此类非法日期字面量,抛出 Incorrect DATE value: ‘2020-02%’ 错误。

根本原因:last_date 是 DATE 类型字段,而 ‘2020-02%’ 是无效的日期字面量——% 不是合法日期字符,MySQL 8.0 不再尝试模糊匹配或截断解析。

推荐解决方案(兼顾性能与可读性)

1. 使用 DATE_FORMAT() 提取年月比较(适用于按“年-月”前缀筛选)

SELECT
    '01',
    2103,
    cssd._campaign_id,
    cssd.first,
    cssd.last,
    cssd.street,
    cssd.city,
    cssd.state,
    cssd.zip,
    cssd.customer_id,
    cssd.vin,
    cssd.email,
    cssd.phone,
    cssd.phone2,
    cssd.phonecell
FROM combined_sales_service_data cssd
WHERE cssd._campaign_id = 25
  AND DATE_FORMAT(cssd.last_date, '%Y-%m') >= '2020-02';

✅ 语义清晰:等价于“2020年2月及之后的所有日期”
⚠️ 注意:该写法无法利用 last_date 上的索引(函数包裹导致索引失效),大数据量时需谨慎。

2. 改用范围查询(最优性能,强烈推荐)

刺鸟创客

刺鸟创客

一款专业高效稳定的AI内容创作平台

下载

-- 查询 2020-02-01 起的所有记录(含当月及之后)
AND cssd.last_date >= '2020-02-01'

-- 若需精确匹配“2020年2月及以后”,可结合日期边界:
AND cssd.last_date >= '2020-02-01'

✅ 完全走索引,执行高效
✅ 符合 SQL 标准,兼容所有 MySQL 版本
? 小技巧:动态生成边界值(如 STR_TO_DATE(‘2020-02’, ‘%Y-%m’))可提升灵活性。

3. 拆分年月字段(适合高频按月查询场景)
若业务频繁按年、月过滤,可在表中增加生成列并建索引:

ALTER TABLE combined_sales_service_data
ADD COLUMN last_year_month CHAR(7) 
  GENERATED ALWAYS AS (DATE_FORMAT(last_date, '%Y-%m')) STORED,
ADD INDEX idx_last_ym (last_year_month);

后续查询即可安全使用:

AND cssd.last_year_month >= '2020-02'

不推荐方案

  • 启用 ALLOW_INVALID_DATES(已弃用且不解决根本问题)
  • 使用 CAST(cssd.last_date AS CHAR) LIKE ‘2020-02%’(隐式转换不可靠,且同样无法索引)

总结:MySQL 8.0 的严格类型校验是正确行为。应摒弃对 DATE 字段使用字符串通配符的旧习惯,优先采用范围查询(>= ‘YYYY-MM-DD’)保障性能与兼容性;若需灵活年月匹配,辅以 DATE_FORMAT() 或冗余生成列优化。

https://www.php.cn/faq/2028134.html

发表回复

Your email address will not be published. Required fields are marked *