第4章 过滤数据
4.1 WHERE 子句
根据需要提取表数据的子集,需要指定搜索条件(search criteria)。
- 在 SELECT 语句中,数据根据 WHERE 子句中指定的搜索条件进行过滤。
- WHERE 子句在表名(FROM 子句)之后给出。
SELECT prod_name, prod_price FROM Products
WHERE prod_price = 3.49;
分析
这条语句从 products 表中检索两个列,但不返回所有行,只返回 prod_price 值为 3.49 的行,输出:
注意
同时使用 ORDER BY 和 WHERE 子句时,ORDER BY 应位于 WHERE 之后,否则将出错。
4.2 WHERE 子句操作符
操作符 | 说明 | 操作符 | 说明 |
---|---|---|---|
= | 等于 | > | 大于 |
<> | 不等于 | >= | 大于等于 |
!= | 不等于 | !> | 不大于 |
< | 小于 | BETWEEN | 在指定的两个值之间 |
<= | 小于等于 | IS NULL | 为NULL值 |
!< | 不小于 |
检查单个值
列出所有价格小于等于 10 美元的产品。
SELECT prod_name, prod_price FROM Products
WHERE prod_price <= 10;
不匹配检查
列出所有不是供应商 DLL01 制造的产品:
SELECT vend_id, prod_name FROM Products
WHERE vend_id <> 'DLL01';
注意:何时使用引号
上述 WHERE 子句中的条件,有的值括在单引号内,而有的值未括起来。
- 单引号用来限定字符串。
- 将值与字符串类型的列进行比较,就要限定引号。
- 将值与数值列进行比较,不用引号。
范围值检索
要检查某个范围的值,使用 BETWEEN 操作符。其语法与其他 WHERE 子句的操作符稍有不同,因为它需要两个值,即范围的开始值和结束值。
例如,BETWEEN 操作符可用来检索价格在 5 美元和 10 美元之间的所有产品,或在指定的开始日期和结束日期之间的所有日期。
SELECT prod_name, prod_price FROM Products
WHERE prod_price BETWEEN 5 AND 10;
空值检查
在创建表时,表设计人员可以指定其中的列能否不包含值。在一个列不包含值时,称其包含空值 NULL。确定值是否为 NULL,用 IS NULL 子句。
SELECT prod_name FROM Products
WHERE prod_price IS NULL;
这条语句返回所有没有价格(空 prod_price 字段,不是价格为 0)的产品。
但是,Customers 表包含具有 NULL 值的列:如果没有电子邮件地址,则 cust_email 列将包含 NULL 值:
SELECT cust_name FROM Customers
WHERE cust_email IS NULL;
第5章 高级数据过滤
5.1 组合 WHERE 子句
SQL 允许给出多个 WHERE 子句,这些子句有两种使用方式,即以 AND 子句或 OR 子句的方式使用。
AND 操作符
SELECT prod_id, prod_price, prod_name FROM Products
WHERE vend_id = 'DLL01' AND prod_price <= 4;
此 SQL 语句检索由供应商 DLL01 制造且价格小于等于 4 美元的所有产品的名称和价格。
OR 操作符
许多 DBMS 在 OR WHERE 子句的第一个条件得到满足的情况下,就不再计算第二个条件了(在第一个条件满足时,不管第二个条件是否满足,相应的行都将被检索出来)。
SELECT prod_name, prod_price FROM Products
WHERE vend_id = 'DLL01' OR vend_id = 'BRS01';
求值顺序
需要列出价格为10美元及以上,且由 DLL01 或 BRS01 制造的所有产品。
SELECT prod_name, prod_price FROM Products
WHERE vend_id = 'DLL01' OR vend_id = 'BRS01'
AND prod_price >= 10;
上面结果返回的行中有 4 行价格小于 10 美元,原因在于求值的顺序。
- SQL 在处理 OR 操作符前,优先处理 AND 操作符。
- SQL 理解 WHERE 子句为:由供应商 BRS01 制造的价格为 10 美元以上的所有产品,以及由供应商 DLL01 制造的所有产品,而不管其价格如何。
- 由于 AND 在求值过程中优先级更高,操作符被错误地组合。
此问题的解决方法是使用圆括号对操作符进行明确分组:
SELECT prod_name, prod_price FROM Products
WHERE (vend_id = 'DLL01' OR vend_id= 'BRS01')
AND prod_price >= 10;
将前两个条件用圆括号括起来,因为圆括号具有比 AND 或 OR 操作符更高的求值顺序,所以 DBMS 首先过滤圆括号内的 OR 条件。
注意
任何时候使用具有 AND 和 OR 操作符的 WHERE 子句,都要使用圆括号分组操作符。
5.2 IN 操作符
IN 操作符用来指定条件范围,一组由逗号分隔括在圆括号中的合法值,范围中的每个条件都可以进行匹配,与 OR 功能相同。
SELECT prod_name, prod_price FROM Products
WHERE vend_id IN ('DLL01', 'BRS01')
ORDER BY prod_name;
IN 操作符的优点
- IN 操作符的语法更清楚直观。
- 在与其他 AND 和 OR 操作符组合使用 IN 时,求值顺序更容易管理。
- IN 操作符一般比一组 OR 操作符执行得更快。
- IN 可以包含其他 SELECT 语句, 能够更动态地建立 WHERE 子句。
5.3 NOT 操作符
WHERE 子句中的 NOT 操作符只有一个功能,否定其后所跟的任何条件。列出除 DLL01 之外的所有供应商制造的产品:
SELECT prod_name FROM Products
WHERE NOT vend_id= 'DLL01' ORDER BY prod_name;
第6章 用通配符进行过滤
6.1 LIKE 操作符
通配符(wildcard)用来匹配值的一部分的特殊字符。
搜索模式(search pattern)由字面值、通配符或两者组合构成的搜索条件。
通配符实际上是 SQL 的 WHERE 子句中有特殊含义的字符。为在搜索子句中使用通配符,必须使用 LIKE 操作符。LIKE 指示 DBMS,后跟的搜索模式利用通配符匹配而不是简单的相等匹配进行比较。
百分号(%)通配符
在搜索串中,%表示任何字符出现任意次数。要找出所有以词 Fish 开头的产品:
SELECT prod_id, prod_name FROM Products
WHERE prod_name LIKE 'Fish%'
在执行这条子句时,将检索任意以 Fish 起头的词。%告诉 DBMS 接受 Fish 之后的任意字符,不管它有多少字符。
通配符可在搜索模式中的任意位置使用,并且可以使用多个通配符。例子使用两个通配符,它们位于模式的两端:
SELECT prod_id, prod_name FROM Products
WHERE prod_name LIKE '%bean bag%';
注意
包括 Access 在内的许多 DBMS 都用空格来填补字段的内容。
例如,如果某列有 50 个字符,而存储的文本为 Fish bean bag toy(17 个字符),则为填满该列需要在文本后附加 33 个空格。这样做一般对数据及其使用没有影响,但是可能对上述 SQL语句有负面影响。
子句WHERE prod_name LIKE 'F%y'
只匹配以 F 开头以 y 结尾的 prod_name。如果值后面跟空格,则不是以 y 结尾,所以 Fish bean bag toy 就不会检索出来。
解决办法:给搜索模式再增加一个%号,'F%y%'
还匹配 y 之后的字符或空格。
注意
通配符%不能匹配 NULL,子句WHERE prod_name LIKE '%'
不匹配产品名称为 NULL 的行。
下划线(_)通配符
下划线的用途与%一样,但只匹配单个字符,而不是多个字符。
SELECT prod_id, prod_name FROM Products
WHERE prod_name LIKE '__ inch teddy bear';
下面 SELECT 语句使用%通配符,返回三行产品:
SELECT prod_id, prod_name FROM Products
WHERE prod_name LIKE '% inch teddy bear';
方括号([ ])通配符
方括号([])通配符用来指定一个字符集,它必须匹配指定位置(通配符的位置)的一个字符。目前只有 Access 和 SQL Server 支持集合。
例如找出所有名字以 J 或 M 起头的联系人:
SELECT cust_contact FROM Customers
WHERE cust_contact LIKE '[JM]%' ORDER BY cust_contact;
此语句的 WHERE 子句中的模式为'[JM]%',这一搜索模式使用了两个不同的通配符。[JM]匹配方括号中任意一个字符,它也只能匹配单个字符。
此通配符可以用前缀字符(脱字号)来否定。例如,查询以 J 和 M 之外的任意字符起头的任意联系人名:
SELECT cust_contact FROM Customers
WHERE cust_contact LIKE '[^JM]%' ORDER BY cust_contact;
也可以使用 NOT 操作符得出类似的结果:
SELECT cust_contact FROM Customers
WHERE NOT cust_contact LIKE '[JM]%' ORDER BY cust_contact;
6.2 使用通配符的技巧
- 如果其他操作符能达到相同的目的,应该使用其他操作符。
- 确实需要使用通配符时,不要把它们用在搜索模式的开始处,会非常慢。
- 如果通配符放错地方,不会返回想要的数据。