版本:
目录导航

9.23. 子查询表达式

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

9.23.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.23.2. IN

expression IN (subquery)

右手边是一个圆括号括起来的子查询,它必须正好只返回一列。左手边表达式将被计算并与子查询结果逐行进行比较。如果找到任何等于子查询行的情况,那么IN的结果就是“true”。 如果没有找到相等行,那么结果是“false”(包括子查询没有返回任何行的情况)。

请注意如果左手边表达式得到空值,或者没有相等的右手边值,并且至少有一个右手边行得到空值,那么IN结构的结果将是空值,而不是false。这个行为是遵照 SQL 处理空值的一般规则的。

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

row_constructor IN (subquery)

这种形式的IN的左手边是一个行构造器,如第 4.2.13 节中所述。右手边是一个圆括号括起来的子查询,它必须返回和左手边返回的行中表达式所构成的完全一样多的列。左手边表达式将被计算并与子查询结果逐行进行比较。如果找到任意相等的子查询行,则IN的结果为“true”。如果没有找到相等行,那么结果为“false”(包括子查询不返回行的情况)。

通常,表达式或者子查询行里的空值是按照 SQL 布尔表达式的一般规则进行组合的。如果两个行对应的成员都非空并且相等,那么认为这两行相等;如果任意对应成员为非空且不等,那么这两行不等;否则这样的行比较的结果是未知(空值)。如果所有行的结果要么是不等,要么是空值,并且至少有一个空值,那么IN的结果是空值。

9.23.3. NOT IN

expression NOT IN (subquery)

右手边是一个用圆括号包围的子查询,它必须返回正好一列。左手边表达式将被计算并与子查询结果逐行进行比较。如果只找到不相等的子查询行(包括子查询不返回行的情况),那么NOT IN的结果是“true”。如果找到任何相等行,则结果为“false”。

请注意如果左手边表达式得到空值,或者没有相等的右手边值,并且至少有一个右手边行得到空值,那么NOT IN结构的结果将是空值,而不是真。这个行为是遵照 SQL 处理空值的一般规则的。

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

row_constructor NOT IN (subquery)

这种形式的NOT IN的左手边是一个行构造器,如第 4.2.13 节中所述。右手边是一个圆括弧子查询,它必须返回和左手边返回的行中表达式所构成的完全一样多的列。左手边表达式将被计算并与子查询结果逐行进行比较。如果找到不等于子查询行的行,则NOT IN的结果为“真”。如果找到相等行,那么结果为“假”(包括子查询不返回行的情况)。

通常,表达式或者子查询行里的空值是按照 SQL 布尔表达式的一般规则进行组合的。如果两个行对应的成员都非空并且相等,那么认为这两行相等;如果任意对应成员为非空且不等,那么这两行不等;否则这样的行比较的结果是未知(空值)。如果所有行的结果要么是不等,要么是空值,并且至少有一个空值,那么NOT IN的结果是空值。

9.23.4. ANY/SOME

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

这种形式的右手边是一个圆括弧括起来的子查询,它必须返回正好一个列。左手边表达式将被计算并使用给出的operator对子查询结果逐行进行比较。如果获得任何真值结果,那么ANY的结果就是“真”。如果没有找到真值结果,那么结果是“假”(包括子查询没有返回任何行的情况)。

SOME是ANY的同义词。IN等价于= ANY。

请注意,如果没有任何成功并且至少有一个右手边行为该操作符结果生成空值, 那么ANY结构的结果将是空值,而不是假。 这个行为是遵照 SQL 处理空值布尔组合的一般规则制定的。

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

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

这种形式的左手边是一个行构造器,如第 4.2.13 节所述。 右手边是一个圆括弧括起来的子查询,它必须返回和左手边列表给出的表达式一样多的列。 左手边表达式将被计算并使用给出的操作符对子查询结果逐行进行比较。 如果比较对任何子查询行返回真,则ANY的结果为“真”。 如果比较对每一个子查询行都返回假,则结果为“假”(包括子查询不返回行的情况)。 如果比较不对任何行返回真,并且至少对一行返回 NULL,则结果为 NULL。

关于行构造器比较的详细含义请见第 9.24.5 节。

9.23.5. ALL

expression operator ALL (subquery)

ALL 的这种形式的右手边是一个圆括弧括起来的子查询,它必须只返回一列。 左手边表达式将被计算并使用给出的操作符对子查询结果逐行进行比较。 该操作符必须生成布尔结果。如果所有行得到真(包括子查询没有返回任何行的情况), ALL的结果就是“真”。如果存在任何假值结果,那么结果是“假”。 如果比较对任何行都不返回假,并且对至少一行返回 NULL,则结果为 NULL。

NOT IN等价于<> ALL。

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

row_constructor operator ALL (subquery)

ALL的这种形式的左侧是一个行构造器,如第 4.2.13 节所述。右侧是一个圆括号括起来的子查询,它必须返回与左侧行中表达式数量相同的列。左侧表达式将被计算,并使用给定的operator逐行与子查询结果进行比较。如果该比较对所有子查询行返回真,则ALL的结果为“true”(包括子查询没有返回任何行的情况)。如果该比较对任何子查询行返回假,则结果为“false”。如果没有与子查询行的比较返回假,并且至少有一个比较返回NULL,则结果为NULL。

关于行构造器比较的详细含义请见第 9.24.5 节。

9.23.6. 单行比较

row_constructor operator (subquery)

左侧是一个行构造器,如第 4.2.13 节所述。右侧是一个圆括号括起来的子查询,该查询必须返回与左侧行中表达式数量完全相同的列。此外,该子查询不能返回超过一行的结果。(如果它返回零行,则结果视为null。)左侧被计算并逐行与单个子查询结果行进行比较。

关于行构造器比较的详细含义请见第 9.24.5 节。