[TOC]
本文主要介绍MySQL基本的过滤和搜索服务, 包括where子句的过滤操作,in, not in的操作符。更精确地,可以采用like,或者regexp写正则表达式进行匹配。
第六章 过滤数据
想象一下,我们现在有一个学生信息的表,学校要求开展关于少数民族的活动,我们想知道班级里有多少人是少数民族,于是我们需要抽取出民族非汉的所有学生,此时我们利用之前学习的检索是做不到的,这也就是我们接下来要介绍的过滤和搜索服务。
WHERE子句是执行过滤操作的关键字。
| 口令 | 用途 | 备注 |
|---|---|---|
| SELECT prod_name,prod_price FROM products WHERE prod_price = 2.5; | 过滤出prod_price为2.5的列 | 相等的过滤 |
| =;<>(不等) ; !=(不等) ; < ; > ; <= ; >= ; BETWEEN a AND b | 不同的where子句的操作符 | BETWEEN的格式注意一下 |
| SELECT prod_name,prod_price FROM products WHERE prod_name = “fuses”; | 字符串相等 | 不区分大小写,也会匹配Fuses |
| SELECT prod_name,prod_price FROM products WHERE prod_price BETWEEN 5 AND 10; | prod_price在5-10之间 | 包括两个端点处的值 |
| SELECT prod_name FROM products WHERE prod_price IS NULL; | 空值检查 | 注意0,空字符串,空格等都不属于空值 |
空值的场景,假设是在搜集估计的信息,可能有些顾客不愿意或者没有提供电子邮件或者电话号码,则会出现空值,我们通常会在创建数据库时指定某列是否允许空值。
注意:用其他的过滤条件不会找出具有NULL值的行,因为NULL与其他条件不匹配。
第七章 数据过滤
WHERE子句允许逻辑操作符,不同的WHERE子句用AND或OR进行连接。
| 口令 | 用途 | 备注 |
|---|---|---|
| SELECT prod_id,prod_name,prod_price FROM products WHERE vend_id=1003 AND prod_price <= 10; | AND逻辑操作符,与 | 集合中的交集操作 |
| SELECT prod_name,prod_price FROM products WHERE vend_id =1002 OR vend_id =1003; | OR逻辑操作符,或 | 集合中的并集操作 |
| SELECT prod_name,prod_price FROM products WHERE vend_id IN (1002,1003) ORDER BY prod_name; | IN指定条件范围,括号内所有值可以进行匹配,以逗号分隔 | 和OR起到的作用一致 |
| SELECT prod_name,prod_price FROM products WHERE vend_id NOT IN (1002,1003) ORDER BY prod_name; | NOT用来否定条件 |
注意:
- 多使用圆括号操作符改变顺序,不然默认的计算次序AND > OR,有时会不经意间产生错误。所以我们建议多多使用圆括号;
- IN比OR更清楚直观,执行速度更快;
- NOT可以用来否定IN, BETWEEN, EXISTS等,注意这只在MySQL。
第八章 用通配符进行过滤
本章介绍如何使用通配符进行复杂过滤。
8.1 什么是通配符
当我们想要获取学生中姓高的学生信息的时候,用之前的检索和过滤操作符就不适用了,因为之前的操作符都是等价匹配,而不会有学生的姓名刚好只有高一个字,而会像高一,高二等,所以我们这章就是利用高来匹配高一高二,这就是通配符或者正则表达式。
通配符(wildcard)是用来匹配值的一部分的特殊字符。
搜索模式(search pattern)由字面值,通配符或者两者组合构成的搜索条件。
8.2 通配符种类
通配符本身就是WHERE子句中具有特殊含义的字符,为了使用通配符,需要使用LIKE操作符。
这里还有一个谓词的概念,当某个操作符的返回值是TRUE,FALSE,UNKNOWN等时,操作符为谓词。
| 口令 | 用途 | 备注 |
|---|---|---|
| SELECT prod_id,prod_name FROM products WHERE prod_name LIKE ‘jet%’; | %用于任何字符出现任意次数,找出所有以jet开头的prod_name | 当然也可以0次 |
| SELECT prod_id,prod_name FROM products WHERE prod_name LIKE ‘%anvil%’; | 可以使用多个通配符,anvil在中间的prod_name | 因为可以是0次,所以开头或结尾都行 |
| SELECT prod_id,prod_name FROM products WHERE prod_name LIKE ‘s%e’; | 以s开头,e结尾的字符 | |
| SELECT prodid,prod_name FROM products WHERE prod_name LIKE ‘ ton anvil’; | 下划线匹配一个字符 |
注意:%不能匹配NULL值;
8.3 使用通配符的技巧
当我们使用通配符时,需要了解:
- 通配符搜索花掉的时间更多;
- 先使用其他操作符,再使用通配符效率会更高;
- 统配符的位置不要放错。
第九章 用正则表达式进行搜索
正则表达式是用来匹配文本的特殊的集合,比如从文本文件中提取电话号码,邮箱等。MySQL仅支持多数正则表达式的一个很小的子集。
| 口令 | 用途 | 备注 | ||
|---|---|---|---|---|
| SELECT prod_name FROM products WHERE prod_name REGEXP “1000” ORDER BY prod_name; | 检索prod_name包含文本1000的所有行 | 他是在列值内进行匹配,如果能找到1000,则匹配成功,相当于操作对象为某列某行的字符串;而LIKE则是匹配整个列,而不是看列值是否包含。 | ||
| SELECT prod_name FROM products WHERE prod_name REGEXP “.000” ORDER BY prod_name; | .表示匹配任意一个字符 | 如果想要区分大小写,可以在REGEXP后加入BINARY | ||
| SELECT prod_name FROM products WHERE prod_name REGEXP “1000\ | 2000” ORDER BY prod_name; | \ | 表示或者的关系 | 匹配1000或者2000 |
| SELECT prod_name FROM products WHERE prod_name REGEXP “[123] ton”ORDER BY prod_name; | [123]表示匹配方括号内任一个字符 | []和\ | 作用类似 | |
| SELECT prod_name FROM products WHERE prod_name REGEXP “[\^123] ton”ORDER BY prod_name; | ^表示不匹配123之一,起否定作用 | 文本中有反斜杠,其实不对,应该扔掉,是因为在Markdown中,如果不加反斜杠的话,^会被解释为脚注,只是格式问题 | ||
| SELECT prod_name FROM products WHERE prod_name REGEXP “[1-5] ton”ORDER BY prod_name; | [1-5]匹配1,2,3,4,5任一字符 | [a-z] | ||
| SELECT prod_name FROM products WHERE prod_name REGEXP “\\.“ORDER BY prod_name; | 匹配特殊字符. | 用两个转义字符\\匹配特殊字符 |
- 假如相匹配 1 ton, 2 ton 或者 3 ton,则需要用”[123] ton”,或者”[1|2|3] ton”,就是不能使用 1|2|3 ton,他会默认是1或者2或者3 ton,从而检索出错。
- \\f匹配换页,\\n匹配换行,\\r匹配回车,\\t匹配制表,\\v匹配纵向制表
9.1 MySQL的字符类
MySQL具有很多预定义的字符集,称为字符类:

