介绍
在某些结构化查询语言(SQL)语句中,WHERE
子句可用于限制给定操作将影响的行。他们通过定义每行必须满足才能受到影响的特定条件(称为搜索条件)来实现这一点。搜索条件由一个或多个谓词组成,这些谓词是计算结果为“真”、“假”或“未知”的特殊表达式,并且操作仅影响WHERE
子句中每个谓词计算结果为“真”的那些行。 ”
SQL 允许用户编写包含各种不同类型谓词的搜索条件,每个谓词都使用特定的运算符来评估行。本指南将概述两种类型的谓词及其使用的运算符:比较运算符和IS NULL
运算符。
尽管本指南将专门在其示例中使用SELECT
语句,但此处解释的概念可用于许多 SQL 操作。特别是,WHERE
条款和他们的搜索条件的重要组成部分UPDATE
和DELETE
操作。
先决条件
为了遵循本指南,您需要一台运行某种类型的使用 SQL 的关系数据库管理系统 (RDBMS) 的计算机。本指南中的说明和示例已使用以下环境进行验证:
- 运行 Ubuntu 20.04 的服务器,具有管理权限的非 root 用户和使用 UFW 配置的防火墙,如我们的 Ubuntu 20.04 初始服务器设置指南中所述。
- 在服务器上安装并保护 MySQL,如如何在 Ubuntu 20.04 上安装 MySQL 中所述。本指南已使用新创建的用户进行验证,如步骤 3 中所述。
- 您还需要一个数据库,其中包含一些加载了示例数据的表,您可以使用这些表来练习使用比较和
IS NULL
运算符。我们鼓励您阅读以下连接到 MySQL 和设置示例数据库部分,详细了解如何连接到 MySQL 服务器并创建本指南示例中使用的测试数据库。
注意:请注意,许多 RDBMS 使用自己独特的 SQL 实现。尽管本教程中概述的命令适用于大多数 RDBMS,包括 PostgreSQL 和 SQLite,但如果您在 MySQL 以外的系统上测试它们,则确切的语法或输出可能会有所不同。
连接到 MySQL 并设置示例数据库
如果您的 SQL 数据库系统在远程服务器上运行,请从本地计算机通过 SSH 连接到您的服务器:
- ssh sammy@your_server_ip
然后打开数据库服务器提示。如果您使用的是 MySQL,请运行以下命令,确保替换sammy
为您的 MySQL 用户帐户的名称:
- mysql -u sammy -p
根据提示,创建一个名为 的数据库comparison_null_db
:
- CREATE DATABASE comparison_null_db;
如果数据库创建成功,您将收到如下输出:
OutputQuery OK, 1 row affected (0.01 sec)
要选择comparison_null_db
数据库,请运行以下USE
语句:
- USE comparison_null_db;
OutputDatabase changed
选择后comparison_null_db
,在其中创建一个表。
为了跟随本指南中使用的示例,假设您和您的一群朋友都决定更加活跃,并将跑步作为锻炼。为此,您的朋友都为下个月想跑多少英里设定了个人目标。您决定在包含以下三列的 SQL 表中跟踪朋友的里程目标以及他们实际跑的里程数:
name
: 每个朋友的名字,使用varchar
最多15个字符的数据类型表示goal
:每个朋友过去一个月希望跑多少英里的目标,使用int
数据类型表示为整数result
:每个朋友在一个月内最终跑的里程数,再次表示为int
运行以下CREATE TABLE
语句以创建一个名为的表running_goals
,该表包含这三列:
- CREATE TABLE running_goals (
- name varchar(15),
- goal int,
- result int
- );
OutputQuery OK, 0 rows affected (0.012 sec)
然后running_goals
用一些示例数据加载表。运行以下INSERT INTO
操作以添加代表您的七个朋友、他们的跑步目标和结果的七行数据:
- INSERT INTO running_goals
- VALUES
- ('Michelle', 55, 48),
- ('Jerry', 25, NULL),
- ('Milton', 45, 52),
- ('Bridget', 40, NULL),
- ('Wanda', 30, 38),
- ('Stewart', 35, NULL),
- ('Leslie', 40, 44);
OutputQuery OK, 7 rows affected (0.004 sec)
Records: 7 Duplicates: 0 Warnings: 0
请注意,其中三个行的result
值为NULL
。出于本示例的目的,假设这些朋友只是没有报告他们过去一个月跑的英里数,因此他们的result
值输入为NULL
。
有了这个,您就可以按照指南的其余部分并开始学习如何IS NULL
在 SQL 中使用比较和运算符。
理解WHERE
从句谓词
在任何从现有表读取数据的 SQL 操作中,您都可以在FROM
子句后跟一个WHERE
子句来限制该操作将影响哪些数据。WHERE
子句通过定义搜索条件来做到这一点;不满足搜索条件的任何行都被排除在操作之外,但包括任何满足搜索条件的行。
搜索条件由一个或多个谓词或表达式组成,这些表达式可以计算一个或多个值表达式并返回“真”、“假”或“未知”的结果。在 SQL 中,值表达式(有时也称为标量表达式)是任何将返回单个值的表达式。值表达式可以是文字值,如字符串或数值、数学表达式或列名。请注意,通常情况下,WHERE
子句谓词中的至少一个值表达式是操作FROM
子句中引用的表中列的名称。
当运行包含WHERE
子句的SQL 查询时,DBMS 会将搜索条件应用于FROM
子句定义的逻辑表中的每一行。然后它将只返回搜索条件中的每个谓词评估为“真”的行。
SQL 标准定义了 18 种类型的谓词,尽管并非每个 RDBMS 在其 SQL 实现中都包含它们中的每一种。以下是五种最常用的谓词类型,以及对每种类型及其使用的运算符的简要说明:
比较:比较谓词将一个值表达式与另一个值表达式进行比较;在查询中,几乎总是这些值表达式中的至少一个是列的名称。六个比较运算符是:
=
: 测试两个值是否相等<>
: 测试两个值是否不等价<
: 测试第一个值是否小于第二个>
: 测试第一个值是否大于第二个<=
: 测试第一个值是否小于或等于第二个>=
: 测试第一个值是否大于或等于第二个
Null:使用IS NULL
运算符的谓词测试给定列中的值是否为 Null
Range:范围谓词使用BETWEEN
运算符来测试一个值表达式是否介于其他两个表达式之间
Membership:此类谓词使用IN
运算符来测试值是否为成员给定集合的
模式匹配:模式匹配谓词使用LIKE
运算符来测试值是否与字符串模式匹配
正如介绍中提到的,本指南重点介绍如何使用 SQL 的比较和IS NULL
运算符来过滤数据。如果您想学习如何分别将BETWEEN
orIN
运算符与范围和成员资格谓词一起使用,我们鼓励您查看有关如何在 SQL 中使用 BETWEEN 和 IN 运算符的指南。或者,如果您想了解如何使用LIKE
运算符根据包含通配符的字符串模式过滤数据,请按照我们的如何在 SQL 中使用通配符指南进行操作。最后,如果您想了解更多关于WHERE
子句的一般知识,您可能对我们关于如何在 SQL 中使用 WHERE 子句的教程感兴趣。
比较谓词
WHERE
子句比较谓词使用六个比较运算符之一来比较一个值表达式与另一个。它们通常遵循这样的语法:
- SELECT column_list
- FROM table_name
- WHERE column_name OPERATOR value_expression;
继WHERE
关键字是一个值表达式,在大多数SQL操作,是列名。在搜索条件中提供列名作为值表达式告诉 RDBMS 使用该列中每一行的值作为该行的搜索条件迭代的值表达式。由于数据库系统按顺序将搜索条件应用于每一行,因此比较运算符将根据搜索条件对于指定列中的值是否为真来包括或过滤掉一行。
为了说明这一点,请运行以下查询,该查询将从running_goals
表name
和goal
列中返回值。请注意该WHERE
子句如何使用比较谓词,该谓词将导致查询仅返回其goal
值等于 的行40
:
- SELECT name, goal
- FROM running_goals
- WHERE goal = 40;
在过去的一个月里,只有两个朋友的目标是正好跑 40 英里,所以查询只返回这两行:
Output+---------+------+
| name | goal |
+---------+------+
| Bridget | 40 |
| Leslie | 40 |
+---------+------+
2 rows in set (0.00 sec)
为了说明其他比较运算符的工作原理,请运行以下查询,这些查询与前面的示例相同,但每个查询使用不同的比较运算符。
该<>
运算符测试两个值是否不相等,因此此查询返回其goal
值不等于的每一行40
:
- SELECT name, goal
- FROM running_goals
- WHERE goal <> 40;
Output+----------+------+
| name | goal |
+----------+------+
| Michelle | 55 |
| Jerry | 25 |
| Milton | 45 |
| Wanda | 30 |
| Stewart | 35 |
+----------+------+
5 rows in set (0.00 sec)
的<
操作者的测试的第一个值表达式是否小于第二:
- SELECT name, goal
- FROM running_goals
- WHERE goal < 40;
Output+---------+------+
| name | goal |
+---------+------+
| Jerry | 25 |
| Wanda | 30 |
| Stewart | 35 |
+---------+------+
3 rows in set (0.00 sec)
的>
操作者的测试的第一个值表达式是否大于第二个:
- SELECT name, goal
- FROM running_goals
- WHERE goal > 40;
Output+----------+------+
| name | goal |
+----------+------+
| Michelle | 55 |
| Milton | 45 |
+----------+------+
2 rows in set (0.00 sec)
的<=
操作者的测试的第一个值是否小于或等于第二:
- SELECT name, goal
- FROM running_goals
- WHERE goal <= 40;
Output+---------+------+
| name | goal |
+---------+------+
| Jerry | 25 |
| Bridget | 40 |
| Wanda | 30 |
| Stewart | 35 |
| Leslie | 40 |
+---------+------+
5 rows in set (0.00 sec)
的>=
操作者的测试的第一个值是否大于或等于第二:
- SELECT name, goal
- FROM running_goals
- WHERE goal >= 40;
Output+----------+------+
| name | goal |
+----------+------+
| Michelle | 55 |
| Milton | 45 |
| Bridget | 40 |
| Leslie | 40 |
+----------+------+
4 rows in set (0.00 sec)
等价 ( =
) 和不等价 ( <>
) 运算符与人们预期的一样处理字符串值。以下查询返回name
等于 的每一行的值'Leslie'
:
- SELECT name
- FROM running_goals
- WHERE name = 'Leslie';
因为表中只有一个朋友名为“Leslie”,所以查询只返回该行:
Output+--------+
| name |
+--------+
| Leslie |
+--------+
1 row in set (0.00 sec)
比较字符串值时<
,>
、<=
、 和>=
运算符都会评估字符串按字母顺序的关系。换句话说,如果您编写一个谓词来测试一个字符串是否“小于”另一个字符串,那么您就是在测试第一个字符串是否按字母顺序排在第二个字符串之前。同样,如果您的谓词测试一个字符串是否“大于”另一个字符串,那么您就是在测试第一个字符串是否按字母顺序排在第二个字符串之后。
为了进行说明,请运行以下查询。这将返回值“小于”字母的每一行的name
和goal
值。换句话说,对于值按字母顺序排在前面的每一行,搜索条件将评估为“真” :name
'M'
name
M
- SELECT name
- FROM running_goals
- WHERE name < 'M';
Output+---------+
| name |
+---------+
| Jerry |
| Bridget |
| Leslie |
+---------+
3 rows in set (0.00 sec)
请注意,此结果集不包含Michelle
或Milton
。这是因为,按字母顺序,单个字母“M”出现在任何以字母“M”开头且有多个字母的字符串之前,因此这两个朋友被排除在此结果集中。
空谓词
在 SQL 中,NULL
是用于表示缺失值或未知值的保留关键字。Null是一种状态,而不是实际值;它不代表零或空字符串。
您可以使用IS NULL
运算符来测试给定的值表达式是否为 Null:
- . . .
- WHERE column_name IS NULL
- . . .
使用这种类型的谓词,数据库系统将查看指定列中每一行的值并评估每一行是否为 Null。如果列中的值确实为 Null,则对于这些行,搜索条件将评估为“真”,并且它们将包含在结果集中。
为了说明这一点,请运行以下查询,该查询返回name
和result
列:
- SELECT name, result
- FROM running_goals
- WHERE result IS NULL;
此查询WHERE
子句中的搜索条件测试每一行的result
值是否为 Null。如果是,则谓词评估为“true”并且该行包含在结果集中:
Output+---------+--------+
| name | result |
+---------+--------+
| Jerry | NULL |
| Bridget | NULL |
| Stewart | NULL |
+---------+--------+
3 rows in set (0.00 sec)
因为您的三个朋友尚未报告他们在过去一个月中最终跑的英里数,所以这些值是NULL
在您加载数据表时记录的。因此,对于这三行,查询中的搜索条件评估为“真”,因此它们是结果集中唯一包含的。
结论
通过遵循本指南,您学习了如何IS NULL
在WHERE
子句中使用 SQL 的比较和运算符来限制操作将影响的行。虽然此处显示的命令应该适用于大多数关系数据库,但请注意,每个 SQL 数据库都使用自己独特的 SQL 标准实现。您应该查阅 DBMS 的官方文档,以获得对每个命令及其全套选项的更完整描述。
如果您想了解有关使用 SQL 的更多信息,我们鼓励您查看本系列中关于如何使用 SQL的其他教程。