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
相关推荐
Hazenix2 小时前
Go 指南:一篇文章速通 Golang
开发语言·后端·golang
灯澜忆梦2 小时前
GO_复合类型---指针
开发语言·后端·golang
IT_陈寒2 小时前
SpringBoot自动装配坑了我一天,原来问题出在这
前端·人工智能·后端
星栈3 小时前
深度复盘:比 EventLoop 更隐蔽!Node 微任务堆积引发的线上接口雪崩事故
后端·node.js
名字还没想好☜4 小时前
Go slice 的 append 陷阱:共享底层数组导致的数据串改
开发语言·后端·golang·go·slice
诸神缄默不语4 小时前
FastAPI后端配置CORS中间件支持浏览器跨域访问
后端·fastapi
Fanta丶4 小时前
14.Activiti7 网关 排他网关ExclusiveGateway、并行网关ParallelGateway
后端
明月_清风4 小时前
robots.txt 完全指南:从入门到精通
后端·爬虫
jvmind_dev4 小时前
Java GC 实战指南(番外篇):被忽视的隐形杀手 —— Class Unloading 如何拖垮 GC
java·后端