charindex返回0表示未找到子串;它从1开始计位,null输入导致结果为null,判断需用>0而非is not null;大小写敏感性由排序规则决定;不支持正则或重叠匹配。

CHARINDEX 返回 0 表示没找到子串
在 SQL Server 中,CHARINDEX 是判断子字符串是否存在的最直接函数。它返回子串第一次出现的位置(从 1 开始),找不到就返回 0。很多人误以为返回 NULL 或报错,其实不会——这是最常踩的坑。
-
CHARINDEX('abc', 'xyzabc123')→ 返回4 -
CHARINDEX('def', 'xyzabc123')→ 返回0 -
CHARINDEX(NULL, 'abc')或CHARINDEX('a', NULL)→ 整个表达式结果为NULL,不是0
所以判断逻辑必须写成 CHARINDEX(@substr, @str) > 0,不能写成 IS NOT NULL,更不能直接跟 = 1(位置不一定是 1)。
区分大小写取决于数据库排序规则
CHARINDEX 的行为完全受当前数据库或字段的排序规则(collation)控制。默认安装的 SQL Server 通常是不区分大小写的(如 SQL_Latin1_General_CP1_CI_AS),但如果你连的是 _CS_AS(case-sensitive)规则的库或列,CHARINDEX('A', 'apple') 就会返回 0。
- 查当前数据库排序规则:
DATABASEPROPERTYEX(DB_NAME(), 'Collation') - 临时强制不区分大小写:
CHARINDEX('A', 'apple' COLLATE SQL_Latin1_General_CP1_CI_AS) - 注意:加
COLLATE可能导致索引失效,线上慎用
和 LIKE 比,CHARINDEX 更适合做条件计算
虽然 LIKE '%abc%' 也能判断包含关系,但它无法返回位置信息,也不能在计算列、窗口函数或 CASE 表达式中灵活复用。而 CHARINDEX 是标量函数,天然支持嵌套:
SELECT
name,
CASE
WHEN CHARINDEX('admin', LOWER(name)) > 0 THEN '系统角色'
WHEN CHARINDEX('user', LOWER(name)) > 0 THEN '普通角色'
ELSE '其他'
END AS role_type
FROM users;
另外,LIKE 在前导通配符('%abc')时基本无法走索引,而 CHARINDEX 虽也不走索引,但至少不隐式阻止优化器对其他条件的判断。
CHARINDEX 不支持正则,也处理不了重叠匹配
它只找第一个非重叠匹配。比如 CHARINDEX('aa', 'aaa') 返回 1,不会返回 2(第二个 aa 从位置 2 开始)。如果业务需要统计出现次数或所有位置,得靠递归 CTE 或字符串拆分,CHARINDEX 自身做不到。
- 想统计出现次数?得配合
LEN和替换:(LEN(@str) - LEN(REPLACE(@str, @substr, ''))) / LEN(@substr)(前提是@substr非空) - 想取子串后的内容?用
SUBSTRING(@str, CHARINDEX(@substr, @str) + LEN(@substr), LEN(@str)) - 空字符串
''作为搜索目标时,SQL Server 返回1(视为“在开头找到空串”),这容易引发逻辑偏差
真正复杂模式匹配,别硬扛——该上 CLR 或迁移到支持 STRING_SPLIT + TRY_CAST 组合的版本,或者干脆前置到应用层处理。










