charindex准确定位子串起始位置(从1计数),返回0表示未找到,null仅当参数为null,空字符串返回1;主串为null则结果为null;start_location越界返回0;用于substring前须判0防错;区分排序规则,不支持通配符。

CHARINDEX 能准确定位子串在字符串中的起始位置(从 1 开始计数),但遇到 NULL、空字符串或越界情况会返回 0 或 NULL,不是所有“没找到”都返回 -1。
CHARINDEX 返回值的含义必须分清
返回 0 表示子串未找到;返回 NULL 只有一种情况:任一参数为 NULL(比如 CHARINDEX('a', NULL));返回正整数才是真实位置。
- 子串为空字符串
''时,SQL Server 视为“在每个位置都能匹配”,但实际行为是:始终返回1(不是报错,也不是按预期遍历) - 主字符串为
NULL,整个表达式结果就是NULL,不会因start_location参数存在而改变 - 若指定
start_location大于主字符串长度,直接返回0,不报错
用 CHARINDEX 做安全的字符串截取前必须判断
很多人用它配合 SUBSTRING 提取分隔符之间的内容,但漏判 0 会导致 SUBSTRING 报错 “Invalid length parameter passed to the LEFT or SUBSTRING function”。
- 错误写法:
SUBSTRING(@str, CHARINDEX('-', @str) + 1, LEN(@str))—— 若@str不含'-',CHARINDEX返回0,导致起始位置为1,但后续逻辑可能越界 - 正确做法:先用
CASE WHEN CHARINDEX('-', @str) > 0 THEN ... ELSE NULL END包裹 - 更稳妥:用
NULLIF(CHARINDEX('-', @str), 0)把0转成NULL,再配合ISNULL或COALESCE设默认值
CHARINDEX 区分排序规则,大小写敏感性不可忽视
它的匹配行为完全依赖当前上下文的排序规则(collation)。如果字段是 Latin1_General_CS_AS,CHARINDEX('A', 'abc') 就返回 0;而 SQL_Latin1_General_CP1_CI_AS 下会返回 1。
- 临时强制不区分大小写:
CHARINDEX('a', @str COLLATE SQL_Latin1_General_CP1_CI_AS) - 临时强制区分大小写:
CHARINDEX('A', @str COLLATE Latin1_General_CS_AS) - 注意:排序规则冲突可能引发“无法解析的冲突”错误,建议统一字段和字面量的 collation
最常被忽略的是:CHARINDEX 不支持通配符(不像 LIKE),传入 '%a%' 就按字面意思找这三个字符;另外它只找第一次出现,要找第 N 次得靠递归 CTE 或自定义函数。











