instr函数返回子串在主串中首次出现的位置(从1开始),未找到返回0;语法为instr(str, substr),参数顺序不可颠倒,null参与运算结果为null。

INSTR函数的基本用法和返回值含义
INSTR 是 MySQL 中用于定位子字符串首次出现位置的函数,它从左往右搜索,返回起始索引(从 1 开始计数),不是从 0。如果没找到,返回 0 —— 这点和 LOCATE 行为一致,但参数顺序相反。
常见错误是误以为返回 0 表示“在开头”,其实 0 只代表“未匹配”。比如 INSTR('hello', 'xyz') 返回 0,而 INSTR('hello', 'h') 返回 1。
-
INSTR(str, substr):必须两个参数,str是主串,substr是待查子串 - 不支持指定起始偏移(这点不如
LOCATE(substr, str, pos)灵活) - 区分大小写取决于字段的 collation;若列是
utf8mb4_0900_as_cs就大小写敏感,_ai结尾则不敏感
INSTR vs LOCATE:什么时候该换用LOCATE
当需要从指定位置开始搜索,或想让子串参数写在前面(更符合直觉),就该用 LOCATE。例如查找第二次出现的位置,INSTR 无法直接做到,但可以组合使用:
SELECT LOCATE('o', 'hello world', INSTR('hello world', 'o') + 1);
上面这句找第二个 'o' 的位置,而 INSTR 本身不接受第三个参数,硬套会报错 Incorrect parameter count in the call to native function 'INSTR'。
-
INSTR('abcabc', 'ab')→1 -
LOCATE('ab', 'abcabc')→1(等价) -
LOCATE('ab', 'abcabc', 2)→4(从第 2 位起搜,INSTR做不到)
在WHERE条件中用INSTR做模糊位置过滤
比起 LIKE '%xxx%',INSTR 更适合判断“是否出现在前 N 个字符内”这类逻辑。例如查用户名前 5 位含 'admin' 的记录:
SELECT * FROM users WHERE INSTR(username, 'admin') BETWEEN 1 AND 5;
注意不能写成 INSTR(username, 'admin') ,因为没匹配时返回 <code>0,也会被误判进去。所以得显式限定下界为 1。
- 性能上,
INSTR无法利用普通 B+Tree 索引加速,跟LIKE一样属于全表扫描场景 - 若字段有前缀索引(如
username(10)),INSTR仍不能走索引 - 想真正提速,得靠生成列 + 函数索引(MySQL 8.0.13+):
ALTER TABLE users ADD COLUMN has_admin TINYINT AS (INSTR(username, 'admin') > 0) STORED, ADD INDEX idx_has_admin (has_admin);
处理空值和边界情况的坑
INSTR 对 NULL 很敏感:任一参数为 NULL,整个结果就是 NULL。这在 WHERE 或 ORDER BY 中容易引发意外过滤或排序异常。
例如 SELECT INSTR(NULL, 'a') → NULL,SELECT INSTR('test', NULL) → 同样 NULL。线上查询若没加 IS NOT NULL 判断,可能漏掉本应命中的行。
- 安全写法:在关键条件中补
AND column_name IS NOT NULL - 避免在
ORDER BY INSTR(...)中混入NULL,会导致这些行排在最前或最后(取决于ASC/DESC和 SQL mode) - 空字符串
''作为子串时,INSTR('abc', '')返回1(MySQL 规定空串总在位置 1 匹配)
实际用的时候,别只盯着“快”字——INSTR 本身函数开销极小,真正的瓶颈永远在数据量和索引设计上。把条件写对、把 NULL 想全,比纠结用哪个函数更重要。











