乐途乐途
主页
  • 计算机基础

    • TCP/IP协议
    • Linux命令
    • HTTP协议
  • 数据库

    • SQL
    • MySQL 5.7
  • 编程语言

    • C语言
    • Python2
    • Python3
  • 数据格式

    • JSON
    • XML
  • 认证与安全

    • JWT
  • 工具

    • Markdown
  • Git

    • GitFlow
  • Quartz

    • Quartz
  • Java

    • MyBatis
    • Spring
    • Spring MVC
    • Maven 入门
    • Maven 进阶
    • Java 设计模式
  • 缓存

    • Redis
联系
阿里云
主页
  • 计算机基础

    • TCP/IP协议
    • Linux命令
    • HTTP协议
  • 数据库

    • SQL
    • MySQL 5.7
  • 编程语言

    • C语言
    • Python2
    • Python3
  • 数据格式

    • JSON
    • XML
  • 认证与安全

    • JWT
  • 工具

    • Markdown
  • Git

    • GitFlow
  • Quartz

    • Quartz
  • Java

    • MyBatis
    • Spring
    • Spring MVC
    • Maven 入门
    • Maven 进阶
    • Java 设计模式
  • 缓存

    • Redis
联系
阿里云
  • 学习路径
  • 第1章 数据库基础与安装

    • MySQL 简介
    • MySQL 5.6 到 5.7 到 8.0 关键差异速查
    • 安装 MySQL 5.7
    • 连接与断开服务器
    • 创建数据库
    • 创建数据表
    • 数据库与数据表
    • 加载数据
    • 获取数据库信息
    • 批处理模式
    • SHOW 语句汇总
    • FLUSH 与 RESET 语句
    • my.cnf 核心参数
    • 字符集与排序规则
  • 第2章 SQL基础查询

    • SELECT
    • WHERE
    • ORDER BY
    • LIMIT
    • COUNT
    • 聚合函数
    • 比较运算符
    • 逻辑运算符
    • 算术运算符
    • 模式匹配
    • NULL 值处理
    • UPDATE
    • DELETE
    • REPLACE
    • SELECT INTO
  • 第3章 数据类型与运算符

    • 数值类型
    • 字符串类型
    • 日期时间类型
    • BIT 类型
    • ENUM 类型
    • SET 类型
    • JSON 类型
    • 类型转换
  • 第4章 函数与表达式

    • 字符串函数
    • 数值函数
    • 日期函数
    • 全文检索函数
  • 第5章 高级查询与子查询

    • JOIN
    • 子查询
    • UNION
    • GROUP BY
    • HAVING
    • DISTINCT
  • 第6章 表与索引

    • 数据定义语言
    • 修改表结构
    • 视图
    • 修改视图与检查选项
    • 外键
    • 索引
    • 唯一索引
    • 复合索引
    • 存储引擎对比
    • 分区表
    • 第一范式与第二范式
    • 第三范式与 BC 范式
    • 反范式设计
  • 第7章 存储过程与函数

    • 存储过程
    • 存储函数
    • 变量
    • 流程控制
    • 游标
    • 预处理语句
  • 第8章 事务与锁

    • 事务
    • 事务隔离级别
    • 锁机制
    • MVCC
    • 死锁专题分析
    • LOCK TABLES
    • XA 事务
  • 第9章 用户管理与安全

    • 用户管理
    • 权限管理
    • 角色
    • SQL 注入防范
  • 第10章 性能优化入门

    • 执行计划
    • 索引优化
    • 查询优化
    • 查询优化器提示
    • 慢查询日志
    • InnoDB 深入机制
    • InnoDB 专项优化
    • Performance Schema
    • sys Schema
  • 第11章 复制与高可用

    • 主从复制原理
    • 半同步复制配置
    • binlog 开启与 point-in-time 恢复
    • mysqldump 全库备份
    • mysqldump 单表与条件备份
    • mysqldump 恢复与导入
    • xtrabackup 全量热备
    • xtrabackup 准备与恢复
    • xtrabackup 增量与流式备份
  • 第12章 触发器与事件

    • 触发器
    • 事件调度器
  • 参考

    • MySQL 5.7 专业术语大全
    • MySQL 5.7 关键字与保留字大全

