1、WHERE 子句1.1 WHERE 子句操作符1.2 检查单值1.3 检查不匹配值1.4 检查范围值1.5 检查空值1.6 组合 WHERE 子句1.7 IN 操作符1.8 NOT 操作符2、LIKE 子句2.1 `%`通配符2.2 `_`通配符3、正则表达式检索3.1 基本字符匹配3.2 进行OR匹配3.3 匹配几个字符之一3.4 匹配范围3.5 匹配特殊字符3.6 匹配字符类3.7 匹配多个实例3.8 定位符

数据库表中包含了很多数据,一般我们不会检索表中的所有行。通常会根据特定的条件来提取出表的子集,此时我们需要指定搜索条件(search criteria),搜索条件也叫作过滤条件(filter condition)。

在 SELECT 语句中,使用 WHERE 子句指定搜索条件,其语法为:

SELECT field1, field2,...fieldN FROM table_name1, table_name2...[WHERE condition1 [AND [OR]] condition2.....查询语句可以使用一个或者多个表,表之间使用逗号分隔;

可以在WHERE 子句中指定任何条件;

可以使用 AND 或者 OR 指定一个或多个条件;

WHERE 子句也可以用于 DELETE 或 UPDATE 命令;

假如我们想要查看 李四 的所有科目的成绩,那么我们就以 name = '李四'  作为筛选条件:

mysql> SELECT name, math_score, chinese_score, english_score    -> FROM score    -> WHERE name = '李四';+------+------------+---------------+---------------+| name | math_score | chinese_score | english_score |+------+------------+---------------+---------------+| 李四 |         74 |            85 |            97 |+------+------------+---------------+---------------+1 row in set (0.00 sec)查看数学成绩高于(包含)90分的同学名单,以 math_score >= 90 作为筛选条件:

mysql> SELECT name, math_score    -> FROM score    -> WHERE math_score >= 90;+------+------------+| name | math_score |+------+------------+| 吴七 |         94 || 陈十 |         96 |+------+------------+2 rows in set (0.00 sec)1.3 检查不匹配值假如我们已经知道李四的成绩了,我们想要查看其它同学的所有成绩,那么以 name <> '李四' 或者 name != '李四' 作为筛选条件:

WHERE column_name IS NULL;1.6 组合 WHERE 子句在进行数据检索时,允许使用多个 WHERE 子句,使用 AND 或 OR 连接。

AND 操作符表示检索同时满足多个条件的数据,比如想要检索语文成绩低于85,英语成绩高于90的同学:

mysql> SELECT name, math_score, chinese_score, english_score    -> FROM score    -> WHERE chinese_score < 85 AND english_score > 90;+------+------------+---------------+---------------+| name | math_score | chinese_score | english_score |+------+------------+---------------+---------------+| 王五 |         79 |            71 |            91 |+------+------------+---------------+---------------+OR 操作符表示检索满足任一条件的数据,比如想要检索数学成绩高于90 或者语文成绩高于90分的同学:

mysql> SELECT name, math_score, chinese_score, english_score    -> FROM score    -> WHERE math_score > 90 OR chinese_score > 90;+------+------------+---------------+---------------+| name | math_score | chinese_score | english_score |+------+------------+---------------+---------------+| 孙三 |         89 |            94 |            90 || 吴七 |         94 |            90 |            93 || 郑八 |         87 |            98 |            97 || 陈十 |         96 |            97 |            96 |+------+------------+---------------+---------------+4 rows in set (0.00 sec)WHERE 可以包含任意数目的 AND 和 OR 操作符,可以组合出更高级的过滤。那么就会出现一个问题:条件的顺序如何?AND操作符 的 优先级要高于 OR 操作符,如果想要指定筛选顺序,可以使用小括号进行分组。例如,要检索数学成绩高于90,语文成绩低于80或高于90的同学,可以使用下列检索语句:

mysql> SELECT name, math_score, chinese_score, english_score    -> FROM score    -> WHERE math_score > 90 AND (chinese_score > 90 OR chinese_score < 80);+------+------------+---------------+---------------+| name | math_score | chinese_score | english_score |+------+------------+---------------+---------------+| 陈十 |         96 |            97 |            96 |+------+------------+---------------+---------------+1 row in set (0.00 sec)1.7 IN 操作符IN 操作符可以指定列的值是否匹配列表中的值或子查询中的任何值。其语法为:

SELECT column1, column2,... FROM table_nameWHERE (expr|column_1) IN ('value1', 'value2', ...)列表中的值使用逗号分隔

假如想检索数学成绩为 79、80和94的同学:

mysql> SELECT name, math_score, chinese_score, english_score    -> FROM score    -> WHERE math_score IN (79, 80, 94);+------+------------+---------------+---------------+| name | math_score | chinese_score | english_score |+------+------------+---------------+---------------+| 钱二 |         80 |            87 |            92 || 王五 |         79 |            71 |            91 || 吴七 |         94 |            90 |            93 |+------+------------+---------------+---------------+3 rows in set (0.01 sec)IN 操作符的优点:

在使用长的合法选项清单时,IN 操作符的语法更清楚且更直观;

在使用 IN 时,计算的次序更容易管理(因为使用的操作符更少);

IN 操作符一般比 OR  操作符清单执行更快;

IN 操作符的最大优点是可以包含其他 SELECT 语句,使得能够更动态地建立 WHERE 子句,后面会对此进行详细介绍。

NOT 操作符的功能是否定它之后所跟的任何条件。

假如想检索数学成绩不为 79、80和94的同学:

通配符(wildcard)是用来匹配值的一部分的特殊字符。

SQL LIKE 子句中使用 % 字符来表示任意字符,如果没有使用 % 那么 LIKE 子句与 等号的效果一样。LIKE 子句语法为:

SELECT column1, column2,... FROM table_nameWHERE column1 LIKE condition1 [AND [OR]] column2 = 'somevalue'可以使用 AND 或 OR 指定一个或多个条件

下面演示如何检索姓冯的同学成绩:

mysql> SELECT name, math_score, chinese_score, english_score    -> FROM score    -> WHERE name LIKE '冯%';+------+------------+---------------+---------------+| name | math_score | chinese_score | english_score |+------+------------+---------------+---------------+| 冯九 |         69 |            82 |            83 |+------+------------+---------------+---------------+1 row in set (0.00 sec)2.2 `_`通配符下划线通配符,只匹配单个字符,不能匹配多个字符。

mysql> SELECT name, math_score, chinese_score, english_score    -> FROM score    -> WHERE name LIKE '冯_';+------+------------+---------------+---------------+| name | math_score | chinese_score | english_score |+------+------------+---------------+---------------+| 冯九 |         69 |            82 |            83 |+------+------------+---------------+---------------+1 row in set (0.00 sec)虽然通配符很有用,但这种功能是有代价的:通配符搜索的处理一般比其他搜索所花时间更长。注意以下几点:

不要过度使用通配符;

确实需要通配符时,除非绝对必要,否则不要把它们用在搜索模式的开始处。把通配符置于搜索模式的开始处,搜索起来最慢。

前面介绍了 LIKE 通配符进行模糊匹配,如果对于基本的过滤,这就够了。但是遇到复杂的过滤条件,通配符就显得有些力不从心了,正则表达式该登场了,正则表达式是用来匹配文本 的特殊的串(字符集合) 。如果想要从文本里提取电话号码、QQ号码或者URL时,正则表达式再适合不过了。MySQL 中使用 REGEXP 操作符来进行正则匹配。

注意:MySQL 仅支持多数正则表达式实现的一个很小的子集。下表中的正则模式可以用于 REGEXP 操作符中:

本节内容我们采用 MySQL 8 自带的数据库(world)中的数据表(city)。

. 是正则表达式语言中的一个特殊字符,它表示匹配任意一个字符,下面筛选出名称中包含 alle 的城市:

mysql> use world;Database changedmysql> SELECT name, Population FROM city    -> WHERE name REGEXP '.alle';+--------------------------------+------------+| name                           | Population |+--------------------------------+------------+| The Valley                     |        595 || San Fernando del Valle de Cata |      |...| McAllen                        |     106414 |+--------------------------------+------------+19 rows in set (0.01 sec)3.2 进行OR匹配如果搜索条件为两个,使用 | 进行条件的连接,下面语句筛选名称中包含alle 或 ille 的城市:

mysql> SELECT name, Population FROM city    -> WHERE name REGEXP 'alle|ille';+--------------------------------+------------+| name                           | Population |+--------------------------------+------------+| Willemstad                     |       2345 || The Valley                     |        595 || San Fernando del Valle de Cata |      || Townsville                     |     109914 |...| Gainesville                    |      92291 |+--------------------------------+------------+42 rows in set (0.01 sec)3.3 匹配几个字符之一如果想匹配几个特定的字符,可通过指定一组用[ 和 ] 括起来的字符完成,下面语句同样筛选名称中包含 alle 或 ille 的城市:

mysql> SELECT name, Population FROM city    -> WHERE name REGEXP '[ai]lle';+--------------------------------+------------+| name                           | Population |+--------------------------------+------------+| Willemstad                     |       2345 || The Valley                     |        595 || San Fernando del Valle de Cata |      || Townsville                     |     109914 |...| Gainesville                    |      92291 |+--------------------------------+------------+42 rows in set (0.01 sec)3.4 匹配范围集合可用来定义要匹配的一个或多个字符,假如我们想要匹配数字0到9可以写成 [0123456789] ,还有一种简单的写法 [0-9]  ,范围不一定是数值,也可以是字母: [a-z] 匹配任意字母字符。

下面语句筛选名称中包含 alle  、blle 、clle 、… 、ille 的城市:

mysql> SELECT name, Population FROM city    -> WHERE name REGEXP '[a-i]lle';+--------------------------------+------------+| name                           | Population |+--------------------------------+------------+| Willemstad                     |       2345 || The Valley                     |        595 || San Fernando del Valle de Cata |      |...| Gainesville                    |      92291 |+--------------------------------+------------+44 rows in set (0.01 sec)3.5 匹配特殊字符在各种编程语言中都有 转义字符 的概念,MySQL 的正则表达式中也由一些特殊字符比如:.、-、[ 和 ] 等,如果要匹配此类字符,必须用 \\ 作为前导, \\- 表示查找 -,\\[ 表示查找 [。

\\ 也用来引用元字符,如表所示:

MySQL 预定义了字符集用来匹配数字或字母字符等,称为 字符类 (character class)。

前面使用的正则表达式都只匹配单次出现。有时候我们需要对匹配的数量进行控制,此时需要* 、+、?、{n}、{n,}或{n,m}。下面语句筛选名称中包含连续的5个a-e的城市,[a-e]{5}也可以写为[a-e][a-e][a-e][a-e][a-e]:

mysql> SELECT name, Population FROM city    -> WHERE name REGEXP '[a-e]{5}';+-------------------+------------+| name              | Population |+-------------------+------------+| Bacabal           |      93121 || Sabadell          |      || Addis Abeba       |    2495000 || Ahmedabad         |    2876710 || Faridabad         |     703592 || Moradabad         |     429214 || Abadan            |     206073 || Jacobabad         |     137700 || M??nchengladbach  |     263697 || Bergisch Gladbach |     106150 |+-------------------+------------+10 rows in set (0.00 sec)3.8 定位符为了匹配特定位置的文本,需要使用如下定位符:

如下语句匹配名称以z开头的城市:

mysql> SELECT name, Population FROM city    -> WHERE name REGEXP '^[z]';+-----------------+------------+| name            | Population |+-----------------+------------+| Zaanstad        |      || Zoetermeer      |     110214 || Zwolle          |     105819 || Zenica          |      96027 |...| Zeleznogorsk    |      94000 |+-----------------+------------+59 rows in set (0.00 sec)

另外,有一份有趣的 Python 游戏开发 专栏等您来开启,点击“阅读原文”查看详情!

系列文章回顾