Day 3:LIKE 与模式匹配 — 让查询学会"模糊搜索"

📌 一句话总结

LIKE 是 SQL 中做模糊匹配的核心运算符,搭配通配符 %(匹配任意长度)和 _(匹配单个字符),实现"包含""开头""结尾"等文本搜索场景。


1. 基础语法

sql 复制代码
SELECT column_list
FROM table_name
WHERE column_name LIKE pattern;
  • LIKE 是区分大小写的(MySQL 默认不区分,取决于 collation)
  • NOT LIKE 取反
  • 模式串中写普通字符就匹配该字符

2. 两个通配符

通配符 含义 示例 匹配结果
% 匹配任意长度(含 0 个字符) '张%' 张三、张无忌、张
_ 匹配恰好一个字符 '张_' 张三、张飞(❌ 张、张无忌)
sql 复制代码
-- 查询所有姓张的员工
SELECT name, email FROM employees
WHERE name LIKE '张%';

-- 查询 "张X" 两个字名字的员工
SELECT name FROM employees
WHERE name LIKE '张_';

-- 查询邮箱包含 @qq.com
SELECT name, email FROM employees
WHERE email LIKE '%@qq.com';

-- 查询名字以 "小" 开头的用户
SELECT username FROM users
WHERE username LIKE '小%';

3. 结合使用

sql 复制代码
-- 名字第二个字是 "大":_ 占一个位置
SELECT name FROM employees
WHERE name LIKE '_大%';
-- 匹配:张大伟、李大牛(❌ 大声、大壮 因为第一个字缺失)

-- 邮箱以 .cn 结尾
SELECT email FROM employees
WHERE email LIKE '%.cn';

-- 手机号前 3 位是 138,后 8 位任意(但只查 11 位)
SELECT phone FROM users
WHERE phone LIKE '138________';

4. 转义通配符

如果要搜索的内容本身包含 %_

sql 复制代码
-- 默认方式:用 ESCAPE 指定转义符
SELECT title FROM articles
WHERE title LIKE '%100%%' ESCAPE '';
-- 匹配:"促销100%折扣"、"升级100%完成"

-- 也可以自定义转义字符
SELECT path FROM files
WHERE path LIKE '%/important_%' ESCAPE '/';
-- 此时的 _ 是普通下划线,不是通配符

实际场景: 搜索文件名含 _ 的日志、产品型号含 % 的数据。


5. 数据库方言差异

PostgreSQL:ILIKE + 正则

sql 复制代码
-- ILIKE:不区分大小写
SELECT name FROM users
WHERE name ILIKE 'zhang%';
-- 匹配:Zhang、zhang、ZHANG

-- SIMILAR TO:带正则的风格
SELECT name FROM users
WHERE name SIMILAR TO '张[三四五]%';
-- 匹配:张三丰、张四海(正则风格的模式匹配)

-- 正则表达式 ~ / ~*(PostgreSQL 独有利器)
SELECT name FROM users
WHERE name ~ '^张[^\s]{1,2}$';
-- 匹配:张飞、张三(2-3字,姓张)
-- ~ 区分大小写,~* 不区分,!~ 取反

MySQL:默认不区分大小写

MySQL 的 LIKE 默认不区分大小写 (取决于表和字段的 collation 设置)。 如果需要区分大小写,用 LIKE BINARY

sql 复制代码
SELECT name FROM users
WHERE name LIKE BINARY 'Zhang%';
-- 只匹配大写 Z,不匹配 zhang

SQLite:简单的 LIKE

SQLite 的 LIKE 默认不区分 ASCII 字母大小写,且不支持 ILIKE 或正则。


6. 性能问题(重要 ⚠️)

sql 复制代码
-- ❌ 以 % 开头的 LIKE 不能走索引
SELECT * FROM logs
WHERE message LIKE '%ERROR%';   -- 全表扫描!

-- ✅ 前缀匹配可以走索引
SELECT * FROM logs
WHERE message LIKE 'ERROR:%';   -- 利用 B-Tree 索引快速查找

-- ✅ 尾部模糊也能走索引
SELECT * FROM logs
WHERE message LIKE '2024-01-%';

为什么?

B-Tree 索引是按字典序 排列的,LIKE 'ABC%' 等价于查 ['ABC', 'ABD') 区间,索引可以快速定位。 但 LIKE '%ABC' 不知道前面是什么,必须扫描所有行。

替代方案

场景 推荐方案
前缀模糊搜索 LIKE 'xxx%' + 索引 ✅
全文搜索(大量文本) 数据库全文索引(MySQL FULLTEXT / PostgreSQL GIN)
搜索引擎级别 Elasticsearch / Meilisearch
任意位置匹配 PostgreSQL 的 pg_trgm 三元组索引
少量数据 直接 LIKE '%text%' 无所谓

7. 实战案例

案例 1:用户搜索

sql 复制代码
-- 搜索框:输入 "张三"
SELECT user_id, username, email, phone
FROM users
WHERE username LIKE CONCAT('%', '张三', '%')
   OR email LIKE '%张三%';
-- ⚠️ 实际产品中应加 LIMIT,防全表爆炸

案例 2:清理含特殊字符的数据

sql 复制代码
-- 找出用户名带下划线的用户(确认下划线是普通字符而非通配符)
SELECT username FROM users
WHERE username LIKE '%/_%' ESCAPE '/';

案例 3:日志按模式分类

sql 复制代码
-- PostgreSQL:用正则提取日志类别
SELECT
    log_entry,
    CASE
        WHEN log_entry ~* 'error|fatal|critical' THEN '严重'
        WHEN log_entry ~* 'warn' THEN '警告'
        WHEN log_entry ~* 'info|debug' THEN '信息'
        ELSE '其他'
    END AS level
FROM system_logs
WHERE log_entry ~ '2024-01-1[5-9]';  -- 1月15-19日的日志

📝 要点总结

概念 要点
% 匹配 0 到任意个字符
_ 匹配恰好 1 个字符
LIKE 区分大小写看数据库/配置
ILIKE PG 专属,不区分大小写
正则 ~ PG 专属,强大灵活
转义 ESCAPE '' 或自定义字符
性能 前缀 % 放在后面才能走索引!
全文搜索 大数据量别用 LIKE,上全文索引或 ES
相关推荐
用户693717500138421 小时前
了解一下 Agent Harness
android·前端·后端
swipe21 小时前
16|(前端转全栈)前端人排查后端问题:curl、traceId、日志、MySQL、Redis 怎么用?
前端·后端·面试
亦暖筑序21 小时前
重新认识 AgentScope-Java 2.0:ReActAgent 负责推理,HarnessAgent 负责运行
java·后端·agent
小林ixn21 小时前
Redis 实战避坑指南:从缓存击穿到高可用,一文全搞定
redis·后端
苍何21 小时前
用 AI 做了套品牌周边,感觉能挂Shopify开卖了
后端
用户2986985301421 小时前
免费在线将 PDF 转为 Word:5 款好用的转换工具
人工智能·后端
newerp21 小时前
unsafe 包与底层编程
后端
orient21 小时前
并发问题排查实战
后端
枫叶V21 小时前
聊天框正在过时:Generative UI 与 A2UI/AG-UI 会怎样改变 AI 应用?
后端
Conan在掘金21 小时前
鸿蒙 7.0 分布式数据盾:DDO 跨端数据对象 + DID 数字身份——可信同步根因
后端