模式匹配

导学

精确匹配和范围查询无法满足所有需求。当你需要"查找姓白的员工"或"查找产品名以 Pro 结尾的商品"时,就需要模式匹配。MySQL 提供了 LIKE 和 REGEXP 两种方式。

定义

模式匹配:通过特殊通配符或正则表达式,对字符串进行模糊匹配的技术。LIKE 使用简单的通配符,REGEXP 使用正则表达式,功能更强但性能更差。

演示数据准备

DROP TABLE IF EXISTS employees;

CREATE TABLE employees (
    emp_id INT PRIMARY KEY AUTO_INCREMENT,
    emp_name VARCHAR(20),
    dept VARCHAR(20),
    score DECIMAL(5,2)
);

INSERT INTO employees (emp_name, dept, score) VALUES
('大翔', '技术部', 100),
('白歌', '技术部', NULL);

当前 employees 表中的完整数据如下:

emp_idemp_namedeptscore
1大翔技术部100
2白歌技术部NULL

LIKE 运算符

LIKE 使用两个通配符:

  • %:匹配任意长度的任意字符(包括空字符)
  • _:匹配单个任意字符

场景一:前缀匹配(最常用,可利用索引)

当前数据状态:见上文 employees 表完整数据。

执行语句:

SELECT emp_name, dept FROM employees WHERE emp_name LIKE '白%';

操作后结果:

emp_namedept
白歌技术部

结果解读:白% 匹配以"白"开头的任何字符串。前缀匹配在某些情况下可以利用索引(如 utf8mb4_general_ci 排序规则),是 LIKE 中性能最好的形式。

场景二:后缀匹配(无法利用普通索引)

当前数据状态:见上文 employees 表完整数据。

执行语句:

SELECT emp_name, dept FROM employees WHERE emp_name LIKE '%蓝';

操作后结果:

emp_namedept

结果解读:%蓝 匹配以"蓝"结尾的姓名。% 在开头时,MySQL 无法使用普通 B-Tree 索引,必须全表扫描。大数据量时极慢。

场景三:包含匹配(无法利用普通索引)

当前数据状态:见上文 employees 表完整数据。

执行语句:

SELECT emp_name, dept FROM employees WHERE emp_name LIKE '%歌%';

操作后结果:

emp_namedept
白歌技术部

结果解读:%歌% 匹配包含"歌"字的任何姓名。这是业务中最常见的模糊搜索需求,但前后都有 % 时完全无法使用 B-Tree 索引。

再看一个部门包含匹配的示例:

SELECT emp_name, dept FROM employees WHERE dept LIKE '%术%';

操作后结果:

emp_namedept
大翔技术部
白歌技术部

结果解读:%术% 匹配包含"术"字的任何部门。技术部包含"术"字,因此大翔和白歌被返回。

场景四:单字符匹配

当前数据状态:见上文 employees 表完整数据。

执行语句:

-- 匹配"白某"(白 + 恰好一个字符)
SELECT emp_name FROM employees WHERE emp_name LIKE '白_';

操作后结果:

emp_name
白歌

结果解读:白_ 匹配"白"后面跟恰好一个字符的字符串。"白歌"符合(白+歌),而如果存在"白歌儿"则不符合。

再看匹配恰好两个字符的姓名:

-- 匹配恰好两个字符的姓名
SELECT emp_name FROM employees WHERE emp_name LIKE '__';

操作后结果:

emp_name
大翔
白歌

结果解读:__(两个下划线)匹配恰好两个字符的字符串。表中所有员工姓名均为两个字,因此全部返回。

场景五:匹配通配符本身

执行语句:

-- 查找包含百分号的字符串(需转义)
SELECT '限时折扣50% off' AS description WHERE '限时折扣50% off' LIKE '%\%%' ESCAPE '\\';

操作后结果:

description
限时折扣50% off

结果解读:ESCAPE '\\' 指定反斜杠为转义字符,\% 表示匹配字面意义的百分号,而非通配符。如果不转义,LIKE '%%%' 会匹配所有包含任意字符的字符串,失去筛选意义。

