9.22. 子查询表达式

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

9.22.1. EXISTS

EXISTS (subquery)

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

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

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

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

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

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

9.22.2. IN

expression IN (subquery)

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

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

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

row_constructor IN (subquery)

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

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

9.22.3. NOT IN

expression NOT IN (subquery)

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

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

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

row_constructor NOT IN (subquery)

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

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

9.22.4. ANY/SOME

expression operator ANY (subquery)
expression operator SOME (subquery)

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

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

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

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

row_constructor operator ANY (subquery)
row_constructor operator SOME (subquery)

左边是一个行构造器(如第 4.2.13 节所述), 右边是一个圆括弧括起来的子查询,它必须返回和左边行构造器一样多的字段。 左边表达式使用operator对子查询结果的每一行进行一次计算和比较。 如果至少获得一个真值,则ANY结果为"真"。 如果全部获得假值,则结果是"假"(包括子查询没有返回任何行的情况)。 如果没有获得任何真值并且至少有一个行返回 NULL ,那么结果将是 NULL。

查看第 9.23.5 节获取关于行构造比较含义的细节。

9.22.5. ALL

expression operator ALL (subquery)

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

NOT IN等效于<> ALL

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

row_constructor operator ALL (subquery)

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

查看第 9.23.5 节以获取关于行构造比较含义的细节。

9.22.6. 单行比较

row_constructor operator (subquery)

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

查看第 9.23.5 节以获取关于行构造比较含义的细节。