子串定位函数是什么
返回子串首次出现的位置,找不到时返回 0。三个函数的参数顺序不同,这是最常见的抄错点:MySQL 的 LOCATE(子串, 字符串) 与 INSTR(字符串, 子串) 顺序相反,PostgreSQL 用 strpos(字符串, 子串) 或标准写法 position(子串 in 字符串)。
基本信息
| MySQL LOCATE | LOCATE(sub, str[, pos]),可指定起始位置 |
|---|---|
| MySQL INSTR | INSTR(str, sub),参数顺序与 LOCATE 相反 |
| MySQL POSITION | POSITION(sub IN str),标准写法 |
| PostgreSQL | strpos(str, sub) 与 position(sub in str) |
| 未命中 | 都返回 0,注意不是 NULL |
| 下标基准 | 位置从 1 开始计数 |
MySQL 写法
MySQL 写法
SELECT LOCATE('lo', 'hello'); -- 3:子串在前
SELECT INSTR('hello', 'lo'); -- 3:字符串在前,顺序相反
SELECT LOCATE('l', 'hello', 5); -- 0:从第 5 位起找不到
SELECT POSITION('lo' IN 'hello'); -- 3:标准写法
-- 常见组合:定位分隔符后截取前半段
SELECT SUBSTRING('user@example.com', 1,
LOCATE('@', 'user@example.com') - 1) AS user_part;PostgreSQL 写法
PostgreSQL 写法
SELECT strpos('hello', 'lo'); -- 3
SELECT position('lo' in 'hello'); -- 3
-- 只需判断是否包含时,正则或 LIKE 的语义更直接
SELECT email ~ '@' AS has_at FROM users;
SELECT email LIKE '%@%' AS has_at FROM users;函数与参数顺序
| 函数 | 参数顺序 | 所在库 |
|---|---|---|
| LOCATE(sub, str[, pos]) | 子串在前 | MySQL |
| INSTR(str, sub) | 字符串在前 | MySQL |
| POSITION(sub IN str) | 标准语法 | MySQL 与 PG |
| strpos(str, sub) | 字符串在前 | PostgreSQL |
| 未命中返回值 | 0 | 两库一致 |
典型使用场景
- 判断字符串里是否包含某个字符,例如邮箱是否含 @
- 按分隔符首次出现的位置切分字符串
- 数据校验:找出缺少必要分隔符的脏数据
- 解析日志行:定位关键字后截取后面的字段
- 清洗任务:找出含有非法字符的记录
- 标签解析:定位前缀后取出剩余部分
- 报表取值:判断字段是否含某个分隔符,决定后续解析路径
- 批量校验:把定位结果为 0 的记录挑出来人工复核
MySQL 的定位函数受排序规则影响:使用不区分大小写的排序规则时 LOCATE('A','abc') 会返回 1;PostgreSQL 始终区分大小写。跨库脚本要先确认匹配语义,再决定是否统一排序规则。
返回值是 1 基下标:位置 1 表示第一个字符,这与很多编程语言的 0 基下标不同。把结果直接传给数组或切片逻辑前先减 1,否则会整体偏移一位。
把 INSTR 与 LOCATE 的参数顺序互换不会报错,只会返回错误位置或直接返回 0,属于典型的静默错误。写完后用一条已知数据验证返回值,再推广到全表。