locate函数返回子串在主字符串中首次出现的起始位置(从1开始计数),未找到则返回0;参数为substr、str及可选pos,null输入返回null,空子串返回1,大小写敏感性由collation决定。

LOCATE函数的基本用法和返回值含义
LOCATE 返回子串在主字符串中首次出现的起始位置(从 1 开始计数),没找到则返回 0。它不是标准 SQL 函数,主要在 MySQL 中原生支持,其他数据库如 PostgreSQL、SQL Server 需用 POSITION 或 CHARINDEX 替代。
基本写法:LOCATE('substr', str) 或带起始位置的三参数形式:LOCATE('substr', str, pos)。注意:第三个参数是“从第几个字符开始搜索”,不是“跳过前几个字符”——它影响的是搜索起点,不影响返回值的编号基准。
- 如果
str为NULL或'substr'为NULL,结果恒为NULL -
LOCATE('', 'abc')返回 1(空串视为在任意位置都匹配,按惯例取最左) -
LOCATE('a', 'ABC')返回 0(默认区分大小写,MySQL 的collation决定行为)
区分大小写的实际影响与规避方式
MySQL 中 LOCATE 是否区分大小写,取决于字段或字符串的排序规则(collation)。例如 utf8mb4_0900_as_cs 是区分大小写的,而 utf8mb4_0900_ai_ci 是不区分的。直接靠函数本身无法强制忽略大小写。
安全做法是显式转换:
- 统一转小写:
LOCATE(LOWER('SubStr'), LOWER(str)) - 统一转大写:
LOCATE(UPPER('substr'), UPPER(str)) - 避免在 WHERE 条件里对字段用函数——会导致索引失效;如需高频模糊查找,建议建函数索引(MySQL 8.0+)或改用全文索引
常见错误:混淆 LOCATE 与 INSTR、POSITION 的参数顺序
容易把 LOCATE 和 INSTR(MySQL 中二者功能相同但参数顺序相反)搞混:INSTR(str, 'substr') 而不是 INSTR('substr', str)。PostgreSQL 的 POSITION('substr' IN str) 语法更接近英语表达,但括号内必须用 IN 关键字,写成 POSITION('substr', str) 会报错 ERROR: function position(unknown, unknown) does not exist。
- Oracle 没有
LOCATE,要用INSTR(str, 'substr') - SQL Server 必须用
CHARINDEX('substr', str),且不支持第三个参数(起始位置) - SQLite 支持
INSTR(str, 'substr'),行为类似 MySQL 的INSTR
性能隐患:在 WHERE 子句中对字段调用 LOCATE
写成 WHERE LOCATE('abc', content) > 0 看似简洁,但会让 content 字段上的普通 B-tree 索引完全失效——因为是对字段施加了函数。即使内容很长,MySQL 也得全表扫描。
- 替代方案:用
content LIKE '%abc%'(仍无法用前导通配符走索引) - 真要高效匹配子串,考虑
FULLTEXT索引 +MATCH ... AGAINST,或引入 Elasticsearch - 若只是前缀匹配,用
content LIKE 'abc%'可走索引
真正容易被忽略的是 collation 对性能的隐性影响:一个 _ci 排序规则的字段,在 LOCATE 中做大小写不敏感比较时,可能比 _cs 慢——因为内部要逐字符做映射转换。











