PostgreSQL 中文参考文档
🌐 英文原版 官方 ↗

9.24. 子查询表达式 #

9.24.1. EXISTS
9.24.2. IN
9.24.3. NOT IN
9.24.4. ANY/SOME
9.24.5. ALL
9.24.6. 单行比较

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

9.24.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.24.2. IN #

expression IN (subquery)

右侧是一个被圆括号括起来的子查询, 它必须恰好返回一列。 会对左侧表达式求值, 并把它与子查询结果的每一行进行比较。 如果找到了任何相等的子查询行, 那么 IN 的结果为 “真”。 如果没有找到相等的行 (包括子查询不返回任何行的情况), 结果为 “假”。

注意, 如果左侧表达式得出空值, 或者没有相等的右侧值且至少有一个右侧行得出空值, 那么 IN 构造的结果将是空, 而非假。 这符合 SQL 对空值布尔组合的常规规则。

与 EXISTS 一样, 假定子查询会被完整地求值是不明智的。

row_constructor IN (subquery)

这种形式的 IN 的左侧是一个行构造器, 如 Section 4.2.13 中所述。 右侧是一个被圆括号括起来的子查询, 它必须返回恰好与左侧行中的表达式数量相同的列。 会对左侧表达式求值, 并按行与子查询结果的每一行进行比较。 如果找到了任何相等的子查询行, 那么 IN 的结果为 “真”。 如果没有找到相等的行 (包括子查询不返回任何行的情况), 结果为 “假”。

照例, 行中的空值会按照 SQL 布尔表达式的常规规则合并。 如果两行所有相应的成员都非空且相等, 则这两行被视为相等; 如果任何相应的成员非空且不相等, 则这两行不相等; 否则那次行比较的结果是未知的 (空)。 如果所有的逐行结果要么是不相等要么是空, 且至少有一个是空, 那么 IN 的结果为空。

9.24.3. NOT IN #

expression NOT IN (subquery)

右侧是一个被圆括号括起来的子查询, 它必须恰好返回一列。 会对左侧表达式求值, 并把它与子查询结果的每一行进行比较。 如果只找到了不相等的子查询行 (包括子查询不返回任何行的情况), 那么 NOT IN 的结果为 “真”。 如果找到了任何相等的行, 结果为 “假”。

注意, 如果左侧表达式得出空值, 或者没有相等的右侧值且至少有一个右侧行得出空值, 那么 NOT IN 构造的结果将是空, 而非真。 这符合 SQL 对空值布尔组合的常规规则。

与 EXISTS 一样, 假定子查询会被完整地求值是不明智的。

row_constructor NOT IN (subquery)

这种形式的 NOT IN 的左侧是一个行构造器, 如 Section 4.2.13 中所述。 右侧是一个被圆括号括起来的子查询, 它必须返回恰好与左侧行中的表达式数量相同的列。 会对左侧表达式求值, 并按行与子查询结果的每一行进行比较。 如果只找到了不相等的子查询行 (包括子查询不返回任何行的情况), 那么 NOT IN 的结果为 “真”。 如果找到了任何相等的行, 结果为 “假”。

照例, 行中的空值会按照 SQL 布尔表达式的常规规则合并。 如果两行所有相应的成员都非空且相等, 则这两行被视为相等; 如果任何相应的成员非空且不相等, 则这两行不相等; 否则那次行比较的结果是未知的 (空)。 如果所有的逐行结果要么是不相等要么是空, 且至少有一个是空, 那么 NOT IN 的结果为空。

9.24.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)

这种形式的 ANY 的左侧是一个行构造器, 如 Section 4.2.13 中所述。 右侧是一个被圆括号括起来的子查询, 它必须返回恰好与左侧行中的表达式数量相同的列。 会对左侧表达式求值, 并使用给定的 operator 按行与子查询结果的每一行进行比较。 如果比较对任何子查询行返回真, 那么 ANY 的结果为 “真”。 如果比较对每个子查询行都返回假 (包括子查询不返回任何行的情况), 结果为 “假”。 如果与子查询行的比较没有返回真, 并且至少有一次比较返回 NULL, 则结果为 NULL。

关于行构造器比较的含义的细节, 请参见 Section 9.25.5。

9.24.5. ALL #

expression operator ALL (subquery)

右侧是一个被圆括号括起来的子查询, 它必须恰好返回一列。 会对左侧表达式求值, 并使用给定的 operator 与子查询结果的每一行进行比较, 该操作符必须产生一个布尔结果。 如果所有行都得出真 (包括子查询不返回任何行的情况), 那么 ALL 的结果为 “真”。 如果找到了任何假的结果, 结果为 “假”。 如果与子查询行的比较没有返回假, 并且至少有一次比较返回 NULL, 则结果为 NULL。

NOT IN 等同于 <> ALL。

与 EXISTS 一样, 假定子查询会被完整地求值是不明智的。

row_constructor operator ALL (subquery)

这种形式的 ALL 的左侧是一个行构造器, 如 Section 4.2.13 中所述。 右侧是一个被圆括号括起来的子查询, 它必须返回恰好与左侧行中的表达式数量相同的列。 会对左侧表达式求值, 并使用给定的 operator 按行与子查询结果的每一行进行比较。 如果比较对所有子查询行都返回真 (包括子查询不返回任何行的情况), 那么 ALL 的结果为 “真”。 如果比较对任何子查询行返回假, 结果为 “假”。 如果与子查询行的比较没有返回假, 并且至少有一次比较返回 NULL, 则结果为 NULL。

关于行构造器比较的含义的细节, 请参见 Section 9.25.5。

9.24.6. 单行比较 #

row_constructor operator (subquery)

左侧是一个行构造器, 如 Section 4.2.13 中所述。 右侧是一个被圆括号括起来的子查询, 它必须返回恰好与左侧行中的表达式数量相同的列。 此外, 该子查询不能返回多于一行。 (如果它返回零行, 那么结果被视为空。) 会对左侧求值, 并按行与该唯一的子查询结果行进行比较。

关于行构造器比较的含义的细节, 请参见 Section 9.25.5。