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 组合时的规则。

提示: 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 组合时的规则。

SOMEANY的同意词。

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

两边都是一个第 4.2.13 节所述的行构造器; 两个行的字段数必须相同。两边都被计算并且逐行比较。目前,行构造器比较的 operator操作符仅允许为 =, <>, <, <=, >>=。 每个行元素必须是有缺省B-tree操作符类的类型,否则尝试比较可能会产生错误。

注意: 如果比较使用较早的字段解决,那么与元素的数量或类型相关的错误可能不会发生。

=<>与其它操作符稍有区别。如果两行对应的元素全都非空且相等, 那么这两行就被认为是相等的;如果两行对应的元素中有任意一对非空且不等, 那么这两行就被认为是不等的;否则这两行的比较结果是未知(NULL)。

对于 <, <=, >, >=操作符, 行中的元素将按照从左到右的顺序依次进行比较,直到遇见一对不相等的元素或者一对 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_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.23.6. 复合类型比较

record operator record

如果结果依赖于比较两个NULL值或一个NULL值和一个非NULL值,SQL 规范要求逐行比较返回 NULL。 PostgreSQL仅当比较两个行构造的结果(就像第 9.23.5 节 中描述的那样)或一个行构造器和子查询的输出时这样做 (就像第 9.22 节描述的那样)。在其它情况下,两个复合类型的值进行比较, 认为两个NULL字段值是相等的,并且NULL大于非NULL。这是必要的,如此才能有一致的排序和复合类型的索引行为。

每一方都要评估并且它们是逐行比较的。仅在operator=<><<=>>=,或具有相似语义的操作符时允许比较复合类型。 (具体来说,一个操作符可以是一个行比较操作符,如果它是B-tree操作符类的一员, 或者是B-tree操作符类=成员的否定。)以上操作符在行构造器上的缺省行为和 IS [ NOT ] DISTINCT FROM是相同的 (参阅第 9.23.5 节)。

为了支持包含没有缺省B-tree操作符类的元素的行匹配,为复合类型比较定义了下列操作符: *=*<>*<*<=*>*>=。这些操作符比较两行的内部二进制表示。 两行可能有不同的二进制表示,即使用等号操作符比较两行返回真。 这些比较操作符下的行排序是动态的,但是没什么意义。 这些操作符内部的用于物化视图,并且可能对于其他特殊用途, 比如替换有用,但是并不打算用于普通的写查询。