instr是mysql中精确子串查找函数,返回首次出现位置,不支持通配符;模拟like前缀需instr(col,'str')=1,后缀宜用right();无法利用普通索引,性能劣于like前缀匹配。

INSTR函数的基本行为和匹配逻辑
INSTR 是 MySQL 中用于返回子字符串首次出现位置的函数,语法为 INSTR(str, substr)。它不支持通配符,也不做模式匹配,只做精确子串查找——这点和 LIKE 本质不同。当你写 INSTR(title, 'MySQL'),它等价于判断“'MySQL' 是否作为连续字符出现在 title 中”,返回值是位置(≥1)或 0。
- 返回 0 表示未找到,非 0 表示存在(常配合
WHERE INSTR(...) > 0使用) - 区分大小写取决于列的排序规则(如
utf8mb4_0900_as_cs下区分,utf8mb4_0900_ai_ci下不区分) - 不支持
%或_,没法表达“开头是”“结尾是”“中间含”等模糊语义,必须靠拼接或组合实现
用INSTR模拟LIKE 'xxx%'(前缀匹配)
想替代 LIKE 'MySQL%'(查以 MySQL 开头的记录),不能只靠 INSTR(col, 'MySQL') = 1,因为 INSTR 在首字符匹配时才返回 1,这恰好满足前缀要求。
- ✅ 正确写法:
WHERE INSTR(title, 'MySQL') = 1 - ❌ 错误写法:
WHERE INSTR(title, 'MySQL') > 0—— 这实际等价于LIKE '%MySQL%',不是前缀 - 注意:如果字段允许 NULL,
INSTR(NULL, 'x')返回 NULL,需额外处理,例如加AND title IS NOT NULL
用INSTR模拟LIKE '%xxx'(后缀匹配)
INSTR 本身无法直接判断结尾,但可以结合 LENGTH 和字符串长度计算:
- 正确写法:
WHERE INSTR(title, 'SQL') > 0 AND LENGTH(title) - INSTR(title, 'SQL') = LENGTH('SQL') - 1 - 更清晰的等价写法(推荐):
WHERE RIGHT(title, LENGTH('SQL')) = 'SQL'—— 虽然这不是INSTR,但它比硬凑INSTR更可靠 - 如果坚持用
INSTR模拟后缀,容易漏掉重叠情况(如查 'aa' 在 'aaaa' 中的最后位置),INSTR只返回第一次出现位置,不适合后缀判断
性能和索引影响比LIKE还差?
INSTR 是纯函数运算,无论字段是否有索引,都会触发全表扫描(除非配合生成列+函数索引,MySQL 8.0.13+ 支持)。
-
LIKE 'MySQL%'在有 B-tree 索引的字段上能走索引范围扫描 -
INSTR(title, 'MySQL') > 0无法使用普通索引,优化器会放弃索引 - 若真需要高性能模糊查询,优先考虑:
- 前缀查用
LIKE 'xxx%'+ 前缀索引 - 全文检索用
MATCH ... AGAINST(需 FULLTEXT 索引) - 外部方案如 Elasticsearch,而非硬套
INSTR
- 前缀查用
INSTR 不是 LIKE 的替代品,而是另一种语义的字符串定位工具;强行用来“替代”,往往让查询更慢、逻辑更绕、可读性更低。真正该问的不是“怎么用 INSTR 替代 LIKE”,而是“这个场景到底需不需要模糊匹配”。











