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”。
请注意,如果左侧表达式产生 null,或者没有相等的右侧值且至少一个右侧行产生 null,则IN
构造的结果将为 null,而不是 false。这符合 SQL 关于 null 值布尔组合的常规规则。
与EXISTS
一样,假设子查询将被完全计算是不明智的。
row_constructor IN (subquery)
此IN
形式的左侧是一个行构造器,如第 4.2.13 节中所述。右侧是一个用括号括起来的子查询,它必须返回的列数与左侧行中的表达式数完全相同。计算左侧表达式并将其逐行与子查询结果的每一行进行比较。如果找到任何相等的子查询行,则IN
的结果为“true”。如果没有找到相等的行(包括子查询不返回任何行的情况),则结果为“false”。
与往常一样,行中的 null 值根据 SQL 布尔表达式的常规规则进行组合。如果所有相应成员均为非 null 且相等,则两行被认为相等;如果任何相应成员为非 null 且不相等,则两行不相等;否则,该行比较的结果未知(null)。如果所有逐行结果都不相等或为 null,且至少有一个为 null,则IN
的结果为 null。
9.23.3.NOT IN
#
expression NOT IN (subquery)
右侧是一个带括号的子查询,它必须返回一列。左表达式会被计算并与子查询结果的每一行进行比较。NOT IN
的结果为“true”,如果只找到不等的子查询行(包括子查询未返回任何行的情况)。如果找到任何相等的行,则结果为“false”。
请注意,如果左表达式产生 null,或者如果没有相等的右侧值且至少一个右侧行产生 null,则NOT IN
构造的结果将为 null,而不是 true。这符合 SQL 关于 null 值的布尔组合的常规规则。
与EXISTS
一样,假设子查询将被完全计算是不明智的。
row_constructor NOT IN (subquery)
此形式的NOT IN
的左侧是一个行构造器,如第 4.2.13 节所述。右侧是一个带括号的子查询,它必须返回与左侧行中的表达式数量完全相同的列。左表达式会被计算并与子查询结果的每一行按行进行比较。NOT IN
的结果为“true”,如果只找到不等的子查询行(包括子查询未返回任何行的情况)。如果找到任何相等的行,则结果为“false”。
与往常一样,行中的 null 值会按照 SQL 布尔表达式的常规规则进行组合。如果所有对应的成员都为非 null 且相等,则两行被视为相等;如果任何对应的成员为非 null 且不等,则两行不等;否则,该行比较的结果未知(null)。如果所有按行结果都为不等或 null,且至少有一个 null,则NOT IN
的结果为 null。
9.23.4.ANY
/SOME
#
expression operator ANY (subquery)
expression operator SOME (subquery)
右侧是一个带括号的子查询,它必须返回一列。左表达式会被计算并与子查询结果的每一行使用给定的*operator
*进行比较,该运算符必须产生一个布尔结果。ANY
的结果为“true”,如果获得任何 true 结果。如果未找到任何 true 结果(包括子查询未返回任何行的情况),则结果为“false”。
SOME
是ANY
的同义词。IN
等效于= ANY
。
请注意,如果没有成功,并且至少有一行右侧返回操作符结果的 null,则ANY
构造的结果将为 null,而不是 false。这符合 SQL 中有关 null 值布尔组合的常规规则。
与EXISTS
一样,假设子查询将被完全计算是不明智的。
row_constructor operator ANY (subquery)
row_constructor operator SOME (subquery)
此ANY
形式的左侧是一个行构造器,如第 4.2.13 节中所述。右侧是一个带括号的子查询,它必须返回与左侧行中表达式数量完全相同的列数。使用给定的*operator
*,对左侧表达式求值,并按行与子查询结果的每一行进行比较。如果比较对任何子查询行返回 true,则ANY
的结果为“true”。如果比较对每个子查询行(包括子查询不返回任何行的情况)返回 false,则结果为“false”。如果没有与子查询行的比较返回 true,并且至少有一个比较返回 NULL,则结果为 NULL。
有关行构造器比较含义的详细信息,请参阅第 9.24.5 节。
9.23.5.ALL
#
expression operator ALL (subquery)
右侧是一个带括号的子查询,它必须返回正好一列。使用给定的*operator
*对左侧表达式求值,并将其与子查询结果的每一行进行比较,该操作符必须产生布尔结果。ALL
的结果为“true”,如果所有行都产生 true(包括子查询不返回任何行的情况)。如果发现任何 false 结果,则结果为“false”。如果没有与子查询行的比较返回 false,并且至少有一个比较返回 NULL,则结果为 NULL。
NOT IN
等效于<> ALL
。
与EXISTS
一样,假设子查询将被完全计算是不明智的。
row_constructor operator ALL (subquery)
此ALL
形式的左侧是一个行构造函数,如第 4.2.13 节所述。右侧是一个带括号的子查询,它必须返回与左侧行中的表达式数量完全相同的列数。使用给定的*operator
*,对左侧表达式进行求值并将其逐行与子查询结果的每一行进行比较。如果比较对所有子查询行(包括子查询不返回任何行的情况)返回 true,则ALL
的结果为“true”。如果比较对任何子查询行返回 false,则结果为“false”。如果与子查询行的比较没有返回 false,但至少有一个比较返回 NULL,则结果为 NULL。
有关行构造器比较含义的详细信息,请参阅第 9.24.5 节。
9.23.6. 单行比较#
row_constructor operator (subquery)
左侧是一个行构造函数,如第 4.2.13 节所述。右侧是一个带括号的子查询,它必须返回与左侧行中的表达式数量完全相同的列数。此外,子查询不能返回多于一行。(如果返回零行,则结果视为 null。)对左侧进行求值并将其逐行与单个子查询结果行进行比较。
有关行构造器比较含义的详细信息,请参阅第 9.24.5 节。