ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
# 9.23\. 行和数组比较 本节描述几个特殊的构造,用于在多组值之间进行多重比较。 这些形式语法上和上一节的子查询形式相关,但是不涉及子查询。 这种形式涉及的数组子表达式是PostgreSQL的扩展; 其它的是SQL兼容的。所有本节记录的表达式形式都返回布尔值(真/假)。 ## 9.23.1\. `IN` ``` _expression_ IN (_value_ [, ...]) ``` 右边是一个圆括弧包围的标量列表。如果左边的表达式结果等于任何右边表达式中的一个, 结果为"真"。它是下面这种方式的缩写 ``` _expression_ = _value1_ OR _expression_ = _value2_ OR ... ``` 请注意,如果左边表达式的值为 NULL ,或者没有相等的右边值并且至少有一个右边表达式的值为 NULL , 那么`IN`的结果将是 NULL ,而不是假。这个行为遵照 SQL 处理布尔值和 NULL 组合时的规则。 ## 9.23.2\. `NOT IN` ``` _expression_ NOT IN (_value_ [, ...]) ``` 右边是一个圆括弧包围的标量列表。如果左边的表达式结果不等于任何右边表达式,结果为"真"。 它是下面这种方式的缩写 ``` _expression_ <> _value1_ AND _expression_ <> _value2_ AND ... ``` 请注意,如果左边表达式的值为 NULL ,或者没有相等的右边值并且至少有一个右边表达式的值为 NULL , 那么`NOT IN`的结果将是 NULL ,而不是真。这个行为遵照 SQL 处理布尔值和 NULL 组合时的规则。 > **Tip:** `x NOT IN y`在所有场合都等价于`NOT (x IN y)`。 但是,在处理 NULL 的时候,用`NOT IN`比用`IN`更容易迷惑新手。 最好用正逻辑来表达你的条件。 ## 9.23.3\. `ANY`/`SOME` (array) ``` _expression_ _operator_ ANY (_array expression_) _expression_ _operator_ SOME (_array expression_) ``` 右边是一个圆括弧包围的表达式,它必须生成一个数组值。左边表达式使用`_operator_` 对数组的每一个元素进行一次计算和比较,其结果必须是布尔值。如果至少获得一个真值, 则`ANY`结果为"真"。如果全部获得假值,则结果是"假" (包括数组不含任何元素的情况)。 如果数组表达式的值为 NULL ,那么`ANY`的结果也为 NULL 。 如果左边表达式的值为 NULL ,那么`ANY`的结果通常也为 NULL (某些不严格的比较操作符可能得到不同的结果)。另外, 如果右边的数组表达式中包含 NULL 元素并且没有为真的比较结果, 那么`ANY`的结果将是 NULL(某些不严格的比较操作符可能得到不同的结果), 而不是假。这个行为遵照 SQL 处理布尔值和 NULL 组合时的规则。 `SOME`是`ANY`的同意词。 ## 9.23.4\. `ALL` (array) ``` _expression_ _operator_ ALL (_array expression_) ``` 右边是一个圆括弧包围的表达式,它必须生成一个数组值。左边表达式使用`_operator_` 对数组的每一个元素进行一次计算和比较,其结果必须是布尔值。如果全部获得真值,`ALL` 结果为"真"(包括数组不含任何元素的情况)。如果至少获得一个假值,则结果是"假"。 如果数组表达式的值为 NULL ,那么`ALL`的结果也为 NULL 。 如果左边表达式的值为 NULL ,那么`ALL`的结果通常也为 NULL (某些不严格的比较操作符可能得到不同的结果)。另外, 如果右边的数组表达式中包含 NULL 元素并且没有为假的比较结果,那么`ALL` 的结果将是 NULL(某些不严格的比较操作符可能得到不同的结果),而不是真。 这个行为遵照 SQL 处理布尔值和 NULL 组合时的规则。 ## 9.23.5\. 逐行比较 ``` _row_constructor_ _operator_ _row_constructor_ ``` 两边都是一个[Section 4.2.13](#calibre_link-1524)所述的行构造器; 两个行的字段数必须相同。两边都被计算并且逐行比较。目前,用于比较的 `_operator_`操作符仅允许为 `=`, `&lt;&gt;`, `&lt;`, `&lt;=`, `&gt;`, `&gt;=`或与其具有相似的语意。 特别地,如果一个操作符属于 B-tree 操作符类,那么该操作符可以是一个行比较操作符或除`=` 之外的 B-tree 操作符类。 `=`和`&lt;&gt;`与其它操作符稍有区别。如果两行对应的元素全都非空且相等, 那么这两行就被认为是相等的;如果两行对应的元素中有任意一对非空且不等, 那么这两行就被认为是不等的;否则这两行的比较结果是未知(NULL)。 对于 `&lt;`, `&lt;=`, `&gt;`, `&gt;=`操作符, 行中的元素将按照从左到右的顺序依次进行比较,直到遇见一对不相等的元素或者一对 NULL 值。 如果这对元素中存在至少一个 NULL 值,那么比较的结果是 NULL ; 否则这对元素的比较结果就是最终的比较结果。例如,`ROW(1,2,NULL) &lt; ROW(1,3,0)` 的结果是真而不是 NULL ,因为比较到第二对元素的时候就已经得到了最终结果,不需要对第三对元素进行比较了。 > **Note:** 在PostgreSQL 8.2之前,`&lt;`, `&lt;=`, `&gt;`, `&gt;=`并不遵守 SQL 标准。比如,`ROW(a,b) &lt; ROW(c,d)` 将等价于`a &lt; c AND b &lt; d`,而正确的做法应当是等价于`a &lt; c OR (a = c AND b &lt; d)`。 ``` _row_constructor_ IS DISTINCT FROM _row_constructor_ ``` 这个构造类似于`&lt;&gt;`行比较,但是它对 NULL 输入不生成 NULL , 而是认为任何 NULL 都不等于任何非 NULL ,并且 NULL 之间是相等的。因此, 结果要么是真要么是假,而绝不会是未知(NULL)。 ``` _row_constructor_ IS NOT DISTINCT FROM _row_constructor_ ``` 这个构造类似于`=`行比较,但是它对 NULL 输入不生成 NULL , 而是认为任何 NULL 都不等于任何非 NULL ,并且 NULL 之间是相等的。 因此,结果要么是真要么是假,而绝不会是未知(NULL)。 > **Note:** 如果结果依赖于比较两个NULL值或一个NULL值和一个非NULL值,SQL 规范要求逐行比较返回 NULL。 PostgreSQL仅当比较两个行构造的结果或一个行构造器和子查询的输出时这样做 (就像[Section 9.22](#calibre_link-1795)描述的那样)。在其它情况下,两个复合类型的值进行比较, 认为两个NULL字段值是相等的,并且NULL大于非NULL。这是必要的,如此才能有一致的排序和复合类型的索引行为。