9.20. 子查询表达式

本节描述PostgreSQL里与SQL兼容的子查询表达式。 所有本节中的表达式都返回布尔值(真/假)结果

9.20.1. EXISTS

EXISTS (subquery)

EXISTS的参数是一个任意的SELECT语句,或者说子查询。 系统对子查询进行运算以判断它是否返回行。如果它至少返回一行, 那么EXISTS的结果就为"真"true""; 如果子查询没有返回任何行,那么EXISTS的结果是"假"false""。

子查询可以引用包围它的查询的变量,这些变量在该子查询的每一次计算中都起常量的作用。

这个子查询通常只是运行到能判断它是否可以生成至少一行为止, 而不是等到全部结束。在这里写任何有副作用的 子查询都是不明智的(比如调用序列函数);这些副作用是否发生是很难判断的。

因为结果只取决于是否会返回行,而不取决于这些行的内容, 所以这个子查询的输出列表通常是无关紧要的。一个常用的编码习惯是 用下面的形式写EXISTS测试:EXISTS(SELECT 1 WHERE ...)。 不过这条规则也有例外,比如那些使用INTERSECT的子查询。

下面这个简单的例子类似在col2上的一次内连接,但是它为每 个tab1的行生成最多一个输出,即使存在多个匹配tab2的行也如此

SELECT col1
FROM tab1
WHERE EXISTS (SELECT 1 FROM tab2 WHERE col2 = tab1.col2);

9.20.2. IN

expressionIN (subquery)

右边是一个圆括号括起来的子查询,它必须只返回一个字段。 左边表达式对子查询结果的每一行进行一次计算和比较。 如果找到任何相等的子查询行,则IN结果为"真"true""。如果没有找到任何相等行, 则结果为"假"false""(包括子查询没有返回任何行的情况)。

请注意,如果左边表达式的值为 NULL ,或者没有相等的右边值并且至少有一个右边行生成 NULL ,那么IN的结果将是 NULL , 而不是假。这个行为遵照 SQL 处理布尔值和 NULL 组合时的规则。

EXISTS一样,假设完全运行子查询是不明智的。

row_constructorIN (subquery)

左边是一个行构造器(如Section 4.2.12所述),右边是一个圆括号括起来的子查询, 它必须返回和左边行构造器一样多的字段。左边表达式对子查询结果的每一行 进行一次计算和比较。如果找到相等的子查询行,则IN结果为"真"true""。 如果没有找到任何相等行,则结果为"假"false""(包括子查询没有返回任何行的情况)。

表达式或子查询行里的 NULL 遵照 SQL 处理布尔值和 NULL 组合时的规则。如果两个行对应的字段都相等且非空, 那么这两行相等;如果任意对应字段不等且非空,那么这两行不等;否则结果是未知(NULL)。如果每一行的结果都是不等或 NULL , 并且至少有一个 NULL ,那么 IN 的结果是 NULL

9.20.3. NOT IN

expressionNOT IN (subquery)

右边是一个圆括号括起来的子查询,它必须只返回一个字段。左边表达式对子查询结果的每一行进行一次计算和比较。 如果只找到不相等的子查询行(包括子查询没有返回任何行的情况), 则NOT IN结果为"真"true""。如果找到任何相等行,则结果为"假"false""。

请注意,如果左边表达式的值为 NULL ,或者没有相等的右边值并且至少有一个右边行生成 NULL ,那么NOT IN的结果将是 NULL , 而不是真。这个行为遵照 SQL 处理布尔值和 NULL 组合时的规则

EXISTS一样,假设完全运行子查询是不明智的。

row_constructorNOT IN (subquery)

左边是一个行构造器(如Section 4.2.12所述),右边是一个圆括号括起来的子查询, 它必须返回和左边行构造器一样多的字段。左边表达式对子查询结果的每一行 进行一次计算和比较。如果只出现不相等的子查询行,则NOT IN结果为"真"true""。 (包括子查询没有返回任何行的情况)。如果找到相等的子查询行,则结果为"假"false""。

表达式或子查询行里的 NULL 遵照 SQL 处理布尔值和 NULL 组合时的规则。 如果两个行对应的字段都相等且非空,那么这两行相等;如果任意对应字段不等且非空,那么这两行不等; 否则结果是未知(NULL)。如果每一行的结果都是不等或 NULL , 并且至少有一个 NULL ,那么NOT IN的结果是 NULL 。

9.20.4. ANY/SOME

expressionoperatorANY (subquery)
expressionoperatorSOME (subquery)

右边是一个圆括号括起来的子查询,它必须只返回一个字段。 左边表达式使用operator对子查询结果的每一行进行一次计算和比较, 其结果必须是布尔值。如果至少获得一个真值,则ANY结果为"真"true""。 如果全部获得假值,则结果是"假"false""(包括子查询没有返回任何行的情况)。

SOMEANY的同意词。IN等效于= ANY

请注意,如果没有获得任何真值并且至少有一个右边行在该操作符上生成 NULL , 那么ANY的结果将是 NULL , 而不是假。这个行为遵照 SQL 处理布尔值和 NULL 组合时的规则。

EXISTS一样,假设完全运行子查询是不明智的。

row_constructoroperatorANY (subquery)
row_constructoroperatorSOME (subquery)

左边是一个行构造器(如Section 4.2.12所述),右边是一个圆括号括起来的子查询, 它必须返回和左边行构造器一样多的字段。左边表达式使用operator对子查 询结果的每一行进行一次计算和比较,其结果必须是布尔值。如果至少获得一个真值, 则ANY结果为"真"true""。如果全部获得假值, 则结果是"假"false""(包括子查询没有返回任何行的情况)。 如果没有获得任何真值并且至少有一个右边行在该操作符上生成 NULL 。

查看Section 9.21.5获取关于逐行比较的细节。

9.20.5. ALL

expressionoperatorALL (subquery)

右边是一个圆括号括起来的子查询,它必须只返回一个字段。 左边表达式使用operator对子查询结果的每行进行一次计算和比较, 其结果必须是布尔值。如果全部获得真值,ALL结果为"真"true""(包括子查询没有返回任何行的情况)。 如果至少获得一个假值,则结果是"假"。如果比较不会返回任何行为 false,并且至少一个行返回 NULL,则结果为 NULL。

NOT IN等效于<> ALL

EXISTS一样,假设完全运行子查询是不明智的。

row_constructoroperatorALL (subquery)

左边是一个行构造器(如Section 4.2.12所述),右边是一个圆括号括起来的子查询, 它必须返回和左边行构造器一样多的字段。左边表达式使用operator对子查询结果 的每一行进行一次计算和比较,其结果必须是布尔值。如果全部获得真值, ALL结果为"真"true""(包括子查询没有返回任何行的情况)。 如果至少获得一个假值,则结果是"假"false""。如果比较不会返回任何行为 false,并且至少一个行返回 NULL,则结果为 NULL。

查看Section 9.21.5以获取关于逐行比较的细节

9.20.6. 逐行比较

row_constructoroperator(subquery)

左边是一个行构造器(如Section 4.2.12所述),右边是一个圆括号括起来的子查询, 它必须返回和左边行构造器一样多的字段。而且,该子查询不能返回超 过 1 行结果(返回零行相当于 NULL)。 左边表达式对子查询的唯一结果行进行计算和比较。

查看Section 9.21.5以获取关于逐行比较的细节。