9.24 行和数组比较#
本节介绍了用于在值组之间进行多重比较的几种专门结构。这些形式在语法上与上一节的子查询形式相关,但并不涉及子查询。涉及数组子表达式的形式是PostgreSQL扩展;其余形式符合SQL。本节中记录的所有表达式形式都返回布尔值(真/假)结果。
9.24.1.IN
#
expression IN (value [, ...])
右侧是一个带括号的表达式列表。如果左侧表达式的结果等于任何右侧表达式,则结果为“true”。这是以下内容的简写符号
expression = value1
OR
expression = value2
OR
...
请注意,如果左侧表达式产生 null,或者如果没有相等的右侧值且至少有一个右侧表达式产生 null,则IN
结构的结果将为 null,而不是 false。这符合 SQL 对 null 值的布尔组合的常规规则。
9.24.2.NOT IN
#
expression NOT IN (value [, ...])
右侧是一个带括号的表达式列表。如果左侧表达式的结果不等于所有右侧表达式,则结果为“true”。这是以下内容的简写符号
expression <> value1
AND
expression <> value2
AND
...
请注意,如果左侧表达式产生 null,或者如果没有相等的右侧值且至少有一个右侧表达式产生 null,则NOT IN
结构的结果将为 null,而不是人们可能天真地期望的 true。这符合 SQL 对 null 值的布尔组合的常规规则。
提示
x NOT IN y
在所有情况下都等效于NOT (x IN y)
。但是,在使用NOT IN
时,null 值比在使用IN
时更容易让新手绊倒。如果可能,最好以肯定的方式表达你的条件。
9.24.3.ANY
/SOME
(数组)#
expression operator ANY (array expression)
expression operator SOME (array expression)
右侧是一个带括号的表达式,它必须产生一个数组值。对左侧表达式求值,并使用给定的*operator
*将其与数组的每个元素进行比较,该运算符必须产生一个布尔结果。如果获得任何 true 结果,则ANY
的结果为“true”。如果没有找到 true 结果(包括数组元素为零的情况),则结果为“false”。
如果数组表达式产生一个 null 数组,则ANY
的结果将为 null。如果左侧表达式产生 null,则ANY
的结果通常为 null(尽管非严格比较运算符可能会产生不同的结果)。此外,如果右侧数组包含任何 null 元素且未获得 true 比较结果,则ANY
的结果将为 null,而不是 false(再次假设为严格比较运算符)。这符合 SQL 对 null 值的布尔组合的常规规则。
SOME
是ANY
的同义词。
9.24.4.ALL
(数组)#
expression operator ALL (array expression)
右侧是一个括号表达式,它必须产生一个数组值。对左侧表达式进行求值,并使用给定的*operator
*(它必须产生一个布尔结果)将其与数组的每个元素进行比较。如果所有比较都产生真(包括数组没有元素的情况),则ALL
的结果为“true”。如果找到任何错误结果,则结果为“false”。
如果数组表达式产生一个空数组,则ALL
的结果将为空。如果左侧表达式产生空,则ALL
的结果通常为空(尽管非严格比较运算符可能会产生不同的结果)。此外,如果右侧数组包含任何空元素并且没有获得错误的比较结果,则ALL
的结果将为空,而不是真(再次假设一个严格的比较运算符)。这符合 SQL 关于空值的布尔组合的正常规则。
9.24.5. 行构造器比较#
row_constructor operator row_constructor
每一侧都是一个行构造器,如第 4.2.13 节所述。两个行构造器必须具有相同数量的字段。给定的*operator
应用于每对对应的字段。(由于字段的类型可能不同,这意味着可以为每对选择不同的特定运算符。)所有选定的运算符必须是某个 B 树运算符类的成员,或者是一个 B 树运算符类的=
成员的否定,这意味着只有当operator
*是=
、<>
、<
、<=
、>
或>=
,或具有与其中一个类似的语义时,行构造器比较才有可能。
=
和<>
情况与其他情况的工作方式略有不同。如果所有对应的成员都为非空且相等,则两行被认为相等;如果任何对应的成员为非空且不相等,则这两行不相等;否则,行比较的结果未知(空)。
对于<
、<=
、>
和>=
情况,行元素从左到右进行比较,一旦找到不匹配或空元素对便停止。如果该元素对中的任一元素为空,则行比较结果未知(空);否则,该元素对的比较决定结果。例如,ROW(1,2,NULL) < ROW(1,3,0)
的结果为真,而非空,因为第三对元素未被考虑。
row_constructor IS DISTINCT FROM row_constructor
此构造类似于<>
行比较,但它不会为 null 输入生成 null。相反,任何 null 值都被视为不等于(不同于)任何非 null 值,任何两个 null 都被视为相等(不不同)。因此,结果将始终为真或假,绝不会为 null。
row_constructor IS NOT DISTINCT FROM row_constructor
此构造类似于=
行比较,但它不会为 null 输入生成 null。相反,任何 null 值都被视为不等于(不同于)任何非 null 值,任何两个 null 都被视为相等(不不同)。因此,结果将始终为真或假,绝不会为 null。
9.24.6. 复合类型比较#
record operator record
SQL 规范要求行比较在结果取决于比较两个 NULL 值或一个 NULL 值和一个非 NULL 值时返回 NULL。PostgreSQL仅在比较两个行构造函数的结果(如第 9.24.5 节所述)或将行构造函数与子查询的输出进行比较(如第 9.23 节所述)时才执行此操作。在比较两个复合类型值的其他情况下,两个 NULL 字段值被视为相等,而 NULL 被视为大于非 NULL。为了对复合类型具有持续的排序和索引行为,这是必需的。
对每一侧进行评估,并逐行进行比较。当*operator
*为=
、<>
、<
、<=
、>
或>=
,或具有与其中一个类似的语义时,允许复合类型比较。(具体来说,如果一个运算符是 B 树运算符类的成员,或者是否定 B 树运算符类的=
成员,则该运算符可以是行比较运算符。)上述运算符的默认行为与行构造函数的IS [ NOT ] DISTINCT FROM
相同(参见第 9.24.5 节)。
为了支持匹配包括不带默认 B 树操作符类的元素的行,针对复合类型比较定义了以下操作符:*=
、*<>
、*<
、*<=
、*>
和*>=
。这些操作符比较两行的内部二进制表示形式。即使使用相等操作符比较两行时为真,两行也可能具有不同的二进制表示形式。这些比较操作符下的行排序是确定性的,但没有其他含义。这些操作符在内部用于物化视图,并且可能对其他专门用途(例如复制和 B 树重复数据删除(请参阅第 67.4.3 节))有用。不过,它们并不旨在普遍用于编写查询。