news 2026/9/7 3:48:54

SQL LIKE 模糊查询全解析:从通配符、性能优化到防注入最佳实践

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
SQL LIKE 模糊查询全解析:从通配符、性能优化到防注入最佳实践

很多开发者第一次接触 LIKE,是在写“模糊查询”的时候:输入一个关键词,把包含它的记录全部捞出来。这个需求太常见了,常见到我们几乎不会停下来想一个问题——LIKE 真的是实现模糊匹配的最好方案吗?它有哪些容易踩的坑?为什么有时候一条 LIKE 查询能把数据库拖慢好几个数量级?为什么同一个 LIKE 在 MySQL 和 SQL Server 里表现还不一样?这些问题,才是这篇文章真正想讲清楚的东西。

不是简单罗列 LIKE 的语法,而是把 LIKE 放在真实的数据库管理系统场景里,从基础用法、通配符语义、大小写规则、ESCAPE 转义,一路讲到性能优化、SQL 注入风险和替代方案。无论你刚学 SQL,还是在生产环境里被慢查询折磨过,这篇文章都值得读完并收藏。

1. 这篇文章真正要解决的问题

先把话说在前面:SQL 里的 LIKE 远不止“加两个百分号”那么简单。很多初学者以为 LIKE 就是WHERE name LIKE '%关键词%',写完能出结果就算会了。但实际工作中,围绕 LIKE 的问题几乎都是下面这几种:

  • 查出来的结果不对:明明数据存在,LIKE 却匹配不到,或者匹配到了不该匹配的,比如大小写、空格、通配符被当成普通字符。
  • 查询慢到无法接受:一张几百万行的表,LIKE '%关键词%'把全表扫了一遍,接口直接超时。
  • 拼接 SQL 导致安全风险:用户输入被直接拼进 LIKE 条件,等于给 SQL 注入开了门。
  • 不同数据库行为不一致:同样的写法在 MySQL 里没问题,换到 SQL Server 或 PostgreSQL 就踩坑。

这篇文章会对上述问题逐一拆解。你不是来这里背语法的,你是来弄清楚 LIKE 怎么用才不出错的。读完以后,你应该能回答三个问题:什么场景该用 LIKE?用的时候要注意什么?当 LIKE 不够用时,有什么更好的替代方案?

2. LIKE 的基础概念与适用场景

2.1 什么是 LIKE

LIKE 是 SQL 标准中用于字符串模式匹配的操作符,通常放在WHERE子句里,配合通配符实现“模糊匹配”。它的核心作用可以概括为一句话:判断某个字段的值是否符合指定的模式。

与之对应的=是精确匹配。举个例子:

  • WHERE name = '张三'只返回姓名恰好是“张三”的记录。
  • WHERE name LIKE '张%'返回所有姓“张”的人。

这两者的差别,就是程序世界里“等值判断”和“模式判断”的差别。=关心的是“你是不是这个值”,LIKE 关心的是“你符不符合我描述的形态”。

2.2 LIKE 解决什么问题

在真实业务里,用户很少能给出完整准确的值。搜索框里输入“华为”,可能想找的是“华为Mate 60 Pro”“华为笔记本”“华为云服务器”。这种前缀匹配(prefix matching)用=根本写不出来,而 LIKE 可以。

再比如手机号中间四位做脱敏查询、订单号模糊搜索、日志表里按关键字过滤消息,这些都是 LIKE 的典型应用场景。它解决的是数据库管理系统中“不确定完整值”的匹配问题,是精确匹配=的有力补充。

2.3 什么样的场景最适合 LIKE

从实际工程经验来看,LIKE 最适合下面几类场景:

  1. 数据量可控的模糊搜索。比如一张配置表、用户表,量级在几十万以内,LIKE 前缀匹配配合索引可以接受。
  2. 需要兼容多种数据库的简单模糊查询。LIKE 是标准 SQL 能力,MySQL、Oracle、SQL Server、PostgreSQL 全都支持。
  3. 模式匹配逻辑简单,不需要正则表达式那么强的表达能力。
  4. 作为全文检索的降级方案。数据量没到那个量级,没必要引入 Elasticsearch,LIKE 够用就先凑合。

