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

9.25. 行与数组比较 #

9.25.1. IN
9.25.2. NOT IN
9.25.3. ANY/SOME(数组)
9.25.4. ALL(数组)
9.25.5. 行构造器比较
9.25.6. 复合类型比较

本节描述用于在值组之间进行多次比较的若干专用构造。 这些形式在语法上与上一节的子查询形式相关, 但不涉及子查询。 涉及数组子表达式的形式是 PostgreSQL 的扩展; 其余的则符合 SQL 标准。 本节中记录的所有表达式形式都返回布尔 (真/假) 结果。

9.25.1. IN #

expression IN (value [, ...])

右侧是一个被圆括号括起来的表达式列表。 如果左侧表达式的结果等于右侧的任何表达式, 则结果为 “真”。 这是以下写法的简写形式:

expression = value1
OR
expression = value2
OR
...

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

9.25.2. NOT IN #

expression NOT IN (value [, ...])

右侧是一个被圆括号括起来的表达式列表。 如果左侧表达式的结果与右侧的所有表达式都不相等, 则结果为 “真”。 这是以下写法的简写形式:

expression <> value1
AND
expression <> value2
AND
...

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

Tip

在所有情况下, x NOT IN y 都等同于 NOT (x IN y)。 然而, 新手在使用 NOT IN 时比在使用 IN 时更容易被空值绊倒。 如果可能, 最好以肯定的方式表达你的条件。

9.25.3. ANY/SOME(数组) #

expression operator ANY (array expression)
expression operator SOME (array expression)

右侧是一个被圆括号括起来的表达式, 它必须得出一个数组值。 会对左侧表达式求值, 并使用给定的 operator 与数组的每个元素进行比较, 该操作符必须产生一个布尔结果。 如果得到了任何真的结果, 那么 ANY 的结果为 “真”。 如果没有找到任何真的结果 (包括数组有零个元素的情况), 结果为 “假”。

如果数组表达式得出一个空数组, 那么 ANY 的结果将为空。 如果左侧表达式得出空值, 那么 ANY 的结果通常为空 (不过一个非严格的比较操作符可能产生不同的结果)。 此外, 如果右侧数组包含任何空元素, 并且没有获得任何真的比较结果, 那么 ANY 的结果将为空, 而非假 (再次假定是一个严格的比较操作符)。 这符合 SQL 对空值布尔组合的常规规则。

SOME 是 ANY 的同义词。

9.25.4. ALL(数组) #

expression operator ALL (array expression)

右侧是一个被圆括号括起来的表达式, 它必须得出一个数组值。 会对左侧表达式求值, 并使用给定的 operator 与数组的每个元素进行比较, 该操作符必须产生一个布尔结果。 如果所有比较都得出真 (包括数组有零个元素的情况), 那么 ALL 的结果为 “真”。 如果找到了任何假的结果, 结果为 “假”。

如果数组表达式得出一个空数组, 那么 ALL 的结果将为空。 如果左侧表达式得出空值, 那么 ALL 的结果通常为空 (不过一个非严格的比较操作符可能产生不同的结果)。 此外, 如果右侧数组包含任何空元素, 并且没有获得任何假的比较结果, 那么 ALL 的结果将为空, 而非真 (再次假定是一个严格的比较操作符)。 这符合 SQL 对空值布尔组合的常规规则。

9.25.5. 行构造器比较 #

row_constructor operator row_constructor

每一侧都是一个行构造器, 如 Section 4.2.13 中所述。 两个行构造器必须具有相同数量的字段。 给定的 operator 会被应用到每一对相应的字段上。 (由于这些字段可能属于不同的类型, 这意味着可能为每一对选择不同的具体操作符。) 所有被选中的操作符都必须是某个 B-tree 操作符类的成员, 或者是一个 B-tree 操作符类的 = 成员的取反操作符, 这意味着行构造器比较只有在 operator 是 =、 <>、 <、 <=、 > 或 >=, 或者语义类似于其中之一时才有可能。

= 和 <> 的情形与其他情形的工作方式略有不同。 如果两行所有相应的成员都非空且相等, 则这两行被视为相等; 如果任何相应的成员非空且不相等, 则这两行不相等; 否则那次行比较的结果是未知的 (空)。

对于 <、 <=、 > 和 >= 这些情形, 行元素会从左到右进行比较, 一旦找到一对不相等或为空的元素就停止。 如果这对元素中的任何一个为空, 那么那次行比较的结果是未知的 (空); 否则这对元素的比较决定结果。 例如, ROW(1,2,NULL) < ROW(1,3,0) 得出真, 而非空, 因为第三对元素没有被考虑。

row_constructor IS DISTINCT FROM row_constructor

这个构造类似于一次 <> 行比较, 但它不会对空的输入得出空。 作为替代, 任何空值都被视为与任何非空值不相等 (相异), 而任何两个空值都被视为相等 (不相异)。 因此结果要么为真要么为假, 永远不会为空。

row_constructor IS NOT DISTINCT FROM row_constructor

这个构造类似于一次 = 行比较, 但它不会对空的输入得出空。 作为替代, 任何空值都被视为与任何非空值不相等 (相异), 而任何两个空值都被视为相等 (不相异)。 因此结果将总是要么为真要么为假, 永远不会为空。

9.25.6. 复合类型比较 #

record operator record

SQL 规范要求, 如果结果取决于对两个 NULL 值、 或一个 NULL 与一个非 NULL 的比较, 那么按行比较要返回 NULL。 PostgreSQL 只有在比较两个行构造器的结果时 (如 Section 9.25.5 中那样), 或者在把一个行构造器与子查询的输出比较时 (如 Section 9.24 中那样), 才会这样做。 在比较两个组合类型值的其他上下文中, 两个 NULL 字段值被视为相等, 而 NULL 被视为大于非 NULL。 这样做是为了让组合类型具有一致的排序和索引行为。

会对两侧求值, 并按行进行比较。 当 operator 是 =、 <>、 <、 <=、 > 或 >=, 或者语义类似于其中之一时, 允许进行组合类型比较。 (具体来说, 如果一个操作符是一个 B-tree 操作符类的成员, 或者是一个 B-tree 操作符类的 = 成员的取反操作符, 那么它可以是一个行比较操作符。) 上述操作符的默认行为与 IS [ NOT ] DISTINCT FROM 针对行构造器的行为相同 (参见 Section 9.25.5)。

为了支持对包含没有默认 B-tree 操作符类的元素的行进行匹配, 以下操作符被定义用于组合类型比较: *=、 *<>、 *<、 *<=、 *> 和 *>=。 这些操作符比较两行的内部二进制表示。 即使两行在用等于操作符比较时为真, 它们也可能拥有不同的二进制表示。 在这些比较操作符下行的顺序是确定性的, 但除此之外没有任何意义。 这些操作符在内部用于物化视图, 并且可能对其他专门的用途有用, 例如复制和 B-Tree 去重 (参见 Section 65.1.4.3)。 不过, 它们并不预期被普遍用于编写查询。