判断一个字符串字段里是否包含某个字符或子串,看起来是件小事,但在实际项目中却经常引发问题:有人用LIKE导致全表扫描拖垮接口性能,有人在MySQL里照搬SQL Server的CHARINDEX直接报错,还有人被大小写敏感、通配符转义这些细节坑过。本文把SQL中判断字符串包含关系的几种主流方法逐一拆开讲清楚,包括写法、原理、跨数据库差异以及容易被忽视的坑。

一、LIKE 模糊匹配:最常用的判断方式
LIKE是SQL标准中定义的模糊匹配操作符,几乎所有数据库都支持。判断是否包含某段子串时,只需要在前后各加一个百分号:WHERE name LIKE '%abc%'。百分号匹配任意长度(包括零长度)的字符序列,因此两侧包裹目标子串就等价于包含判断。
需要注意通配符的差异。除了百分号,SQL Server和MySQL还支持下划线_匹配单个字符,方括号[]是SQL Server特有的字符集合语法,例如LIKE '%[0-9]%'可以判断字符串中是否包含数字。如果目标子串本身包含百分号或下划线,必须显式转义,否则匹配结果会出错。
-- SQL Server 中转义下划线,判断是否包含字面意义的下划线 SELECT * FROM users WHERE name LIKE '%\_%' ESCAPE '\'; -- SQL Server 判断是否包含数字字符 SELECT * FROM products WHERE code LIKE '%[0-9]%'; -- MySQL 判断是否包含数字,只能借助REGEXP SELECT * FROM products WHERE code REGEXP '[0-9]';
LIKE的返回值是布尔型,只能用于WHERE、CASE WHEN等条件位置,不能直接拿到匹配的位置信息,这是它和后面几个函数的本质区别。另外要警惕前置百分号带来的索引失效问题,数据量大时应考虑全文索引或倒排类方案。
二、CHARINDEX 与 PATINDEX:SQL Server 的两把利器
CHARINDEX是SQL Server中最直接的包含判断函数,语法为CHARINDEX(要找的字符串, 被搜索的字符串[, 起始位置]),返回子串第一次出现的起始位置,找不到返回0。配合大于零的比较就能完成包含判断:
-- 返回位置大于0即表示包含
SELECT * FROM articles WHERE CHARINDEX('数据库', title) > 0;
-- 从第5个字符开始查找,常用于跳过前缀
SELECT CHARINDEX('a', 'banana banana', 5) AS pos; -- 结果为 4 之后的出现位置
PATINDEX可以理解为支持通配符的CHARINDEX,语法是PATINDEX('%模式%', 字符串),模式部分可以写百分号、下划线、方括号等通配符。例如PATINDEX('%[0-9]%', col)返回第一个数字出现的位置,配合SUBSTRING可以精准提取数字片段,这是CHARINDEX做不到的。
两者返回值都可能是0或具体位置,判断包含时务必写大于0而不是不等于-1,这是从其他语言习惯迁移过来最容易犯的错。
三、MySQL 与 Oracle:INSTR、LOCATE、POSITION 各有千秋
MySQL中首选INSTR,语法为INSTR(被搜索的字符串, 要找的字符串)。注意参数顺序和CHARINDEX正好相反,跨库迁移时这是经典陷阱。LOCATE则和CHARINDEX参数顺序一致,还支持第三个参数指定起始位置。POSITION是标准SQL写法,使用特殊语法POSITION('abc' IN col)。
-- MySQL 三种等价写法
SELECT * FROM users WHERE INSTR(name, '张') > 0;
SELECT * FROM users WHERE LOCATE('张', name) > 0;
SELECT * FROM users WHERE POSITION('张' IN name) > 0;
-- Oracle 中的 INSTR 支持更丰富的参数
SELECT INSTR('hello world hello', 'hello', 1, 2) FROM dual; -- 从第1字符起找第2次出现,返回14
Oracle的INSTR功能最强大,支持起始位置和第几次出现两个扩展参数,甚至允许起始位置为负数表示从尾部倒数查找,处理分隔符提取场景时非常灵活。此外Oracle还提供INSTRB按字节查找,中文场景要注意字符集区别。
还要注意大小写问题。SQL Server默认排序规则不区分大小写,而Oracle和很多MySQL排序规则默认区分大小写。如果需要忽略大小写判断,可以在比较前统一转换:WHERE INSTR(LOWER(name), LOWER('ABC')) > 0。
四、方法选型建议与性能注意事项
从功能上选:只需要判断是否包含,LIKE最简洁通用;需要拿到位置做进一步截取,用CHARINDEX、PATINDEX或INSTR;需要模式匹配(比如包含数字、包含某几个字符之一),SQL Server用PATINDEX或LIKE加方括号,MySQL用REGEXP,Oracle用REGEXP_LIKE。
从性能上讲,无论是前置百分号的LIKE还是这类定位函数,多数情况下都无法走普通索引,会触发全表扫描。数据量在几十万以内通常无感,超过百万级就要考虑优化:为字段建立全文索引(MySQL的FULLTEXT、SQL Server的全文检索)、引入搜索引擎中间件,或者把高频查询的包含关系冗余成标志位字段。函数写在字段上会导致索引失效,这一点在写WHERE条件时要时刻提醒自己。
最后给一个跨库兼容的小技巧:如果项目需要同时兼容多个数据库,优先使用标准SQL的POSITION或者INSTR在条件中做大于零判断,配合各数据库的方言适配层封装,可以大幅减少迁移成本。掌握这些函数的参数顺序、返回值约定和大小写规则,包含判断这类问题基本不会再成为绊脚石。
SQL字符串函数CHARINDEXPATINDEXLIKEINSTRLOCATE修改时间:2026-09-15 20:46:52