但也要泼一盆冷水:LIKE 并不适合所有模糊搜索场景,尤其是你对查询性能和匹配精度都有要求的时候。后面第五、第六部分会专门讲这个问题。

3. LIKE 语法与通配符详解

3.1 LIKE 基本语法

LIKE 的语法非常简单,标准的 SQL 写法是:

SELECT 列名 FROM 表名 WHERE 列名 LIKE 模式;

模式(pattern)是一个字符串,里面可以包含通配符。SQL 标准里有两个核心通配符:%_

3.2 通配符 % 的含义与用法

%表示匹配任意长度(包括 0)的任意字符序列。

模式含义匹配示例
张%以“张”开头张三、张伟、张无忌
%张以“张”结尾老张(如果姓在后)、组合张
%张%包含“张”张三、老张头、小张三
张%三以“张”开头,以“三”结尾张三、张飞三(但要求同一字段连续满足)

注意一个细节:'张%'会匹配“张”本身,因为%可以代表 0 个字符。这在很多面试题里出现过,属于基础但容易忽略的点。

3.3 通配符 _ 的含义与用法

_表示匹配单个任意字符。它和%的区别,关键在于“量”的精确限制。

模式含义匹配示例
张_“张”后面恰好一个字符张三、张四,不匹配“张伟强”
张__“张”后面恰好两个字符张伟强、张小美,不匹配“张三”
_张%第二个字符是“张”老张、小张,不匹配“张伟”

实际使用中,_的使用频率远低于%,因为业务上“精确控制一个字符长度”的需求不算多。但在字符串格式校验类场景里,_很有用,比如校验手机号前三位和后四位。

理解%_的最佳方式,是把它们类比为正则表达式中的.*.。虽然语义不完全等价(正则里.*可以匹配换行符之外任意字符,SQL 里%匹配的字符集跟排序规则有关),但思维模型是一样的:一个是“任意长度”,一个是“单个位置”。

3.4 不同数据库中的 LIKE 通配符差异

%_在 SQL 标准里是通用的,这点必须记住。但不同数据库管理系统在细节上有差异:

  • MySQL:默认情况下LIKE不区分大小写(取决于表的排序规则,通常为utf8_general_ciutf8mb4_general_ci,_ci 结尾就是不区分大小写)。另外 MySQL 还支持非标准的ESCAPE子句来指定转义字符。
  • PostgreSQLLIKE区分大小写,但提供了ILIKE做不区分大小写的匹配。还支持SIMILAR TO和正则表达式函数。
  • SQL ServerLIKE支持标准通配符,还额外支持[a-z]字符集匹配和[^a-z]反向匹配。这是非常实用的增强能力。
  • OracleLIKE区分大小写,可以使用UPPER(列名) LIKE UPPER('%关键词%')来做不区分大小写的查询。

这段内容先留个印象,后面第四部分会通过代码示例体现这些差异。

3.5 ESCAPE 子句:如何匹配通配符本身

如果用户搜索的关键词里恰好包含%_,怎么处理?比如要查名字叫“100%纯棉”的商品,LIKE '%100%%%'就会让数据库糊涂。

答案是用ESCAPE子句指定一个转义字符。默认的转义字符可以不用写,但需要显式声明:

-- 查询商品名称中包含“100%”的记录 SELECT * FROM products WHERE product_name LIKE '%100\%%' ESCAPE '\';

这段 SQL 的含义是:\后面的%是普通字符,而不是通配符。第一个%和最后一个%仍然是通配符。

这个细节在实际项目中很容易踩坑。用户输入搜索关键词时,程序必须对用户输入里的%_\做转义处理,否则用户搜“100%棉”会返回一堆奇怪的数据。

下面给一个 Java 后端转义 LIKE 关键字的参考实现:

public static String escapeLike(String input) { if (input == null) { return null; } return input .replace("\\", "\\\\") .replace("%", "\\%") .replace("_", "\\_"); }

然后在拼接 SQL 时使用ESCAPE '\'。这块如果不处理,开发环境里测试数据少问题不明显,一到生产环境用户乱输入就开始出问题了。

4. LIKE 完整示例与代码实现

