9.24. 行和数组比较 #
本节描述几个特殊的结构,用于在值的组之间进行多重比较。这些形式语法上和前面一节的子查询形式相关,但是不涉及子查询。涉及数组子表达式的形式是 PostgreSQL 的扩展;其余形式是 SQL 兼容的。本节介绍的所有表达式形式都返回布尔(Boolean)结果(真/假)。
9.24.1. IN #
expressionIN (value[, ...])
右侧是一个用圆括号括起来的表达式列表。如果左侧表达式的结果等于右侧任一表达式的结果,则结果为“真”。这等价于以下写法:
expression=value1ORexpression=value2OR ...
请注意如果左手边表达式得到空值,或者没有相等的右手边值并且至少有一个右手边的表达式得到空值,那么 IN 结构的结果将为空值,而不是假。这符合 SQL 处理空值的布尔组合的一般规则。
9.24.2. NOT IN #
expressionNOT IN (value[, ...])
右侧是一个用圆括号括起来的表达式列表。如果左侧表达式的结果与右侧所有表达式的结果都不相等,则结果为“真”。这等价于以下写法:
expression<>value1ANDexpression<>value2AND ...
请注意如果左手边表达式得到空值,或者没有相等的右手边值并且至少有一个右手边的表达式得到空值,那么 NOT IN 结构的结果将为空值,而不是我们可能天真地认为的真值。这符合 SQL 处理空值的布尔组合的一般规则。
提示
x NOT IN y 在所有情况下都等效于 NOT (x IN y)。但是,在处理空值的时候,用 NOT IN 比用 IN 更可能迷惑新手。最好尽可能用正逻辑来表达你的条件。
9.24.3. ANY/SOME(数组)#
expressionoperatorANY (array expression)expressionoperatorSOME (array expression)
右侧是一个用括号括起来的表达式,它必须产生一个数组值。左侧表达式会被求值,并使用给定的 operator 与数组的每个元素进行比较,该操作符必须产生布尔结果。如果得到了任何真值结果,那么 ANY 的结果是“真”。如果没有找到真值结果(包括数组有零个元素的情况),那么结果是“假”。
如果数组表达式得到的是 null 数组,那么 ANY 的结果将为 null。如果左手边的表达式得到 null,ANY 通常也为 null(尽管非严格比较操作符可能得到不同结果)。另外,如果右手边数组包含任何 null 元素,并且没有得到真值比较结果,那么 ANY 的结果将为 null 而不是假(同样假设这里使用的是严格比较操作符)。这符合 SQL 处理 null 值布尔组合的一般规则。
SOME 是 ANY 的同义词。
9.24.4. ALL(数组)#
expressionoperatorALL (array expression)
右侧是一个用括号括起来的表达式,它必须产生一个数组值。左侧表达式会被求值,并使用给定的 operator 与数组的每个元素进行比较,该操作符必须产生布尔结果。如果所有比较都得到真值结果,那么 ALL 的结果是“真”(包括数组有零个元素的情况)。如果有任何假值结果,那么结果是“假”。
如果数组表达式得到的是 null 数组,那么 ALL 的结果将为 null。如果左手边的表达式得到 null,ALL 通常也为 null(尽管非严格比较操作符可能得到不同结果)。另外,如果右手边数组包含任何 null 元素,并且没有得到假值比较结果,那么 ALL 的结果将为 null 而不是真(同样假设这里使用的是严格比较操作符)。这符合 SQL 处理 null 值布尔组合的一般规则。
9.24.5. 行构造器比较 #
row_constructoroperatorrow_constructor
两侧都是行构造器,如第 4.2.13 节所述。两个行构造器必须具有相同数量的字段。给定的 operator 应用于每一对对应字段。(由于字段可能具有不同的类型,因此可能为各对字段选择不同的具体操作符。)所选操作符必须是某个 B-树操作符类的成员,或者是 B-树操作符类中=成员的否定操作符。这意味着只有当 operator 是=、<>、<、<=、>、>=,或具有与这些操作符类似的语义时,才可以进行行构造器比较。
=和<> 情况略有不同。如果两行的所有对应成员都是非空且相等则这两行被认为相等;如果任何对应成员是非空但是不相等则这两行不相等;否则行比较的结果为未知(空值)。
对于<、<=、> 和>=这几种情况,会从左到右比较各行元素,一旦找到一对不相等或含有 null 的元素就立即停止。如果这对元素中的任意一个为 null,那么行比较的结果就是未知(null);否则,这对元素的比较结果决定整个行比较的结果。例如,ROW(1,2,NULL) < ROW(1,3,0) 的结果为真,而不是 null,因为第三对元素并不会被考虑。
注意
在 PostgreSQL 8.2 之前,<、<=、> 和>=这几种情况并不是按照 SQL 规范处理的。像 ROW(a,b) < ROW(c,d) 这样的比较会被实现为 a < c AND b < d,而正确行为应当等价于 a < c OR (a = c AND b < d)。
row_constructorIS DISTINCT FROMrow_constructor
这个结构与<> 行比较相似,但是它对于空值输入不会得到空值。任何空值被认为和任何非空值不相等(有区别),并且任意两个空值被认为相等(无区别)。因此结果将总是为真或为假,永远不会是空值。
row_constructorIS NOT DISTINCT FROMrow_constructor
这个结构与=行比较相似,但是它对于空值输入不会得到空值。任何空值被认为和任何非空值不相等(有区别),并且任意两个空值被认为相等(无区别)。因此结果将总是为真或为假,永远不会是空值。
9.24.6. 复合类型比较 #
recordoperatorrecord
SQL 规范要求在结果依赖于比较两个 NULL 值或者一个 NULL 与一个非 NULL 时行比较返回 NULL。PostgreSQL 只有在比较两个行构造器(如第 9.24.5 节)的结果或者比较一个行构造器与一个子查询的输出时才这样做(如第 9.23 节中所述)。在其他比较两个复合类型值的环境中,两个 NULL 字段值被认为相等,并且一个 NULL 被认为大于一个非 NULL。为了得到复合类型的一致的排序和索引行为,这样做是必要的。
对两侧分别求值后,按行进行比较。当 operator 是
=、<>、<、<=、> 或者
>=时或者具有与这些类似的语义时,允许复合类型的比较(更准确地说,如果一个操作符是一个 B-树操作符类的成员,或者是一个 B-树操作符类的=成员的否定操作符,它就可以是一个行比较操作符)。上述操作符的默认行为与用于行构造器(见第 9.24.5 节)的 IS [ NOT ] DISTINCT FROM 相同。
为了支持包含无默认 B-树操作符类的元素的行匹配,为复合类型比较定义了下列操作符:*=、*<>、*<、*<=、*> 以及
*>=。这些操作符比较两行的内部二进制表示。即使两行用相等操作符的比较为真,两行也可能具有不同的二进制表示。使用这些比较操作符得到的行排序是确定的,但除此之外没有其他意义。这些操作符在内部被用于物化视图并且可能对其他如复制和 B-树去重(参见第 64.4.3 节)之类的特殊功能有用,但是它们并不打算用在书写查询这类普通用途中。
报告文档问题
阅读 上游文档. 通过 PostgreSQL 文档反馈表单.