EXISTS 关键字

关键字 EXISTS 也被称为存在限定符,因为仅当外部 SELECT(如下所示)找到至少一行时,子查询才为 true 。

图: 查询

SELECT UNIQUE manu_name, lead_time 
          FROM manufact
          WHERE EXISTS
          (SELECT * FROM stock 
          WHERE description MATCHES '*shoe*'
          AND manufact.manu_code = stock.manu_code);
通常可使用 EXISTS 来构造等价于使用 IN 的查询的查询。下列查询使用 IN 谓词来构造与上述返回相同结果的查询。

图: 查询

SELECT UNIQUE manu_name, lead_time 
          FROM stock, manufact
          WHERE manufact.manu_code IN
          (SELECT manu_code FROM stock 
          WHERE description MATCHES '*shoe*')
          AND stock.manu_code = manufact.manu_code;
图 1图 2返回生产某种鞋的制造商以及预订产品的交付周期的行。该结果显示了返回值。

图: 查询结果

manu_name       lead_time 
          
          Anza               5
          Hero               4
          Karsten           21
          Nikolus            8
          ProCycle           9
          Shimara           30

将关键字 NOT 添加至 IN 或 EXISTS 以创建与前面查询相反的搜索条件。也可以用 !=ALL 代替 NOT IN。

下列查询显示了执行同一操作的两种方法。一种方法可能允许数据库服务器执行相对另一种方法较少的工作,则会取决于数据库的设计和表的大小。要了解哪一种查询更好,使用 SET EXPLAIN 命令来获取查询计划的清单。在 GBase 8s 性能指南 GBase 8s SQL 指南:语法 中讨论了 SET EXPLAIN。

图: 查询

SELECT customer_num, company FROM customer
          WHERE customer_num NOT IN
          (SELECT customer_num FROM orders
          WHERE customer.customer_num = orders.customer_num);
          
          SELECT customer_num, company FROM customer
          WHERE NOT EXISTS
          (SELECT * FROM orders
          WHERE customer.customer_num = orders.customer_num);
查询中的每个语句返回下列行,这些行标识尚未下订单的客户。

图: 查询结果

customer_num company
          
          102 Sports Spot
          103 Phil's Sports
          105 Los Altos Sports
          107 Athletic Supplies
          108 Quinn's Sports
          109 Sport Stuff
          113 Sportstown
          114 Sporting Place
          118 Blue Ribbon Sports
          125 Total Fitness Sports
          128 Phoenix University

关键字 EXISTS 和 IN 用于称为相交的集合运算,关键 NOT EXISTS 和 NOT IN 用于称为差异的集合运算。这些概念在集合运算中讨论。

下列查询执行对 items 表的子查询来标识 stock 表中尚未预订的所有商品。

图: 查询

SELECT * FROM stock 
          WHERE NOT EXISTS
          (SELECT * FROM items 
          WHERE stock.stock_num = items.stock_num
          AND stock.manu_code = items.manu_code);
该查询返回以下行。

图: 查询结果

stock_num manu_code description unit_price unit unit_descr
        
        101  PRC        bicycle tires       $88.00  box   4/box
        102  SHM        bicycle brakes     $220.00  case  4 sets/case
        102  PRC        bicycle brakes     $480.00  case  4 sets/case
        105  PRC        bicycle wheels      $53.00  pair  pair
        ⋮
        312  HRO        racer goggles       $72.00  box   12/box
        313  SHM        swim cap            $72.00  box   12/box
        313  ANZ        swim cap            $60.00  box   12/box

对 SELECT 语句可具有的子查询数没有逻辑限制。

您可能想要检查是否在数据库中正确输入了信息。查找数据库中的错误的一种方法是编写仅当错误存在时才会返回输出的查询。这种类型的子查询充当一种审计查询,如下所示。

图: 查询

SELECT * FROM items
          WHERE total_price != quantity *
          (SELECT unit_price FROM stock
          WHERE stock.stock_num = items.stock_num
          AND stock.manu_code = items.manu_code);
该查询只返回订单上商品的总价格不等于库存单价乘以订单数量的行。如果没有应用任何折扣,那么可能在数据库中不正确地输入了此类型的行。仅当错误发生时查询才会返回行。如果正确地将信息插入到数据库中,那么不会返回任何行。

图: 查询结果

item_num order_num stock_num manu_code quantity total_price 
          
          1      1004         1 HRO              1     $960.00
          2      1006         5 NRG              5     $190.00