4.1 环境准备

为了让示例真实可跑,本文以 MySQL 8.0 作为主要演示环境,同时标注 SQL Server 和 PostgreSQL 的差异点。一个简单的学生表 + 成绩表就够用了。如果你本地没有 MySQL,可以用 Docker 快速起一个:

docker run --name mysql-like-demo \ -e MYSQL_ROOT_PASSWORD=root123 \ -e MYSQL_DATABASE=student_db \ -p 3306:3306 \ -d mysql:8.0

4.2 建表与初始化数据

-- 文件路径:01_create_table.sql CREATE DATABASE IF NOT EXISTS student_db; USE student_db; DROP TABLE IF EXISTS student; CREATE TABLE student ( id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(50) NOT NULL, student_no VARCHAR(20) NOT NULL, email VARCHAR(100), enroll_year INT );

先插入一批测试数据,覆盖各种边界情况:

-- 文件路径:02_insert_data.sql INSERT INTO student (name, student_no, email, enroll_year) VALUES ('张三', '20230001', 'zhangsan@example.com', 2023), ('张三丰', '20220015', 'zhangfeng@example.com', 2022), ('张伟', '20210088', 'zhangwei@example.com', 2021), ('李四', '20230022', 'lisi@example.com', 2023), ('王五', '20200033', 'wangwu@example.com', 2020), ('张小明', '20230056', 'zhangxiaoming@example.com', 2023), ('陈静', '20210077', 'chenjing@example.com', 2021), ('李静怡', '20220099', 'lijingyi@example.com', 2022), ('张静', '20230101', 'zhangjing@example.com', 2023), ('100%纯棉短袖', 'P2023001', 'product@example.com', 2023);

注意最后一条,故意插入一个包含%的字段值,用来演示 ESCAPE 转义。

4.3 基础 LIKE 查询示例

示例 1:查询所有姓“张”的学生

SELECT id, name, student_no, enroll_year FROM student WHERE name LIKE '张%' ORDER BY enroll_year;

这条 SQL 的语义是“以张开头”,匹配结果包括:张三、张三丰、张伟、张小明、张静。如果表里有人叫“老张”,不会被匹配到。

示例 2:查询姓名中包含“静”的学生

SELECT id, name, student_no, enroll_year FROM student WHERE name LIKE '%静%';

匹配结果:陈静、李静怡、张静。这条 SQL 是典型的包含匹配,也是实际业务中最常见的用法。

示例 3:查询姓“张”且名字一共两个字的学生

SELECT id, name, student_no, enroll_year FROM student WHERE name LIKE '张_';

匹配结果只有“张三”和“张静”,因为它们名字是两个字符,且第一个字符是“张”。“张小明”是三个字,匹配不了。

4.4 LIKE 与 ESCAPE 转义示例

示例 4:查询商品名称中包含“100%”的记录

SELECT id, name FROM student WHERE name LIKE '%100\%%' ESCAPE '\';

这里的关键在于ESCAPE '\'告诉数据库反斜杠是转义字符。第一个%和最后一个%是通配符,中间\%是真实存在的百分号字符。

如果不加 ESCAPE,写成LIKE '%100%%%',数据库会把它解析成“包含100”后面任意字符,结果完全不可控。

示例 5:SQL Server 中匹配以任意字符开头、后面是“张”的写法

-- SQL Server 兼容写法 SELECT id, name FROM student WHERE name LIKE '_[张]%';

在 SQL Server 中,[张]表示匹配单个字符集合中的任意一个。这个语法在 MySQL 里不生效,MySQL 的 LIKE 不直接支持字符集合写法。如果你在 SQL Server 环境使用,这行代码可以更精确地表达“第二个字符是张”的语义。

4.5 NOT LIKE 与组合条件

LIKE 也可以配合NOT使用:

-- 查询姓名中不包含“张”的所有学生 SELECT id, name FROM student WHERE name NOT LIKE '%张%';

还可以和ANDOR组合:

-- 查询 2023 年入学且姓名以“张”开头的学生 SELECT id, name, enroll_year FROM student WHERE enroll_year = 2023 AND name LIKE '张%';