REGEXP 运算符

REGEXP(或 RLIKE)支持完整的正则表达式匹配,功能远强于 LIKE。

场景六:正则匹配姓名格式

当前数据状态:见上文 employees 表完整数据。

执行语句:

SELECT emp_name, dept FROM employees
WHERE emp_name REGEXP '^..$';

操作后结果:

emp_namedept
大翔技术部
白歌技术部

结果解读:

  • ^ 表示字符串开头
  • .. 表示任意两个字符
  • $ 表示字符串结尾

表中所有员工姓名都是两个字,因此全部返回。如需匹配特定长度的字符串,正则表达式非常直观。

场景七:匹配多个模式

当前数据状态:见上文 employees 表完整数据。

执行语句:

-- 查找部门为技术部或产品部的员工
SELECT emp_name, dept FROM employees
WHERE dept REGEXP '技术部|产品部';

操作后结果:

emp_namedept
大翔技术部
白歌技术部

结果解读:| 在正则中表示"或",因此 '技术部|产品部' 匹配包含任一模式的部门。这比 LIKE 更强大,因为 LIKE 一次只能写一个模式(除非用 OR 连接多个 LIKE 条件)。

场景八:匹配中文字符

当前数据状态:见上文 employees 表完整数据。

执行语句:

SELECT emp_name, dept FROM employees
WHERE emp_name REGEXP '[一-龥]';

操作后结果:

emp_namedept
大翔技术部
白歌技术部

结果解读:[一-龥] 匹配任意一个中文字符。所有员工姓名都包含中文字符,因此全部返回。这展示了正则表达式字符类的强大能力。

LIKE vs REGEXP 对比

特性LIKEREGEXP
语法复杂度简单(%, _)复杂(正则语法)
性能相对较好较慢
索引利用前缀匹配可用完全不能用索引
功能基础模糊匹配复杂模式匹配
大小写敏感取决于排序规则默认不敏感,可用 BINARY

常见误区

误区正解
LIKE '%xxx%' 可以用索引不能。含前导 % 的 LIKE 无法使用 B-Tree 索引。
LIKE 是大小写敏感的默认不敏感,取决于排序规则。如需敏感匹配用 LIKE BINARY。
REGEXP 比 LIKE 快恰恰相反,REGEXP 更慢且完全无法使用索引。
LIKE '白%' 和 = 一样快前缀 LIKE 可以用索引,但通常比 = 稍慢(范围扫描 vs 精确查找)。

面试考点

Q:LIKE '%abc' 为什么慢?如何优化?

前导 % 导致无法使用 B-Tree 索引,必须全表扫描。优化方案:1. 业务上改为前缀匹配;2. 使用全文索引(FULLTEXT);3. 使用倒排表或搜索引擎(Elasticsearch)。

Q:LIKE 和 REGEXP 的区别?

LIKE 使用 % 和 _ 通配符,语法简单,前缀匹配可利用索引;REGEXP 使用正则表达式,功能强大但性能差,完全无法利用索引。

Q:MySQL 5.7 有全文索引吗?

有。InnoDB 和 MyISAM 都支持 FULLTEXT 索引,用于高效的全文检索,可以替代 %keyword% 的慢查询。但中文全文检索需要额外配置 ngram 解析器(MySQL 5.7.6+)。

Q:如何让 LIKE 区分大小写?

使用 LIKE BINARY 或确保列的排序规则是 _bin(如 utf8mb4_bin)。

小结

  • LIKE 是日常模糊匹配的首选,% 匹配任意字符,_ 匹配单个字符
  • 只有前缀匹配('xxx%')可能利用索引,其他形式会全表扫描
  • REGEXP 功能更强但性能更差,大数据量慎用
  • 匹配通配符本身需要用 ESCAPE 指定转义字符
  • 全文检索需求应考虑 FULLTEXT 索引或外部搜索引擎

下一章引子:学会了筛选单行数据,接下来学习如何对多行数据进行汇总统计——聚合函数。

上一页
算术运算符
下一页
NULL 值处理