PATINDEX 是 SQL Server 等微软数据库产品中由 Transact-SQL 提供的字符串函数。它在一个字符表达式中查找指定模式首次出现的位置,位置从 1 开始计数,没有匹配时返回 0。[1][2] 其模式使用与 LIKE 相同的通配符,因此能按字符类型或字符范围定位子串,这是它相对只做字面量查找的 CHARINDEX 的主要长处。[1] 在 SQL Server 2022 及更早版本缺少原生正则支持的时期,它常被用于实现较复杂的模式匹配。[1][3]
定义
PATINDEX 属于字符串函数,作用是给出某个模式在目标表达式中首次出现的位置序号,因此常被用来判断一段文本里是否存在符合特定形态的字符。[1][2] 它的写法为 PATINDEX ( '%pattern%' , expression ),其中 pattern 是包含待查找序列的字符表达式,expression 通常是被搜索的字符列或字符表达式。[1]
模式中可以包含 通配符,但 % 需要出现在模式的首尾,只有在搜索第一个或最后一个字符时才例外;模式长度上限为 8000 个字符。[1] 位置从 1 数起;若被搜索表达式为 varchar(max) 或 nvarchar(max) 类型,函数返回 bigint,其他情况下返回 int。[1]
原理
匹配规则与 LIKE 相同,因此 LIKE 可用的通配符 PATINDEX 都能使用,%、_、[ ]、[^ ]、[a-z] 分别对应任意长度字符、任意单个字符、指定字符集合、排除集合与字符范围;模式也不必强制夹在百分号之间,PATINDEX('a%', 'abc') 得到 1,PATINDEX('%a', 'cba') 得到 3。[1]
与 LIKE 只判断是否匹配不同,PATINDEX 输出的是位置,在这一点上与 CHARINDEX 相近;例如 PATINDEX('%ter%', 'interesting data') 的结果是 3,而 PATINDEX('%[^ 0-9A-Za-z]%', 'Please ensure the door is locked!') 的结果是 33。[1]
比较依据输入的排序规则进行,需要指定排序规则时可用 COLLATE 显式施加,因此大小写敏感性由排序规则决定,而不是函数本身的固定行为。[1] 在使用带补充字符的排序规则时,expression 中的 UTF-16 代理项对被计作一个字符;0x0000(char(0))在 Windows 排序规则里属于未定义字符,不能出现在 PATINDEX 中。[1]
mermaid\nflowchart LR\nA[模式 pattern] --> C{PATINDEX 在 expression 中逐字符比对}\nB[expression 被搜索表达式] --> C\nC -->|匹配到| D[返回首次出现的起始位置,从 1 起]\nC -->|未匹配| E[返回 0]\n
发展历程
PATINDEX 至少在 SQL Server 2005 时期已见于微软文档,当时的说明同样要求模式前后带 %,并记载了返回值与数据库兼容级别的关系:兼容级别为 70 时 pattern 或 expression 为 NULL 即返回 NULL,兼容级别不高于 65 时则要两者同时为 NULL 才返回 NULL。[4]
此后该函数随产品线扩展,适用于 SQL Server、Azure SQL 数据库、Azure SQL 托管实例、Azure Synapse Analytics、分析平台系统(PDW)以及 Microsoft Fabric 中的相关服务。[1][2] 在 SQL Server 2022(16.x)及更早版本中,传统正则表达式不被原生支持,类似的复杂匹配需要用各种通配符表达式拼出来。[1]
SQL Server 2025(17.x)开始提供原生 正则表达式 函数,其中 REGEXP_INSTR 既能返回匹配的起始位置,也能返回结束位置,功能强于只返回起始位置的 PATINDEX 与 CHARINDEX。[1][3]
应用
最常见的用法是在 WHERE 子句中把结果与 0 比较,从而筛选出含有某类字符的行,例如用 PATINDEX('%[0-9]%', 列名) > 0 找出字段里含数字的记录;若不加 WHERE 限制,查询会扫描表中所有行,对命中模式的行给出非零值、未命中的行给出 0。[5][1]
它也被用来做数据校验,例如找出包含多个 @ 符号的邮箱记录,用以发现格式异常的地址;在数据清洗中常用它定位模式起点,再配合 SUBSTRING 截取需要的片段;在日志分析里则用于确定错误代码或特定条目出现的位置。[5]
早期文档还指出,PATINDEX 对 text 数据类型有用,并且除 IS NULL、IS NOT NULL 与 LIKE 之外,它也可以出现在 WHERE 子句中作为比较条件。[6]
局限
PATINDEX 不是正则引擎,只接受 LIKE 风格的通配符,重复量词(+、*、{n,m})与分组、分支(( )、|)这类正则语法在 LIKE 和 PATINDEX 中都不存在。[1][7] 模式长度不得超过 8000 个字符,而且 % 的位置会改变语义:写在前面表示前缀匹配、写在后面表示后缀匹配,省略首尾的 % 往往得不到预期结果。[1]
函数只接受模式与被搜索表达式两个参数,不能像 CHARINDEX 那样另行指定开始搜索的位置。[1] 返回值受排序规则影响,同一模式在不同排序规则下可能给出不同结果,控制大小写敏感度需要借助 COLLATE 或列自身的排序规则。[1]
0 表示未找到,含义与 NULL 不同:pattern 为 NULL 时结果为 NULL,因此判断未匹配应比较是否等于 0,而不能依赖 IS NULL。[1] 0x0000(char(0))无法参与匹配。[1] 在大型文本字段上频繁查找时性能可能受影响,可考虑优化查询或改用 全文索引。[5]
该函数并非各数据库通用:MySQL、Oracle、PostgreSQL 都没有 PATINDEX,通常改用 INSTR、POSITION 等函数,MySQL 8.0 起才有功能相近的 REGEXP_INSTR。[8][9] 即便同名,跨产品语义也不一致,例如 SAP IQ 中任一参数为 NULL 时结果为 0,模式超过 126 字节返回 NULL,长度为 0 的模式返回 1,并且不支持 LONG BINARY 数据。[10]
参见
-
SQL Server —— PATINDEX 主要所在的关系数据库产品
-
Transact-SQL —— 提供 PATINDEX 的查询语言
-
CHARINDEX —— 同样返回子串起始位置但不支持通配符的函数
-
LIKE —— 使用同一套通配符语法的模式匹配运算符
-
正则表达式 —— PATINDEX 无法表达、由 SQL Server 2025 原生支持的模式匹配方式
-
通配符 —— PATINDEX 模式中用于匹配字符的符号
参考资料
- PATINDEX (Transact-SQL) . microsoft.com [引用日期2026-09-29]
- patindex-transact-sql . microsoft.com [引用日期2026-09-29]
- red-gate.com 上的网页 . red-gate.com [引用日期2026-09-29]
- PATINDEX (Transact-SQL) . microsoft.com [引用日期2026-09-29]
- 如何在 SQL Server 中使用 `PATINDEX` 函数 . huaweicloud.com [引用日期2026-09-29]
- sql --patindex用法 . aliyun.com [引用日期2026-09-29]
- qiita.com 上的网页 . qiita.com [引用日期2026-09-29]
- PATINDEX . sqlzoo.net [引用日期2026-09-29]
- PATINDEX() replacement in MYSQL . stackoverflow.com [引用日期2026-09-29]
- SAP_IQ_SQL_Reference_en(PDF) . sap.com [引用日期2026-09-29]
浏览次数:0 次
阅读量:0 次 · 阅读完成量:0 次
最近更新:2026-09-29T10:29:34Z
完成率 = 阅读完成量 ÷ 阅读量,分母是阅读量不是浏览次数 —— 关了 JS 的、秒退的都在浏览次数里、不在阅读量里。 详细口径在后台的「数据统计」页。