这些都是非常常见的业务组合,逻辑上并不复杂,重点是避免在组合条件里写出互相矛盾的过滤逻辑。

4.6 如何运行和验证

如果你用的是 MySQL 客户端:

mysql -uroot -p root123 -h 127.0.0.1 < 01_create_table.sql mysql -uroot -p root123 -h 127.0.0.1 student_db < 02_insert_data.sql

然后进入交互式客户端逐条执行查询语句,观察返回结果是否符合预期。验证的重点不是“有没有结果”,而是“结果是不是多出来了”或“少掉了”。多出来往往是通配符误用了%,少掉了往往是大小写或排序规则的问题。

4.7 运行结果与效果验证

以示例 1 为例,预期输出大致如下:

+----+--------+------------+-------------+ | id | name | student_no | enroll_year | +----+--------+------------+-------------+ | 1 | 张三 | 20230001 | 2023 | | 2 | 张三丰 | 20220015 | 2022 | | 3 | 张伟 | 20210088 | 2021 | | 6 | 张小明 | 20230056 | 2023 | | 9 | 张静 | 20230101 | 2023 | +----+--------+------------+-------------+

判断成功的标准很简单:返回的行和预期数据一致,不包含“老张”“张二丰他爹”这类不符合前缀规则的记录。如果结果不对,优先按下面顺序排查:

  1. 检查表里的真实数据,确认自己以为的数据和实际存储的数据一致。
  2. 检查字段排序规则(collation),确认是不是大小写或全角半角导致匹配失败。
  3. 去掉%缩小范围,先跑一个精确匹配,确认命令本身没有拼错。

5. LIKE 与性能:为什么 % 开头会让查询变慢

5.1 从全表扫描开始说起

LIKE 最大的性能杀手是前导通配符,也就是LIKE '%关键词'LIKE '%关键词%'这种写法。

原因要从 B+ 树索引的结构说起。数据库索引本质上是按照字段值排序后建立的一种快速查找结构。对于普通索引,在条件col = '关键词'时,数据库可以直接从索引树的根节点一路找到叶子节点,定位到匹配记录。这就是索引带来的加速效果。

但是对于LIKE '%关键词%'%在开头,数据库不知道关键词后面是什么,更不知道前面是什么,所以无法利用索引进行范围扫描。它只能老老实实地从表的第一个数据块开始,逐行读取、逐行尝试匹配,这就是全表扫描(Full Table Scan / Sequential Scan)。

数据量小的时候无所谓,几千条记录扫就扫了。但到了千万级别,全表扫描的磁盘 I/O 和 CPU 开销会迅速放大,一条 LIKE 查询拖垮一个接口的事情在真实项目里并不少见。这也是“慢 SQL 优化”话题中,LIKE '%x%'长期霸榜的原因。

5.2 哪一种 LIKE 写法能走索引

在 MySQL 的 InnoDB 存储引擎下,规则大致如下:

LIKE 写法是否能走索引原因
LIKE '关键词%'可以前缀是确定的,可以用索引范围扫描
LIKE '%关键词'基本不行前缀通配,需要全表扫描
LIKE '%关键词%'基本不行前后都通配,需要全表扫描
LIKE '_关键词%'基本不行_本身也可能让前缀不确定

这里的“基本不行”是有例外的,比如 MySQL 的 ICP(Index Condition Pushdown)和覆盖索引可以带来部分优化,但整体结论仍然稳健:前导通配符会让索引失效。

5.3 查看执行计划

在任何数据库里,遇到 LIKE 查询变慢,第一步都是看执行计划。

MySQL 查看方式:

EXPLAIN SELECT id, name FROM student WHERE name LIKE '张%';

重点关注type列。如果看到ALL,说明是全表扫描;如果看到rangeref,说明走的是索引范围扫描。

对于EXPLAIN结果,有一个常见误区是:只要看到key列有值,就以为走了索引。实际上type = ALL时即使key列有值,也往往只是用到覆盖索引做扫描,并没有真正利用索引加速定位。更稳妥的判断指标,是看rows列是否明显小于总行数。

5.4 利用前缀索引或生成列优化

如果业务一定要做包含匹配,但数据量又大,有几种替代思路。

