如何在SQL Server中用CHARINDEX函数查找子字符串位置

夜涛小哥_2916

夜涛小哥_2916

2026-11-11

633人浏览

原创

CHARINDEX返回从1开始的位置,找不到返回0;参数为NULL时结果为NULL,非SARGable且不支持第N次匹配。

如何在sql server中用charindex函数查找子字符串位置

CHARINDEX 返回的是从 1 开始的位置,不是 0

SQL Server 的 CHARINDEX 函数不遵循编程语言常见的 0 起始索引习惯。如果子字符串存在,它返回第一个匹配字符的**从 1 计数的位置**;找不到则返回 0。这点容易在条件判断中出错——比如写成 WHERE CHARINDEX('abc', col) > 0 是对的,但误写成 >= 1 虽然结果一样,却掩盖了语义:返回值只有 0 或正整数,不存在负数或 NULL(除非任一参数为 NULL)。

常见错误现象:
– 用 IS NULL 判断是否找到(实际返回 0,不是 NULL)
– 在 SUBSTRING 中直接用 CHARINDEX(...) + 1 却没检查是否为 0,导致位置为 1 时截取到开头,位置为 0 时变成 SUBSTRING(..., 1, ...),逻辑错乱

  • 始终用 CHARINDEX(...) > 0 做存在性判断
  • 若用于 SUBSTRING 起始位置,先用 CASE WHEN CHARINDEX(...) > 0 THEN ... ELSE ... END 处理未找到情况
  • CHARINDEX 对大小写是否敏感取决于所在数据库的排序规则(collation),不是函数本身控制

第三个参数 start_location 控制查找起点,但不支持“第 N 次出现”

CHARINDEX 的第三个参数是起始搜索位置(从 1 开始计数),不是“找第几次”。例如 CHARINDEX('o', 'hello world', 5) 会从第 5 个字符(即第一个 o 后的空格)开始往后找,返回第二个 o 的位置(8)。但它**无法直接定位“第二次出现”**——因为如果第一次出现在位置 2,你传入 3,它确实跳过了第一次,但前提是你知道第一次在哪。

  • 想查第 N 次出现,需嵌套调用或配合 STUFF/REPLACE 配合计数逻辑(较重)
  • 第三个参数若超出字符串长度,返回 0;若为 NULL 或小于 1,SQL Server 会报错 Argument data type varchar is invalid for argument 3 of charindex function.
  • 传入负数或非整数(如 1.5)会触发隐式转换,但行为不可靠,应显式转为 INT

NULL 参数会导致整个结果为 NULL,不是 0

只要 CHARINDEX 的任意一个参数(待查字符串、源字符串、起始位置)是 NULL,函数立刻返回 NULL,而不是 0。这和「找不到返回 0」的直觉冲突,尤其在列可能为空的场景下极易漏判。

使用场景举例:用户表里 email 列允许 NULL,你想筛选含 @ 的记录:
❌ 错误写法:WHERE CHARINDEX('@', email) > 0 —— 若 email 为 NULL,整条表达式结果为 NULL,该行被过滤掉(看似合理,但逻辑不透明)
✅ 更安全写法:WHERE email IS NOT NULL AND CHARINDEX('@', email) > 0

  • 在计算列、CTE 或子查询中使用前,先用 ISNULL 或 COALESCE 处理潜在 NULL 输入
  • CHARINDEX(NULL, 'abc') 和 CHARINDEX('a', NULL) 都返回 NULL,没有例外
  • 注意:空字符串 '' 是合法输入,CHARINDEX('', 'abc') 返回 1(因为空字符串被认为在每个位置都“存在”)

性能上,CHARINDEX 无法利用常规索引加速模糊查找

CHARINDEX 是运行时逐字符扫描函数,即使你在 WHERE 子句中用它做过滤(如 CHARINDEX('admin', name) > 0),SQL Server 也无法使用 name 列上的普通 B-tree 索引跳过扫描——本质等价于 LIKE '%admin%',属于非SARGable 表达式。

  • 若高频执行此类查找,考虑添加计算列 + 索引(如 ALTER TABLE t ADD has_admin AS CASE WHEN CHARINDEX('admin', name) > 0 THEN 1 ELSE 0 END PERSISTED,再对该列建索引)
  • 全文索引(Full-Text Index)更适合复杂文本匹配,但配置成本高,且不适用于简单子串定位需求
  • 在 WHERE 中混用 CHARINDEX 和其它 SARGable 条件时,优化器可能仍选择全表扫描,需看实际执行计划确认

