PostgreSQL 8.2.3 中文文档
后退快退章9. 函数和操作符快进前进

9.16. 子查询表达式

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

9.16.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.16.2. IN

expression IN (subquery)

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

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

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

row_constructor IN (subquery)

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

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

9.16.3. NOT IN

expression NOT IN (subquery)

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

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

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

row_constructor NOT IN (subquery)

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

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

9.16.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.11所述),右边是一个圆括弧括起来的子查询,它必须返回和左边行构造器一样多的字段。左边表达式使用 operator 对子查询结果的每一行进行一次计算和比较,其结果必须是布尔值。如果至少获得一个真值,则 ANY 结果为"真"。如果全部获得假值,则结果是"假"(包括子查询没有返回任何行的情况)。

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

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

9.16.5. ALL

expression operator ALL (subquery)

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

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

NOT IN 等效于 <> ALL

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

row_constructor operator ALL (subquery)

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

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

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

9.16.6. 逐行比较

row_constructor operator (subquery)

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

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


后退首页前进
聚集函数上一级行和数组比较