方案一:把后缀匹配转换成前缀匹配。比如要查询LIKE '%abc',可以在表中增加一个反转列(reversed_col),存储原字段反转后的值,并给反转列建索引。查询时改成WHERE reversed_col LIKE 'cba%',因为反转后的数据,前缀是确定的,就可以走索引了。

MySQL 8.0 支持函数索引(Functional Index),可以直接给REVERSE(col)建立索引。SQL Server 支持计算列 + 索引。PostgreSQL 也有表达式索引。思路都是类似的:让模糊匹配变成确定前缀的匹配。

方案二:在 PostgreSQL 中使用 pg_trgm 扩展,通过 GIN 索引支持LIKE '%关键词%'ILIKE '%关键词%'。这种方法利用了三元组(trigram)的特性,可以在大量文本里做高效的相似度匹配。

方案三:如果业务是全文搜索,且数据量大、更新频繁,可以考虑 MySQL 全文索引(FULLTEXT)、PostgreSQL 全文搜索,或者引入 Elasticsearch 这类专门做检索的中间件。LIKE 在这种场景下的角色应该是“兜底方案”,而不是主角。

6. LIKE 与 SQL 注入:安全风险边界

6.1 SQL 注入为什么会和 LIKE 扯上关系

在数据库管理系统的安全风险里,SQL 注入是长期霸榜的高危问题。而 LIKE 又因为它的“拼接”特性,特别容易被开发者写坏。

最常见的问题代码长这样:

String keyword = request.getParameter("keyword"); String sql = "SELECT * FROM products WHERE product_name LIKE '%" + keyword + "%'"; Statement stmt = connection.createStatement(); ResultSet rs = stmt.executeQuery(sql);

这段代码的问题非常明显:用户输入的keyword被直接拼进 SQL 字符串。如果用户输入:

'; DROP TABLE products; --

拼接后的 SQL 就变成了:

SELECT * FROM products WHERE product_name LIKE '%'; DROP TABLE products; --%'

攻击者利用注释符把后面的内容注释掉,再插入一条破坏性 SQL。这不是理论上的恐吓,这是 SQL 注入攻击里最经典的案例,任何写过几年 SQL 的开发者都应该有敬畏之心。

6.2 参数化查询是底线

正确的写法,是使用参数化查询(PreparedStatement):

String keyword = request.getParameter("keyword"); String sql = "SELECT * FROM products WHERE product_name LIKE ?"; PreparedStatement ps = connection.prepareStatement(sql); ps.setString(1, "%" + keyword + "%"); ResultSet rs = ps.executeQuery();

参数化查询的思路是:把 SQL 语句结构和用户输入的数据彻底分离,数据库先把 SQL 模板解析好,再把参数当作纯数据传入。这样用户输入里的任何内容都只是字符串的一部分,不会改变 SQL 语句的语义。

这里有一个细节要注意:参数化查询解决了 SQL 注入问题,但并没有解决 LIKE 通配符语义问题。如果用户输入%_,它们仍然会被当作通配符处理,查询出来的结果可能超出预期。所以,参数化查询之外,还需要对用户输入做转义处理。两者是配合关系,不是替代关系。

6.3 其他安全注意事项

  1. 最小权限原则:执行 LIKE 查询的应用账号,不应该拥有 DROP、DELETE 这类高权限。即使 SQL 被注入了,破坏范围也有限。
  2. 不要把用户输入直接拼进数据库对象名(表名、列名),包括 LIKE 里的表名。
  3. 日志里不要打印完整的 SQL 拼接过后的语句,防止敏感信息泄露,也防止调试日志本身成为攻击面。
  4. 如果提供的是 REST API 接口,建议在参数校验层限制搜索关键词的长度,比如最大 50 个字符,避免恶意构造超长 LIKE 语句。

7. 什么时候该换掉 LIKE,用什么替代

7.1 业务场景对匹配精度有更高要求

LIKE 的能力边界很清晰:只能做“包含”“前缀”“后缀”这类简单的模式匹配。如果业务需要正则表达式级别的匹配,比如手机号格式校验、邮箱格式校验,LIKE 就力不从心了。

