PostgreSQL 9.4.4 中文手册
上一页 | 上一级 | 章 9. 函数和操作符 | 下一页

# 9.22. 子查询表达式

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

## 9.22.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.22.2. `IN`

    expression IN (subquery)

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

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

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

    row_constructor IN (subquery)

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

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

## 9.22.3. `NOT IN`

    expression NOT IN (subquery)

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

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

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

    row_constructor NOT IN (subquery)

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

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

## 9.22.4. `ANY`/`SOME`

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

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

`SOME`是`ANY`的同意词。`IN`等效于`= ANY`。

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

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

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

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

查看第 9.23.5 节获取关于行构造比较含义的细节。

## 9.22.5. `ALL`

    expression operator ALL (subquery)

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

`NOT IN`等效于`<> ALL`。

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

    row_constructor operator ALL (subquery)

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

查看第 9.23.5 节以获取关于行构造比较含义的细节。

## 9.22.6. 单行比较

    row_constructor operator (subquery)

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

查看第 9.23.5 节以获取关于行构造比较含义的细节。

上一页 | 起始页 | 下一页
窗口函数 | 上一级 | 行和数组比较