mysql推荐用locate而非instr,因参数顺序相反且locate支持起始位置;postgresql用position或strpos;sql server用charindex;跨库不兼容,需按数据库适配。

MySQL里找字符位置用 LOCATE,别硬套 INSTR
MySQL官方推荐用 LOCATE,不是 INSTR。虽然二者行为相似,但参数顺序相反——LOCATE(substring, string[, position]) 是「子串在前、主串在后」,而 INSTR(string, substring) 正好反过来。新手照着其他数据库(比如 Oracle)习惯写 INSTR('hello', 'e'),结果返回 0,其实是没匹配上,因为 MySQL 的 INSTR 把第一个参数当主串,第二个当子串,但很多人误以为它和 LOCATE 一样。
-
LOCATE('e', 'hello')→ 返回2(正确) -
INSTR('hello', 'e')→ 也返回2(碰巧对了,但语义反直觉) -
INSTR('e', 'hello')→ 返回0(常见误写,主串子串颠倒) - 想从第3位开始搜?
LOCATE('l', 'hello', 3)可行;INSTR不支持起始位置参数
PostgreSQL 没有 INSTR 或 LOCATE,得用 POSITION 或 STRPOS
PostgreSQL 原生不认 INSTR 和 LOCATE,直接执行会报错:ERROR: function instr(unknown, unknown) does not exist。必须换函数:
-
POSITION('e' IN 'hello')→ 返回2,语法固定,不能省略IN -
STRPOS('hello', 'e')→ 同样返回2,参数顺序和 MySQL 的INSTR一致,但这是 PostgreSQL 自己的函数 - 想从某位置起搜?两个函数都不支持偏移量,得先用
SUBSTRING截取再查 - 查不到时都返回
0,不是NULL,注意和空值逻辑区分
SQL Server 用 CHARINDEX,参数顺序和 MySQL 的 INSTR 类似但更严格
CHARINDEX 是 SQL Server 唯一靠谱的字符定位函数,但它对参数类型敏感:两个参数都必须是字符串类型,不能是数字或 NULL 直接传入,否则报错 Argument data type int is invalid for argument 1 of charindex function。
-
CHARINDEX('e', 'hello')→2(OK) -
CHARINDEX('e', column_name)→ OK,只要列是字符串类型 -
CHARINDEX('e', 123)→ 报错,得显式转成CAST(123 AS VARCHAR) - 支持第三个参数指定起始位置:
CHARINDEX('l', 'hello', 3)→4 - 查不到返回
0,不是-1,别按 C 风格逻辑判断
跨数据库写法不稳定,别指望一个函数走天下
同一个 SQL 脚本在 MySQL、PostgreSQL、SQL Server 之间迁移时,INSTR/LOCATE/POSITION/CHARINDEX 全都不兼容。哪怕只是改个参数顺序,也可能导致逻辑错误或运行失败。
- 应用层处理比 SQL 层更可控:比如 Python 用
str.find(),Go 用strings.Index(),返回值语义统一(-1 表示未找到) - 如果非要在 SQL 里做,优先选标准度高的
POSITION(PostgreSQL)或CHARINDEX(SQL Server),但得加注释说明适配库 - 注意大小写:MySQL 默认不区分大小写,PostgreSQL 默认区分,
POSITION('E' IN 'hello')在 PG 里返回0 - 空字符串
''作为子串时,MySQL 和 PG 都返回1,SQL Server 返回0——这个边界情况很容易漏测