这种场景应该使用数据库自带的正则表达式能力:

  • MySQL:REGEXP_LIKE()REGEXP
  • PostgreSQL:~~*SIMILAR TO
  • SQL Server:较新版本支持LIKE但正则支持不如前两者,需通过 CLR 或数据库层函数实现

但正则表达式的代价是性能通常比 LIKE 更差,尽量不要在核心查询路径上使用。

7.2 全文检索场景

如果业务是做文章搜索、商品描述搜索、日志内容搜索,数据量在百万以上,且需要分词、排序、高亮等功能,LIKE 完全不合适。此时应该考虑:

  • MySQL FULLTEXT 索引,配合MATCH ... AGAINST语法。
  • PostgreSQL 全文搜索,支持 tsvector、tsquery,能处理中文分词配置。
  • Elasticsearch,适合独立搜索引擎架构,功能最强大但也要额外维护一套集群。

7.3 数据量较小且匹配简单时

如果数据量只有几百条或几千条,LIKE 仍然是最简单可靠的方案。不要为了追求“高级”而给一个小系统引入全文搜索引擎,那是过度设计。开发效率和可维护性同样重要,在数据量可控的范畴内,LIKE 的可读性和通用性没有任何替代方案能比。

7.4 一个实用的选型决策思路

简单归纳一下:

场景推荐方案
少量数据,模糊查询LIKE
大量数据,前缀匹配LIKE + 索引,或函数索引
大量数据,包含匹配生成列 + 索引 / pg_trgm / 全文索引
复杂模式校验正则表达式
大规模全文搜索全文索引 / Elasticsearch
关键词搜索 + 排序 + 高亮Elasticsearch 或专业搜索组件

8. LIKE 常见问题与排查方法

问题现象可能原因排查方式解决方案
LIKE 查询结果为空,但确认数据存在大小写不匹配或字段排序规则不同SELECT直接查看原始数据;检查字段 collation使用UPPER(col) LIKE UPPER('%关键词%'),或调整排序规则
匹配到了预期之外的数据%_被当作通配符解释了检查用户输入是否包含通配符%_\做转义,配合ESCAPE子句
查询非常慢%关键词%导致全表扫描执行EXPLAIN查看type=ALL改为前缀匹配、增加生成列索引,或换全文检索
同样 SQL 在 MySQL 有结果、SQL Server 没有两库的排序规则和 LIKE 行为不同查看数据库 collation统一排序规则,或显式使用COLLATE
包含中文时匹配不到编码问题,字符集不一致检查连接字符集和表字符集统一使用utf8mb4
NOT LIKE 排除不掉某些记录字段值为 NULL,NOT LIKE 对 NULL 返回 NULL检查空值数据条件中显式加AND col IS NOT NULL
后端拼接 SQL 被注入用户输入直接拼入 SQL 语句检查代码中的字符串拼接使用参数化查询
搜索关键词包含空格导致匹配异常字段存储了多余空格去掉首尾空格再比较存储时使用TRIM,查询时同样处理

9. 最佳实践与工程建议

9.1 别让 LIKE 出现在核心链路的全表扫描里

这是最重要的一条。凡是用户直接触发的查询路径,都要对 LIKE 的写法保持敏感。能写成前缀匹配就尽量写前缀匹配。写不了,就评估数据量,数据量大就引入替代方案。不要把LIKE '%关键词%'当成万能工具。

9.2 用户输入的转义不能省

后端只要接受用户输入并用 LIKE 查询,就必须考虑转义逻辑。写成一个公共工具方法,所有模块复用,而不是每个 SQL 里手写一遍转义逻辑。这个工具方法应该对\%_三个字符都做处理,并搭配ESCAPE子句。

9.3 索引设计要结合 LIKE 的实际使用

如果业务里频繁出现WHERE name LIKE '张%',那么给name字段建立普通 B+ 树索引就能生效。如果还有WHERE enroll_year = 2023 AND name LIKE '张%',更适合创建组合索引(enroll_year, name),注意列顺序。

如果频繁出现反向前缀匹配LIKE '%com',可以创建函数索引,比如 MySQL 8.0 的CREATE INDEX idx_reverse_email ON student ((REVERSE(email)))

