例子:有 Product 产品表 和 ShopProduct 店铺表,选取出“大阪店(shop_id:000C)在售商品的销售单价”。
-- IN 写法 SELECT product_name, sale_price FROM Product WHERE product_id IN ( SELECT product_id FROM ShopProduct WHERE shop_id = '000C' ); -- EXISTS 写法 [推荐] SELECT product_name, sale_price FROM Product AS P WHERE EXISTS ( SELECT * -- ① FROM ShopProduct AS SP WHERE SP.shop_id = '000C' AND SP.product_id = P.product_id ); -- NOT EXISTS 写法 —— “东京店(shop_id:000A)在售之外的商品的销售单价” SELECT product_name, sale_price FROM Product AS P WHERE NOT EXISTS ( SELECT * FROM ShopProduct AS SP WHERE SP.shop_id = '000A' AND SP.product_id = P.product_id );注意:① 这里的 SELECT * ,返回哪些列都没有关系(当然惯例还是用 * 最好),因为 EXIST 只关心记录是否存在。
拓展:NOT EXISTS 具备有差集运算的功能。
7、NOT、AND、OR
NOT 运算符用来否定某一条件,但是不能滥用。否则会降低可读性。
(6)拓展 - N 阶谓词的划分谓词逻辑中,根据输入值的阶数(order)对谓词进行分类。
= 或者 BETWEEEN 等大多数输入值为一行的谓词叫作“一阶谓词”,
而像 IN(ANY)、ALL 、EXISTS 还有 HAVING 这样输入值为行的集合的谓词叫作“二阶谓词”。
二阶谓词一般都习惯跟 关联子查询 搭配使用。
二阶谓词,如 IN 和 EXISTS 和 HAVING 在很多情况下都是可以互换的,
三阶谓词=输入值为“集合的集合”的谓词
四阶谓词=输入值为“集合的集合的集合”的谓词
我们可以像上面这样无限地扩展阶数,但是SQL 里并不会出现三阶以上的情况,所以不用太在意。
使用过List、Hakell 等函数式语言或者Java 的读者可能知道“高阶函数”这一概念。它指的是不以一般的原子性的值为参数,而以函数为参数的函数。
(7)运算符上面从谓词的角度分类,这里我们按照运算符的角度来划分的话:
1、算术运算符
+、-、*、/、%
2、比较运算符
即上面介绍的 比较谓词。
3、逻辑运算符
即上面介绍的 其他谓词。
4、其他运算符
||:拼接字符串
运算符的优先级:(圆括号)> 算术运算符 > 比较运算符 > 逻辑运算符。
其中,逻辑运算符中的优先级:NOT > AND > OR。
(8)特殊的 NULL1、NULL 不是值
NULL 容易被认为是值的原因恐怕有两个。
第一个是在 C 语言等编程语言里面,NULL 被定义为了一个常量(很多语言将其定义为了整数0),这导致了人们的混淆。但是,其实 SQL 里的 NULL 和其他编程语言里的 NULL 是完全不同的东西。
第二个原因是,IS NULL 这样的谓词是由两个单词构成的,所以人们容易把 IS 当作谓词,而把 NULL 当作值。我们应该把 IS NULL 看作是一个谓词。因此,如果可以的话,写成 IS_NULL 这样也许更合适。
2、因为 NULL 不是值,所以常见的对 NULL 的说法也是错的:“列的值为NULL”、“NULL 值”……
3、算术运算符 遇上 NULL 结果都是 NULL
4、比较运算符 和 逻辑运算符 遇上 NULL 结果基本上是 unknown,或者说,对 NULL 使用谓词后的结果基本上是 unknown。
为什么说基本上? 因为有特殊情况,如遇到 OR 和 AND,还是会分别出现结果是 TRUE 和 FALSE 的;或者 EXIST
具体参考下面的真值表: