9.2. 比较函数和运算符 #

如表 9.1所示,提供了常规的比较运算符。

表 9.1. 比较运算符

运算符 描述
数据类型 < 数据类型 → boolean 小于
数据类型 > 数据类型 → boolean 大于
数据类型 <= 数据类型 → boolean 小于等于
数据类型 >= 数据类型 → boolean 大于等于
数据类型 = 数据类型 → boolean 等于
数据类型 <> 数据类型 → boolean 不等于
数据类型 != 数据类型 → boolean 不等于

注意

<> 是标准的 SQL 表示“不等于”的记法。!= 是一个别名,它在解析的早期阶段被转换成 <>。因此,不可能实现具有不同行为的 != 和 <> 运算符。

这些比较运算符可用于所有具有自然顺序的内置数据类型,包括数值、字符串和日期/时间类型。此外,如果数组、复合类型和范围的组成数据类型是可比较的,则它们也可以进行比较。

通常也可以比较相关数据类型的值;例如,integer > bigint 可以工作。这种类型的一些情况是通过“交叉类型”比较运算符直接实现的,但如果没有此类运算符,解析器将把不那么通用的类型强制转换为更通用的类型,并应用后者(更通用类型)的比较运算符。

如上所示,所有比较运算符都是返回 boolean 类型值的二元运算符。因此,像 1 < 2 < 3 这样的表达式无效(因为没有 < 运算符可以将布尔值与 3 进行比较)。使用下面显示的 BETWEEN 谓词来执行范围测试。

还有一些比较谓词,如表 9.2所示。它们的作用与运算符非常相似,但具有 SQL 标准强制的特殊语法。

表 9.2. 比较谓词

谓词

描述

示例

数据类型 BETWEEN 数据类型 AND 数据类型 → boolean

在…之间(包含范围的端点)。

2 BETWEEN 1 AND 3 → t

2 BETWEEN 3 AND 1 → f

数据类型 NOT BETWEEN 数据类型 AND 数据类型 → boolean

不在…之间(BETWEEN 的否定)。

2 NOT BETWEEN 1 AND 3 → f

数据类型 BETWEEN SYMMETRIC 数据类型 AND 数据类型 → boolean

在…之间,对两个端点值进行排序后。

2 BETWEEN SYMMETRIC 3 AND 1 → t

数据类型 NOT BETWEEN SYMMETRIC 数据类型 AND 数据类型 → boolean

不在…之间,对两个端点值进行排序后。

2 NOT BETWEEN SYMMETRIC 3 AND 1 → f

数据类型 IS DISTINCT FROM 数据类型 → boolean

不等于,将 NULL 视为可比较的值。

1 IS DISTINCT FROM NULL → t(而不是 NULL)

NULL IS DISTINCT FROM NULL → f(而不是 NULL)

数据类型 IS NOT DISTINCT FROM 数据类型 → boolean

等于,将 NULL 视为可比较的值。

1 IS NOT DISTINCT FROM NULL → f(而不是 NULL)

NULL IS NOT DISTINCT FROM NULL → t(而不是 NULL)

数据类型 IS NULL → boolean

测试值是否为 NULL。

1.5 IS NULL → f

数据类型 IS NOT NULL → boolean

测试值是否不为 NULL。

'null' IS NOT NULL → t

数据类型 ISNULL → boolean

测试值是否为 NULL(非标准语法)。

数据类型 NOTNULL → boolean

测试值是否不为 NULL(非标准语法)。

boolean IS TRUE → boolean

测试布尔表达式是否结果为 TRUE。

true IS TRUE → t

NULL::boolean IS TRUE → f(而不是 NULL)

boolean IS NOT TRUE → boolean

测试布尔表达式是否结果为 FALSE 或 UNKNOWN。

true IS NOT TRUE → f

NULL::boolean IS NOT TRUE → t(而不是 NULL)

boolean IS FALSE → boolean

测试布尔表达式是否结果为 FALSE。

true IS FALSE → f

NULL::boolean IS FALSE → f(而不是 NULL)

boolean IS NOT FALSE → boolean

测试布尔表达式是否结果为 TRUE 或 UNKNOWN。

true IS NOT FALSE → t

NULL::boolean IS NOT FALSE → t(而不是 NULL)

boolean IS UNKNOWN → boolean

测试布尔表达式是否结果为 UNKNOWN。

true IS UNKNOWN → f

NULL::boolean IS UNKNOWN → t(而不是 NULL)

boolean IS NOT UNKNOWN → boolean

测试布尔表达式是否结果为 TRUE 或 FALSE。

true IS NOT UNKNOWN → t

NULL::boolean IS NOT UNKNOWN → f(而不是 NULL)


BETWEEN 谓词简化了范围测试

a BETWEEN x AND y

等同于

a >= x AND a <= y

BETWEEN 将端点值视为包含在范围内。 BETWEEN SYMMETRIC 类似于 BETWEEN,只是它不要求 AND 左侧的参数小于或等于右侧的参数。如果不是,则这两个参数会自动交换,因此总会隐含一个非空范围。

BETWEEN 的各种变体是基于普通比较运算符实现的,因此它们适用于任何可比较的数据类型。

注意

BETWEEN 语法中使用 AND 会与 AND 作为逻辑运算符的使用产生歧义。为解决此问题,BETWEEN 子句的第二个参数只允许有限类型的表达式。如果您需要在 BETWEEN 中编写更复杂的子表达式,请将子表达式括在括号中。

普通比较运算符在任一输入为 NULL 时会产生 NULL(表示“未知”),而不是 TRUE 或 FALSE。例如,7 = NULL 会产生 NULL,7 <> NULL 也是如此。当这种行为不合适时,请使用 IS [ NOT ] DISTINCT FROM 谓词。

a IS DISTINCT FROM b
a IS NOT DISTINCT FROM b

对于非 NULL 输入,IS DISTINCT FROM 与 <> 运算符相同。但是,如果两个输入都为 NULL,它将返回 FALSE;如果只有一个输入为 NULL,它将返回 TRUE。类似地,对于非 NULL 输入,IS NOT DISTINCT FROM 与 = 相同,但当两个输入都为 NULL 时它返回 TRUE,当只有一个输入为 NULL 时它返回 FALSE。因此,这些谓词有效地像 NULL 是普通数据值一样进行处理,而不是“未知”。

要检查一个值是否为 NULL 或非 NULL,请使用谓词

expression IS NULL
expression IS NOT NULL

或等效的、但非标准的谓词

expression ISNULL
expression NOTNULL

请不要写 表达式 = NULL,因为 NULL 不“等于”NULL。(NULL 值代表一个未知值,无法确定两个未知值是否相等。)

提示

某些应用程序可能期望 表达式 = NULL 在 表达式 计算为 NULL 值时返回 TRUE。强烈建议修改这些应用程序以符合 SQL 标准。但是,如果无法做到这一点,可以使用 transform_null_equals 配置变量。如果启用,PostgreSQL 会将 x = NULL 子句转换为 x IS NULL。

如果 表达式 是行值,则当行表达式本身为 NULL 或行中的所有字段都为 NULL 时,IS NULL 为 TRUE;当行表达式非 NULL 且行中的所有字段都非 NULL 时,IS NOT NULL 为 TRUE。由于这种行为,对于行值表达式,IS NULL 和 IS NOT NULL 不总是返回相反的结果;特别地,包含 NULL 和非 NULL 字段的行值表达式对这两种测试都返回 FALSE。例如

SELECT ROW(1,2.5,'this is a test') = ROW(1, 3, 'not the same');

SELECT ROW(table.*) IS NULL FROM table;  -- detect all-null rows

SELECT ROW(table.*) IS NOT NULL FROM table;  -- detect all-non-null rows

SELECT NOT(ROW(table.*) IS NOT NULL) FROM TABLE; -- detect at least one null in rows

在某些情况下,最好使用 行 IS DISTINCT FROM NULL 或 行 IS NOT DISTINCT FROM NULL,它将简单地检查整个行值是否为 NULL,而无需对行字段进行任何额外测试。

布尔值也可以使用谓词进行测试

boolean_expression IS TRUE
boolean_expression IS NOT TRUE
boolean_expression IS FALSE
boolean_expression IS NOT FALSE
boolean_expression IS UNKNOWN
boolean_expression IS NOT UNKNOWN

即使操作数为 NULL,这些谓词也总是返回 TRUE 或 FALSE,绝不会返回 NULL 值。NULL 输入被视为逻辑值“未知”。请注意,IS UNKNOWN 和 IS NOT UNKNOWN 在功能上分别等同于 IS NULL 和 IS NOT NULL,只是输入表达式必须是布尔类型。

一些与比较相关的函数也可用,如表 9.3所示。

表 9.3. 比较函数

函数

描述

示例

num_nonnulls ( VARIADIC "any" ) → integer

返回非 NULL 参数的数量。

num_nonnulls(1, NULL, 2) → 2

num_nulls ( VARIADIC "any" ) → integer

返回 NULL 参数的数量。

num_nulls(1, NULL, 2) → 1