MySQL中查子串应优先用LOCATE以兼顾SQL标准兼容性INSTR为MySQL特有二者功能相同但参数顺序相反查不到返回0查到返回从1开始的位置NULL输入返回NULL且均不走索引。MySQL里查子串用 LOCATE 还是 INSTR两个函数功能完全一样LOCATE 是标准 SQL 风格写法LOCATE(sub, str)INSTR 是 MySQL 特有风格INSTR(str, sub)。选哪个只看团队习惯或 SQL 兼容需求——如果未来可能迁到 PostgreSQL 或 SQL Server优先用 LOCATE纯 MySQL 项目INSTR 更顺手。常见错误是记反参数顺序写成 INSTR(sub, str) 会返回 0找不到但不报错容易误判。实际它第一个参数是被搜索的字符串第二个才是子串。查不到时返回什么怎么安全判断存在性两个函数查不到都返回 0查到则返回**起始位置从 1 开始计数**。所以不能用 IF(LOCATE(...), ...) 直接当布尔值用——因为位置可能是 1而 1 在 MySQL 里是 true没问题但万一子串在开头LOCATE 返回 1逻辑成立可如果写成 LOCATE(...) 0 才是真正稳妥的写法。LOCATE(abc, xabcx) 0 → true推荐LOCATE(abc, xabcx) 单独用于条件 → 虽然也生效但语义模糊易被后续维护者误解INSTR(xabcx, abc) 0 → 错误这是判断“不存在”但漏掉了空字符串或 NULL 输入的边界情况遇到 NULL 或空字符串会怎样只要任意一个参数为 NULLLOCATE 和 INSTR 都直接返回 NULL而不是 0。这意味着如果你没做预处理WHERE LOCATE(sub, col) 0 会把含 NULL 的整行过滤掉——不是因为你没找到而是表达式结果为 NULL而 NULL 0 是 unknown在 WHERE 中等价于 false。安全写法是显式处理WHERE LOCATE(x, col) 0 AND col IS NOT NULL或者更彻底地用 COALESCEWHERE LOCATE(x, COALESCE(col, )) 0。另外注意LOCATE(, abc) 返回 1空字符串被认为在任何字符串开头存在这和多数人直觉不符但符合 SQL 标准定义。性能差异大吗要不要加索引两者底层实现一致性能无差别。但关键点在于**它们都不走索引**。哪怕你在 name 字段建了 BTree 索引WHERE LOCATE(john, name) 0 依然全表扫描。真要查子串且数据量大得换思路前缀匹配用 name LIKE john% → 可走索引后缀匹配用 name LIKE %john → 多数引擎无法走索引除非倒排或函数索引全文检索场景考虑 MATCH ... AGAINST 或外部方案Elasticsearch如果只是固定关键词枚举提前拆解为字段如 has_tag_json JSON_CONTAINS更可控别指望 LOCATE 或 INSTR 优化查询速度——它们是兜底工具不是加速器。