position函数返回子串首次出现位置,从1开始计数而非0;未找到返回0而非null;标准语法为position('sub' in str),不同数据库对空字符串、null及大小写处理存在差异。

POSITION函数返回位置从1开始,不是0
所有支持POSITION的数据库(PostgreSQL、MySQL 8.0+、Databricks SQL)都按标准SQL定义:位置索引从1起算。POSITION('o' IN 'hello')返回5,不是4。这点直接影响后续SUBSTRING或LEFT等函数的偏移计算——如果误当0-based用,比如写成SUBSTRING(str FROM POSITION(...) ),会漏掉第一个字符。
常见错误场景:
- 想取“world”之后的内容,却写
SUBSTRING('hello world' FROM POSITION('world' IN 'hello world'))→ 实际截出的是'world'本身,而非后面部分 - 正确做法是加1:
SUBSTRING('hello world' FROM POSITION('world' IN 'hello world') + 1) - 在WHERE中判断存在性时,必须用
POSITION(...) > 0,而不是IS NOT NULL(因为没找到返回0,不是NULL)
语法只有两种合法形式,别混参数顺序
POSITION只接受POSITION('sub' IN str)这一种标准写法,或Databricks/MySQL兼容的POSITION(substr, str [, pos])变体。二者不能混用。
典型翻车点:
- 在PostgreSQL里写
POSITION('x', 'xyz')→ 报错syntax error at or near ',' - 在MySQL 8.0+里写
POSITION('x' IN 'xyz')→ 正常返回1;但写成POSITION('xyz', 'x')→ 返回0(因为把整个'xyz'当子串去查单个'x') - Databricks允许
POSITION('bar', 'abcbarbar', 5),但PostgreSQL不认第三个参数,必须用SUBSTRING+ 嵌套POSITION模拟
空字符串和NULL的处理差异极大
POSITION('', str)在PostgreSQL和Databricks中返回1,但在MySQL 8.0+中会报错Invalid argument to function position;而只要任一参数为NULL,所有平台都返回NULL。
实际写SQL时必须提前防御:
- 字段可能为
NULL?加WHERE col IS NOT NULL或用COALESCE(col, '')兜底 - 要查的子串来自变量或计算字段?先
WHERE sub IS NOT NULL AND sub != '',否则MySQL直接炸 - 跨库迁移时,别依赖
POSITION('', ...)行为——它在PostgreSQL安全,在MySQL不可用
找不到时返回0,不是NULL,也不是-1
这是最容易被忽略的语义细节:POSITION严格遵循SQL标准,未匹配一律返回整数0。这意味着:
-
WHERE POSITION('x', col) IS NOT NULL永远为真(除非col是NULL),根本筛不出含'x'的行 -
WHERE POSITION('x', col) = 0能准确找出不含'x'的记录,但要注意它同时包含col IS NULL的行(因为NULL参与比较结果为UNKNOWN) - 想安全提取子串后内容?必须嵌套
CASE WHEN POSITION(...) > 0 THEN SUBSTRING(...) ELSE ... END,否则传入0给SUBSTRING会导致行为不一致(PostgreSQL从开头截,MySQL可能返回空或报错)
SELECT POSITION('a' IN 'abc'), POSITION('' IN 'abc'), POSITION('A' IN 'abc')确认行为,比背文档管用。











