5.1 组合WHERE子句
第4课介绍的所有WHERE
子句在过滤数据时使用的都是单一的条件。为了进行更强的过滤控制,SQL允许给出多个WHERE
子句。这些子句有两种使用方式,即以AND
子句或OR
子句的方式使用。
操作符(operator)
用来联结或改变WHERE
子句中的子句的关键字,也称为逻辑操作符(logical operator)。
5.1.1 AND操作符
要通过不止一个列进行过滤,可以使用AND
操作符给WHERE
子句附加条件。下面的代码给出了一个例子:
输入▼
SELECT prod_id, prod_price, prod_name
FROM Products
WHERE vend_id = 'DLL01' AND prod_price <= 4;
分析▼
此SQL语句检索由供应商DLL01
制造且价格小于等于4美元的所有产品的名称和价格。这条SELECT
语句中的WHERE
子句包含两个条件,用AND
关键字联结在一起。AND
指示DBMS只返回满足所有给定条件的行。如果某个产品由供应商DLL01
制造,但价格高于4美元,则不检索它。类似地,如果产品价格小于4美元,但不是由指定供应商制造的也不被检索。这条SQL语句产生的输出如下:
输出▼
prod_id prod_price prod_name
------- ---------- --------------------
BNBG02 3.4900 Bird bean bag toy
BNBG01 3.4900 Fish bean bag toy
BNBG03 3.4900 Rabbit bean bag toy
AND
用在WHERE
子句中的关键字,用来指示检索满足所有给定条件的行。
这个例子只包含一个AND
子句,因此最多有两个过滤条件。可以增加多个过滤条件,每个条件间都要使用AND
关键字。
说明:没有
ORDER BY
子句
为了节省空间,也为了减少你的输入,我在很多例子里省略了ORDER BY
子句。因此,你的输出完全有可能与书上的输出不一致。虽然返回行的数量总是对的,但它们的顺序可能不同。当然,如果你愿意也可以加上一个ORDER BY
子句,它应该放在WHERE
子句之后。
5.1.2 OR操作符
OR
操作符与AND
操作符正好相反,它指示DBMS检索匹配任一条件的行。事实上,许多DBMS在OR WHERE
子句的第一个条件得到满足的情况下,就不再计算第二个条件了(在第一个条件满足时,不管第二个条件是否满足,相应的行都将被检索出来)。
请看如下的SELECT
语句:
输入▼
SELECT prod_name, prod_price
FROM Products
WHERE vend_id = 'DLL01' OR vend_id = ‘BRS01’;
分析▼
此SQL语句检索由任一个指定供应商制造的所有产品的产品名和价格。OR
操作符告诉DBMS匹配任一条件而不是同时匹配两个条件。如果这里使用的是AND
操作符,则没有数据返回(因为会创建没有匹配行的WHERE
子句)。这条SQL语句产生的输出如下:
输出▼
prod_name prod_price
------------------- ----------
Fish bean bag toy 3.4900
Bird bean bag toy 3.4900
Rabbit bean bag toy 3.4900
8 inch teddy bear 5.9900
12 inch teddy bear 8.9900
18 inch teddy bear 11.9900
Raggedy Ann 4.9900
OR
WHERE
子句中使用的关键字,用来表示检索匹配任一给定条件的行。
5.1.3 求值顺序
WHERE
子句可以包含任意数目的AND
和OR
操作符。允许两者结合以进行复杂、高级的过滤。
但是,组合AND
和OR
会带来了一个有趣的问题。为了说明这个问题,来看一个例子。假如需要列出价格为10美元及以上,且由DLL01
或BRS01
制造的所有产品。下面的SELECT
语句使用组合的AND
和OR
操作符建立了一个WHERE
子句:
输入▼
SELECT prod_name, prod_price
FROM Products
WHERE vend_id = 'DLL01' OR vend_id = ‘BRS01’
AND prod_price >= 10;
输出▼
prod_name prod_price
------------------- ----------
Fish bean bag toy 3.4900
Bird bean bag toy 3.4900
Rabbit bean bag toy 3.4900
18 inch teddy bear 11.9900
Raggedy Ann 4.9900
分析▼
请看上面的结果。返回的行中有4行价格小于10美元,显然,返回的行未按预期的进行过滤。为什么会这样呢?原因在于求值的顺序。SQL(像多数语言一样)在处理OR
操作符前,优先处理AND
操作符。当SQL看到上述WHERE
子句时,它理解为:由供应商BRS01
制造的价格为10美元以上的所有产品,以及由供应商DLL01
制造的所有产品,而不管其价格如何。换句话说,由于AND
在求值过程中优先级更高,操作符被错误地组合了。
此问题的解决方法是使用圆括号对操作符进行明确分组。请看下面的SELECT
语句及输出:
输入▼
SELECT prod_name, prod_price
FROM Products
WHERE (vend_id = 'DLL01' OR vend_id = ‘BRS01’)
AND prod_price >= 10;
输出▼
prod_name prod_price
------------------- ----------
18 inch teddy bear 11.9900
分析▼
这条SELECT
语句与前一条的唯一差别是,将前两个条件用圆括号括了起来。因为圆括号具有比AND
或OR
操作符更高的求值顺序,所以DBMS首先过滤圆括号内的OR
条件。这时,SQL语句变成了选择由供应商DLL01
或BRS01
制造的且价格在10美元及以上的所有产品,这正是我们希望的结果。
提示:在
WHERE
子句中使用圆括号
任何时候使用具有AND
和OR
操作符的WHERE
子句,都应该使用圆括号明确地分组操作符。不要过分依赖默认求值顺序,即使它确实如你希望的那样。使用圆括号没有什么坏处,它能消除歧义。