实际用起来最常踩的坑,是把 CHARINDEX 当成“安全的字符串查找工具”而忽略它的 NULL 传播性和非SARGable 特性——尤其在数据质量不可控、查询性能敏感的生产环境里,这两点往往比语法细节更致命。

PHP速学视频免费教程(入门到精通)
PHP速学视频免费教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
sqlserver和mysql区别
sqlserver和mysql区别

SQL Server和MySQL是两种广泛使用的关系型数据库管理系统。它们具有相似的功能和用途,但在某些方面存在一些显著的区别。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

2023.08.11

6631

4

数据库三范式
数据库三范式

数据库三范式是一种设计规范,用于规范化关系型数据库中的数据结构,它通过消除冗余数据、提高数据库性能和数据一致性,提供了一种有效的数据库设计方法。本专题提供数据库三范式相关的文章、下载和课程。

2023.06.29

3125

3

如何删除数据库
如何删除数据库

删除数据库是指在MySQL中完全移除一个数据库及其所包含的所有数据和结构,作用包括:1、释放存储空间;2、确保数据的安全性;3、提高数据库的整体性能,加速查询和操作的执行速度。尽管删除数据库具有一些好处,但在执行任何删除操作之前,务必谨慎操作,并备份重要的数据。删除数据库将永久性地删除所有相关数据和结构,无法回滚。

2023.08.14

4201

10

vb怎么连接数据库
vb怎么连接数据库

在VB中,连接数据库通常使用ADO(ActiveX 数据对象)或 DAO(Data Access Objects)这两个技术来实现:1、引入ADO库;2、创建ADO连接对象;3、配置连接字符串;4、打开连接;5、执行SQL语句;6、处理查询结果;7、关闭连接即可。

2023.08.31

3531

3

MySQL恢复数据库
MySQL恢复数据库

MySQL恢复数据库的方法有使用物理备份恢复、使用逻辑备份恢复、使用二进制日志恢复和使用数据库复制进行恢复等。本专题为大家提供MySQL数据库相关的文章、下载、课程内容,供大家免费下载体验。

2023.09.05

1087

5

vb中怎么连接access数据库
vb中怎么连接access数据库

vb中连接access数据库的步骤包括引用必要的命名空间、创建连接字符串、创建连接对象、打开连接、执行SQL语句和关闭连接。本专题为大家提供连接access数据库相关的文章、下载、课程内容,供大家免费下载体验。

2023.10.09

3067

5

数据库对象名无效怎么解决
数据库对象名无效怎么解决

数据库对象名无效解决办法:1、检查使用的对象名是否正确,确保没有拼写错误;2、检查数据库中是否已存在具有相同名称的对象,如果是,请更改对象名为一个不同的名称,然后重新创建;3、确保在连接数据库时使用了正确的用户名、密码和数据库名称;4、尝试重启数据库服务,然后再次尝试创建或使用对象;5、尝试更新驱动程序,然后再次尝试创建或使用对象。

2023.10.16

3047

4

vb连接access数据库的方法
vb连接access数据库的方法

vb连接access数据库方法:1、使用ADO连接,首先导入System.Data.OleDb模块,然后定义一个连接字符串,接着创建一个OleDbConnection对象并使用Open() 方法打开连接;2、使用DAO连接,首先导入 Microsoft.Jet.OLEDB模块,然后定义一个连接字符串,接着创建一个JetConnection对象并使用Open()方法打开连接即可。

2023.10.16

2993

3

vb连接数据库的方法
vb连接数据库的方法

vb连接数据库的方法有使用ADO对象库、使用OLEDB数据提供程序、使用ODBC数据源等。详细介绍:1、使用ADO对象库方法,ADO是一种用于访问数据库的COM组件,可以通过ADO连接数据库并执行SQL语句。可以使用ADODB.Connection对象来建立与数据库的连接,然后使用ADODB.Recordset对象来执行查询和操作数据;2、使用OLEDB数据提供程序方法等等。

2023.10.19

2861

3

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
热门推荐
/
最新课程
phpStudy极速入门视频教程
phpStudy极速入门视频教程

共6课时 | 54.7万人学习

独孤九贱(4)_PHP视频教程
独孤九贱(4)_PHP视频教程

共89课时 | 134.3万人学习