4.15. 子查询表达式 #
本节描述 PostgreSQL 中可用的 SQL 兼容的子查询表达式。本节中记录的所有表达式形式都返回布尔值(真/假)结果。
EXISTS
EXISTS ( subquery ) EXISTS 的参数是一个任意的 SELECT 语句,即子查询。对子查询求值以确定它是否返回任何行。如果它返回至少一行,EXISTS 的结果是
TRUE;如果子查询不返回行,EXISTS 的结果是 FALSE。
子查询可以引用外层查询的变量,这些变量在该子查询的任何一次计算中都起常量的作用。
子查询通常只会执行到足以确定是否至少返回一行,而不会完全执行到结束。编写有副作用的子查询(如调用序列函数)是不明智的;副作用是否发生可能难以预测。
由于结果只取决于是否返回任何行,而不取决于这些行的内容,子查询的输出列表通常无关紧要。一个常见的编码惯例是把所有
EXISTS 测试写成
EXISTS(SELECT 1 WHERE ...) 的形式。但这条规则也有例外,比如使用 INTERSECT 的子查询。
这个简单的例子类似于在 col2 上的内连接,但即使有多个匹配的 tab2 行,它对每个 tab1 行也最多产生一个输出行:
SELECT col1 FROM tab1
WHERE EXISTS(SELECT 1 FROM tab2 WHERE col2 = tab1.col2);
IN (scalar form)
expressionIN (value[, ...])
这种形式的 IN 的右边是一个由圆括号括起的标量表达式列表。如果左边表达式的结果等于任何一个右边表达式,结果为 TRUE。这是一种简写记法:
expression=value1ORexpression=value2OR ...
注意,如果左边表达式产生 NULL,或者没有相等的右边值且至少一个右边行产生
NULL,IN 结构的结果将是 NULL 而不是 FALSE。这符合 SQL 对 NULL 布尔组合的正常规则。
注意
这种形式的 IN 并不是真正的子查询表达式,但把它与子查询 IN 记录在同一地方似乎最合适。
IN (subquery form)
expressionIN (subquery)
这种形式的 IN 的右边是一个带圆括号的子查询,它必须恰好返回一列。左边的表达式被求值并与子查询结果的每一行比较。如果找到任何相等的子查询行,IN 的结果为 TRUE。如果没有找到相等的行(包括子查询不返回行的特殊情况),结果为 FALSE。
注意,如果左边表达式产生 NULL,或者没有相等的右边值且至少一个右边行产生
NULL,IN 结构的结果将是 NULL 而不是 FALSE。这符合 SQL 对 NULL 布尔组合的正常规则。
和EXISTS一样,假定子查询一定会完整运行并不明智。
(expression,expression[, ...]) IN (subquery)
这种形式的 IN 的右边是一个带圆括号的子查询,它必须返回与左边列表中表达式数量完全相同的列。左边的表达式与子查询结果的每一行逐行比较。如果找到任何相等的子查询行,IN 的结果为 TRUE。如果没有找到相等的行(包括子查询不返回行的特殊情况),结果为 FALSE。
与通常一样,表达式或子查询行中的 NULL 按照
SQL 布尔表达式的正常规则组合。如果两个行的所有对应成员都非空且相等,则认为它们相等;如果任何对应成员非空且不相等,则两行不相等;否则该行比较的结果为未知(NULL)。如果所有行比较的结果要么不相等要么为 NULL,且至少有一个为 NULL,那么 IN 的结果为 NULL。
NOT IN (scalar form)
expressionNOT IN (value[, ...])
这种形式的 NOT IN 的右边是一个由圆括号括起的标量表达式列表。如果左边表达式的结果与所有右边表达式都不相等,结果为 TRUE。这是一种简写记法:
expression<>value1ANDexpression<>value2AND ...
注意,如果左边表达式产生 NULL,或者没有相等的右边值且至少一个右边行产生
NULL,NOT IN 结构的结果将是 NULL 而不是人们可能天真期望的 TRUE。这符合 SQL 对 NULL 布尔组合的正常规则。
提示
x NOT IN y 在所有情况下都等价于
NOT (x IN y)。但是,使用
NOT IN 时 NULL 比使用 IN 时更容易让新手犯错。如果可能,最好用肯定的形式表达你的条件。
NOT IN (subquery form)
expressionNOT IN (subquery)
这种形式的 NOT IN 的右边是一个带圆括号的子查询,它必须恰好返回一列。左边的表达式被求值并与子查询结果的每一行比较。如果只找到不相等的子查询行(包括子查询不返回行的特殊情况),NOT IN 的结果为 TRUE。如果找到任何相等的行,结果为 FALSE。
注意,如果左边表达式产生 NULL,或者没有相等的右边值且至少一个右边行产生
NULL,NOT IN 结构的结果将是 NULL 而不是 TRUE。这符合 SQL 对 NULL 布尔组合的正常规则。
和EXISTS一样,假定子查询一定会完整运行并不明智。
(expression,expression[, ...]) NOT IN (subquery)
这种形式的 NOT IN 的右边是一个带圆括号的子查询,它必须返回与左边列表中表达式数量完全相同的列。左边的表达式与子查询结果的每一行逐行比较。如果只找到不相等的子查询行(包括子查询不返回行的特殊情况),NOT IN 的结果为 TRUE。如果找到任何相等的行,结果为 FALSE。
与通常一样,表达式或子查询行中的 NULL 按照
SQL 布尔表达式的正常规则组合。如果两个行的所有对应成员都非空且相等,则认为它们相等;如果任何对应成员非空且不相等,则两行不相等;否则该行比较的结果为未知(NULL)。如果所有行比较的结果要么不相等要么为 NULL,且至少有一个为 NULL,那么 NOT IN 的结果为 NULL。
ANY
expressionoperatorANY (subquery)expressionoperatorSOME (subquery)
这种形式的 ANY 的右边是一个带圆括号的子查询,它必须恰好返回一列。左边的表达式使用给定的 operator 与子查询结果的每一行比较,该操作符必须产生布尔结果。如果得到任何真结果,ANY 的结果为 TRUE。如果没有找到真结果(包括子查询不返回行的特殊情况),结果为 FALSE。
SOME是ANY的同义词。IN等价于= ANY。
注意,如果没有成功且至少一个右边行对操作符的结果产生
NULL,ANY 结构的结果将是 NULL 而不是 FALSE。这符合 SQL 对 NULL 布尔组合的正常规则。
和EXISTS一样,假定子查询一定会完整运行并不明智。
(expression,expression[, ...])operatorANY (subquery) (expression,expression[, ...])operatorSOME (subquery)
这种形式的 ANY 的右边是一个带圆括号的子查询,它必须返回与左边列表中表达式数量完全相同的列。左边的表达式使用给定的 operator
与子查询结果的每一行逐行比较。目前,逐行 ANY 查询中只允许使用 = 和 <> 操作符。相应地,如果找到相等或不等的行,ANY 的结果为 TRUE。如果没有找到这样的行(包括子查询不返回行的特殊情况),结果为 FALSE。
与通常一样,表达式或子查询行中的 NULL 按照
SQL 布尔表达式的正常规则组合。如果两个行的所有对应成员都非空且相等,则认为它们相等;如果任何对应成员非空且不相等,则两行不相等;否则该行比较的结果为未知(NULL)。如果至少有一个行比较结果为 NULL,那么 ANY 的结果不可能是 FALSE;它将是 TRUE 或 NULL。
ALL
expressionoperatorALL (subquery)
这种形式的 ALL 的右边是一个带圆括号的子查询,它必须恰好返回一列。左边的表达式使用给定的 operator 与子查询结果的每一行比较,该操作符必须产生布尔结果。如果所有行都产生真(包括子查询不返回行的特殊情况),ALL 的结果为 TRUE。如果找到任何假结果,结果为 FALSE。
NOT IN等价于<> ALL。
注意,如果没有失败但至少一个右边行对操作符的结果产生
NULL,ALL 结构的结果将是 NULL 而不是 TRUE。这符合 SQL 对 NULL 布尔组合的正常规则。
和EXISTS一样,假定子查询一定会完整运行并不明智。
(expression,expression[, ...])operatorALL (subquery)
这种形式的 ALL 的右边是一个带圆括号的子查询,它必须返回与左边列表中表达式数量完全相同的列。左边的表达式使用给定的 operator
与子查询结果的每一行逐行比较。目前,逐行 ALL 查询中只允许使用 = 和 <> 操作符。相应地,如果所有子查询行都相等或都不相等(包括子查询不返回行的特殊情况),ALL 的结果为 TRUE。如果发现任何一行不相等或相等,结果为 FALSE。
与通常一样,表达式或子查询行中的 NULL 按照
SQL 布尔表达式的正常规则组合。如果两个行的所有对应成员都非空且相等,则认为它们相等;如果任何对应成员非空且不相等,则两行不相等;否则该行比较的结果为未知(NULL)。如果至少有一个行比较结果为 NULL,那么 ALL 的结果不可能是 TRUE;它将是 FALSE 或 NULL。
Row-wise comparison
(expression,expression[, ...])operator(subquery) (expression,expression[, ...])operator(expression,expression[, ...])
左边是标量表达式的列表。右边既可以是相同长度的标量表达式列表,也可以是一个带圆括号的子查询,该子查询必须恰好返回与左边表达式数量相同的列。此外,子查询不能返回多于一行。(如果它返回零行,结果视为 NULL。)左边被求值并与子查询结果的唯一一行或右边的表达式列表逐行比较。相应地,如果这两行相等或不相等,结果为 TRUE。
与通常一样,表达式或子查询行中的 NULL 按照 SQL 布尔表达式的正常规则组合。如果两个行的所有对应成员都非空且相等,则认为它们相等;如果任何对应成员非空且不相等,则两行不相等;否则该行比较的结果为未知(NULL)。