POSITION函数返回子串首次出现位置(从1开始),未找到返回0;标准写法为POSITION('sub' IN str),PostgreSQL/MySQL 8.0+支持,旧版MySQL需用LOCATE;大小写敏感,跨库兼容性优于INSTR/CHARINDEX。

POSITION 函数能查字符在字符串里的位置,但注意它只返回第一个匹配的位置,且索引从 1 开始,不是 0。
POSITION 在 PostgreSQL / MySQL / SQL Standard 中怎么用
标准写法是 POSITION('substring' IN string),比如查字母 'o' 在 'hello' 里的位置,结果是 5(不是 4)。MySQL 8.0+ 和 PostgreSQL 都支持;老版本 MySQL 得用 LOCATE('o', 'hello'),顺序相反。
-
POSITION是 SQL 标准函数,跨数据库兼容性比INSTR或CHARINDEX好一点 - PostgreSQL 中大小写敏感,
POSITION('O' IN 'hello')返回0(没找到) - MySQL 5.7 及更早不支持
POSITION,直接执行会报错ERROR 1305 (42000): FUNCTION db.POSITION does not exist
为什么 POSITION 找不到子串时返回 0 而不是 NULL
这是 SQL 标准定义的行为:没匹配就返回 0。这点和 STRPOS(PostgreSQL 专属)不同,后者找不到返回 0,但语义更接近“位置索引”,容易混淆。
- 别用
IS NULL判断是否找到,得写POSITION(...) > 0 - 如果后续要切字符串(比如
SUBSTRING(str FROM pos)),传入0会导致行为异常——PostgreSQL 把SUBSTRING('abc' FROM 0)当成从开头截,MySQL 则可能报错或返回空 - 需要安全截取时,建议套一层
CASE WHEN POSITION(...) > 0 THEN ... ELSE ... END
想查第 N 次出现的位置?POSITION 不行,得换思路
POSITION 只认第一次。要找第二次的 'l' 在 'hello' 中的位置,不能靠它直接解决。
- PostgreSQL 可用递归 CTE 或
regexp_matches配合generate_subscripts - MySQL 8.0+ 可用
REGEXP_SUBSTR+ 自定义序号变量模拟,但性能差 - 更实际的做法:应用层处理——先用
POSITION找第一次,再用SUBSTRING截掉前面部分,再查第二次,循环两次即可 - 示例(PostgreSQL):
POSITION('l' IN SUBSTRING('hello' FROM POSITION('l' IN 'hello') + 1)) + POSITION('l' IN 'hello'),结果是4(第二个l实际位置)
真正麻烦的不是语法,而是不同数据库对“位置”的定义差异——有的从 0 开始,有的从 1;有的对空格/换行敏感,有的忽略;还有嵌套函数时错误不报在哪儿,只报最终结果错。写之前最好先 SELECT POSITION('x' IN 'xyz') 确认下当前环境行为。

