这些索引设计的小技巧,能让 LIKE 查询在不改变业务逻辑的情况下快一个数量级。

9.4 把查询结果纳入监控和预警

在慢 SQL 统计中,LIKE 查询往往占比很高。建议在数据库端开启慢查询日志,定期分析哪些 LIKE 查询耗时最长,针对 Top N 做优化。优化的优先级,建议参考“执行频率 x 单次耗时”这个指标,而不是只看单条 SQL 的绝对耗时。

对于频繁执行的关键 LIKE 查询,还可以加一层缓存。但要注意缓存一致性,数据更新后要主动失效,别让用户看到旧数据,这比缓存命中率更重要。

9.5 写出可读的 SQL

简单说几个 LIKE 相关 SQL 的代码规范:

  • 通配符尽量写在参数一侧、拼接处集中管理,不要散落在多个 SQL 里。
  • 使用ESCAPE '\'时保持一致性,同一项目的转义风格统一。
  • 涉及相同模式的逻辑,抽取成数据库视图,或者后端公共查询方法,避免重复写。
  • 在复杂查询里,给 LIKE 条件加注释,说明匹配意图,方便后来的人维护。

9.6 防止过度设计

最后一条建议,是别把简单问题复杂化。如果表只有几万行,LIKE '%关键词%'也能跑得很快,就没有必要为了“性能优化”去强行引入函数索引或者全文检索。工程上最重要的判断标准是:当前的数据量、查询频率和用户体验,决定当前需要什么方案。永远不要为了炫技而降低系统的可维护性。

10. 总结与后续学习方向

关于 LIKE,核心的知识点可以压缩成三句话:

第一,它是一个模式匹配操作符,%表示任意长度,_表示单个字符,ESCAPE用来匹配通配符本身。

第二,它很好用,但有性能边界和安全边界。前导通配符会让索引失效,用户输入不转义会让 SQL 注入有机可乘。

第三,它不是唯一的模糊匹配方案。前缀匹配、函数索引、全文检索、正则表达式,各自有各自的最佳场景,选型要结合数据量和业务复杂度。

如果你刚开始学 SQL,可以沿着“LIKE 基础 → 通配符细节 → 执行计划 → 索引优化”这条线继续深入,每一步都动手建表、造数据、跑查询。尤其建议自己造一张百万行的测试表,看看LIKE '前缀%'LIKE '%后缀'的执行计划差异有多大。实践带来的体感,比看十篇教程都更有用。

如果你是在生产环境维护数据库,可以把这篇文章里关于ESCAPE、参数化查询、函数索引的内容作为团队内部 review 的 checklist,减少自己和同事在 LIKE 上栽跟头的概率。

LKE 虽小,却贯穿了 SQL 语法、索引原理、安全编码和查询优化好几个核心方向。把一个小知识点挖深了,比囫囵吞枣刷一百个 SQL 面试题更有价值。下一步,建议去查一下你正在用的数据库版本,对照本文的示例实际跑一遍,看看执行计划里到底发生了什么。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/7 3:45:32

PEGASUS方法学:自动驾驶测试验证的底层逻辑与场景库构建指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/7 3:44:50

[Feature Name] Implementation Plan

[Feature Name] Implementation Plan 【免费下载链接】superpowers An agentic skills framework & software development methodology that works. 项目地址: https://gitcode.com/GitHub_Trending/su/superpowers For agentic workers: REQUIRED SUB-SKILL: Use su…

作者头像 李华
网站建设 2026/9/7 3:44:07

高并发红包系统设计:防超发、削峰与异步入账实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/7 3:43:53

Excel 前端 + Access 数据库:轻量级行政管理系统这样搭

关键词&#xff1a;Excel 前端、Access 数据库、行政管理系统、VBA 读写 Access、轻量级 OA 实现行政部的同事诉苦&#xff1a;公司一共 40 多人&#xff0c;固定资产一个表格、考勤一个文件夹、会议室预约一份共享文档&#xff0c;月底汇总数据要对到天黑。很多人第一反应是“…

作者头像 李华
网站建设 2026/9/7 3:41:39

系统架构设计师备考全攻略:资料分类、真题战术与论文模板

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华