LOCATE() 这个函数挺有意思:它返回子串第一次出现的位置(从 1 开始计数),找不到就返回 0。参数顺序要记牢——LOCATE(子串, 字符串[, 起始位置]),第三个参数可选,指定从哪开始搜。至于大小写是否敏感,全看数据库的排序规则(collation)。

MySQL 中用 LOCATE() 找字符位置
MySQL 没有标准 SQL 里的 INSTR(),但 LOCATE() 是最直接的替代。它返回子串首次出现的起始位置(从 1 开始),没找到返回 0。
注意:第二个参数是被搜索的字符串,第一个参数才是你要找的字符或子串——这和很多编程语言的函数顺序正好相反,写代码时特别容易搞混。
LOCATE('a', 'banana')→ 返回2(不是 1 哦)LOCATE('x', 'hello')→ 返回0,不是NULL,所以判断时别用IS NULL- 支持第三个参数指定起始搜索位置:
LOCATE('a', 'banana', 3)→ 返回4
PostgreSQL 中用 POSITION() 或 STRPOS()
PostgreSQL 给了你两个选择:POSITION() 符合 SQL 标准,STRPOS() 是 PostgreSQL 自带的别名,行为完全一致。两个都返回从 1 开始的位置,找不到返回 0。
POSITION('o' IN 'hello')→ 返回5;注意语法是POSITION(sub IN str),中间必须用IN关键字STRPOS('hello', 'l')→ 返回3;参数顺序和 MySQL 的LOCATE()一样- 两个函数都不支持指定起始偏移,如果想跳过前 N 个字符,得先用
SUBSTRING()截取再查
SQL Server 中用 CHARINDEX()
CHARINDEX() 是 SQL Server 的标准方案,返回从 1 开始的位置,找不到返回 0。可选第三个参数表示起始搜索位置。
CHARINDEX('e', 'hello')→ 返回2CHARINDEX('l', 'hello', 3)→ 返回4(从第 3 位开始找,跳过了第一个l)- 区分大小写取决于数据库排序规则(collation)。如需忽略大小写,确保列或字符串使用不区分大小写的 collation,比如加
COLLATE SQL_Latin1_General_CP1_CI_AS
跨数据库兼容性问题与常见误判
所有主流数据库都用“从 1 开始”而不是“从 0 开始”,这一点和编程语言的习惯不同。直接参与计算(比如切片)之前务必减 1。另外,返回值为 0 表示未找到,不是错误,所以 WHERE CHARINDEX(...) > 0 才是正确的过滤写法。
- 不要把
LOCATE()和FIND_IN_SET()混用:FIND_IN_SET()只适用于逗号分隔的字符串列表,且只匹配完整项 - 想查所有出现位置?SQL 标准不支持正则全局匹配索引。MySQL 8.0+ 可以用
REGEXP_SUBSTR()配合变量模拟,但性能很差;更现实的做法是导出后用程序处理 - 在
ORDER BY或GROUP BY中使用这些函数时,注意它们不可索引,可能触发全表扫描
实际用的时候,先确认数据库类型,再挑对应函数。拿不准就 SELECT 试一两条数据,看返回值是不是你预期的“从 1 开始”的整数——很多人卡在以为返回的是 0 起始,结果切串偏了。
