%
匹配任意长度字符(如 '张%'
找姓张的记录),2. _
匹配单个字符(如 '李_'
找两个字且姓李的),3. 注意通配符位置影响查询性能(避免开头用%
)在数据库操作中,精确查找(比如查找 id = 1001
或 name = '张三'
)是常见的需求,但很多时候,我们可能只知道信息的一部分,或者需要查找包含特定模式的数据,这时,就需要用到模糊查询。
模糊查询的核心在于使用特殊的通配符来匹配不确定的字符或字符串片段,在大多数主流关系型数据库(如 MySQL, PostgreSQL, SQL Server, Oracle)中,实现模糊查询最常用的工具是 LIKE
操作符。
模糊查询的核心:LIKE
操作符与通配符
LIKE
操作符用在 WHERE
子句中,用于搜索列中匹配指定模式的值,它的威力来自于两个主要的通配符:
-
(百分号):
- 含义: 代表零个、一个或多个任意字符。
- 示例:
WHERE name LIKE '张%'
:查找所有以“张”开头的名字(如“张三”、“张伟”、“张三丰”)。WHERE email LIKE '%@gmail.com'
:查找所有以“@gmail.com”结尾的邮箱(如“example@gmail.com”、“john.doe@gmail.com”)。WHERE description LIKE '%数据库%'
:查找描述中包含“数据库”这个词的所有记录(如“学习数据库知识”、“数据库管理系统”、“高性能数据库”)。WHERE product_name LIKE '%手机%'
:查找产品名称中包含“手机”的所有商品。
-
_
(下划线):- 含义: 代表一个单一的任意字符。
- 示例:
WHERE name LIKE '_三'
:查找名字只有两个字,且第二个字是“三”的名字(如“张三”、“李三”,但不会匹配“张三丰”或“王三石”)。WHERE code LIKE 'A_C'
:查找代码是三个字符,以’A’开头,以’C’中间是任意一个字符的记录(如“ABC”、“AXC”、“A1C”)。WHERE phone LIKE '13_%'
:查找手机号以“13”开头,第三位是任意一个字符,后面还有任意字符的记录(匹配所有13X开头的手机号)。
组合使用通配符
你可以将 和 _
组合起来,构建更复杂的模式:
WHERE name LIKE '张_%'
:查找以“张”开头,后面至少还有一个字符的名字(匹配“张三”、“张伟”,不匹配单独的“张”)。WHERE address LIKE '%区__路%'
:查找地址中包含“区”字,区”后面紧跟着两个任意字符,然后是“路”字的记录(如“XX区中山路XX号”、“YY区解放路YY大厦”)。WHERE filename LIKE 'report_2025-__-%.xlsx'
:查找文件名以“report_2025-”开头,接着是两个字符(代表月份),然后是“-”,再接着是任意字符(代表日期),最后以“.xlsx”结尾的文件(如“report_2025-01-01.xlsx”, “report_2025-12-31_final.xlsx”)。
转义通配符:ESCAPE
子句
如果你需要查找的字符串本身就包含 或 _
字符(例如查找包含“折扣率 5%” 或 “user_id” 的记录),就需要使用 ESCAPE
子句来告诉数据库哪个字符是转义字符,将通配符当作普通字符处理。
- 示例:
WHERE note LIKE '%折扣率 5!%%' ESCAPE '!'
- 这里 被定义为转义字符。
- 表示查找一个普通的百分号 。
- 这个查询会匹配包含“折扣率 5%”的笔记(如“本次促销折扣率 5%”,“最终折扣率 5%”)。
模糊查询的注意事项(重要!)
-
性能影响:
- 模糊查询,尤其是以 开头的查询(如
LIKE '%keyword'
或LIKE '%keyword%'
),通常无法有效利用数据库索引,这意味着数据库需要进行全表扫描,逐行检查数据是否符合模式,对于大型表,这可能会非常慢。 - 优化建议:
- 尽量避免以 开头,如果可能,使用
LIKE 'keyword%'
(前缀匹配),这种查询有时可以利用索引(取决于数据库和索引类型)。 - 考虑使用全文搜索引擎(如 Elasticsearch, Solr)或数据库内置的全文索引功能(如 MySQL 的
FULLTEXT
索引, PostgreSQL 的tsvector
/tsquery
)来处理复杂的文本搜索需求(包含多个词、词干提取、同义词等),它们的效率远高于LIKE
的模糊查询。 - 确保被查询的列上有合适的索引(虽然对
%keyword%
帮助有限,但对keyword%
可能有帮助)。 - 明确需求,只在确实需要模糊匹配时使用
LIKE
。
- 尽量避免以 开头,如果可能,使用
- 模糊查询,尤其是以 开头的查询(如
-
大小写敏感性:
- 模糊查询是否区分大小写取决于数据库的排序规则(Collation)设置。
- 在默认区分大小写的排序规则下,
LIKE 'apple'
不会匹配 “Apple”。 - 如果需要不区分大小写的模糊查询,通常有两种方法:
- 使用函数: 将列和搜索值都转换为相同的大小写(如
WHERE LOWER(name) LIKE LOWER('%apple%')
)。 - 使用特定排序规则: 在查询或数据库/表/列设置中指定不区分大小写的排序规则(如
WHERE name LIKE '%apple%' COLLATE utf8_general_ci
– 具体名称因数据库而异),使用函数通常会影响索引使用。
- 使用函数: 将列和搜索值都转换为相同的大小写(如
-
SQL 注入风险:
- 如果模糊查询的模式字符串是由用户输入直接拼接而成的(如
"SELECT ... WHERE name LIKE '%" + userInput + "%'"
),会存在严重的 SQL 注入漏洞。 - 绝对安全的方法: 始终使用参数化查询(Prepared Statements) 或存储过程来传递用户输入值,数据库驱动程序会正确处理这些值,确保它们被安全地当作数据(而非 SQL 代码的一部分)来处理。
- 如果模糊查询的模式字符串是由用户输入直接拼接而成的(如
其他数据库中的模糊查询
- SQLite: 同样使用
LIKE
和 /_
通配符。 - Oracle: 除了
LIKE
,还提供REGEXP_LIKE
函数进行更强大的正则表达式匹配。 - SQL Server: 除了
LIKE
,也提供PATINDEX
和更强大的全文搜索功能。 - PostgreSQL: 除了
LIKE
和ILIKE
(不区分大小写的 LIKE),还支持强大的 (正则表达式匹配)操作符和全文搜索。
模糊查询是数据库检索中不可或缺的功能,通过 LIKE
操作符配合 (多个字符)和 _
(单个字符)通配符实现,它非常灵活,可以查找开头、包含特定模式或符合特定字符长度的数据,务必注意其性能开销(尤其是 开头的模式)和潜在的 SQL 注入风险,优化策略包括避免前导通配符、考虑使用全文搜索以及始终使用参数化查询来保证安全,理解你的数据库的大小写敏感性规则和提供的其他模式匹配工具(如正则表达式)也很重要。
引用说明:
- 基于通用的 SQL 标准(特别是
LIKE
操作符和通配符的定义)以及主流关系型数据库(MySQL, PostgreSQL, SQL Server, Oracle, SQLite)的通用实现。 - 关于特定数据库(如 Oracle 的
REGEXP_LIKE
, PostgreSQL 的 , SQL Server 的全文搜索)的扩展功能,可参考各自的官方文档:- MySQL: https://dev.mysql.com/doc/
- PostgreSQL: https://www.postgresql.org/docs/
- SQL Server: https://docs.microsoft.com/en-us/sql/sql-server/
- Oracle: https://docs.oracle.com/en/database/
- SQLite: https://www.sqlite.org/docs.html
- SQL 注入和参数化查询的重要性,是 Web 应用安全(如 OWASP Top 10)的核心原则之一,可参考 OWASP 相关资源:https://owasp.org/www-project-top-ten/。
原创文章,发布者:酷盾叔,转转请注明出处:https://www.kd.cn/ask/46805.html