9.2 匹配多个实例
当你想要匹配一个电话号码的时候,需要匹配11个数字,但如果写出[0-9]重复11次,则显得非常冗余,有没有什么方式可以指定匹配11个数字呢,我们有如下的特殊字符。
| 元字符 | 说明 |
|---|---|
| * | 匹配任意长度字符,可以为0 |
| + | 至少一个字符 |
| ? | 0个或1个 |
| {n} | n个 |
| {n,} | 至少n个 |
| {n,m} | n-m个,m不超过255 |
| ^ | 文本的开始(在[]内部作否定使用) |
| $ | 文本的结尾 |
| [[:<:]] | 词的开始(没有试验成功,不知使用方法) |
| [[:>:]] | 词的结尾 |
下面我们给出一些示例。
| 口令 | 用途 | 备注 |
|---|---|---|
| SELECT prod_name FROM products WHERE prod_name REGEXP ‘\\([0-9] sticks?\\)‘ ORDER BY prod_name; | \\(\\)使得匹配圆括号;sticks?使得s可有可无 | |
| SELECT prod_name FROM products WHERE prod_name REGEXP ‘[[:digit:]]{4}’ ORDER BY prod_name; | [:digit:]代表任意数字,{4}代表4次 | [:digit:]可以想象成0-9 |
| SELECT prod_name FROM products WHERE prod_name REGEXP ‘^[0-9\\.]’ ORDER BY prod_name; | 以数字或者.开头的匹配 | |
| SELECT “hello” REGEXP ‘[0-9]’; | 返回0 | 在不调用数据库情况下测试正则表达式 |