CREATE OPERATOR

定义一个新运算符。

概要

CREATE OPERATOR <name> ( 
       { FUNCTION | PROCEDURE } = <function\_name>
       [, LEFTARG = <left_type>] [, RIGHTARG = <right_type>]
       [, COMMUTATOR = <com_op>] [, NEGATOR = <neg_op>]
       [, RESTRICT = <res_proc>] [, JOIN = <join_proc>]
       [, HASHES] [, MERGES] )

描述

CREATE OPERATOR 用于定义新运算符。定义运算符的用户将成为其所有者。若指定模式名称,则运算符将在该模式下创建;否则创建于当前模式。

运算符名称由以下字符序列组成,长度不超过 NAMEDATALEN-1(默认63个字符):

      • / < > = ~ ! @ # % ^ & | ` ? .

名称选择需遵守以下限制:

-- and /* cannot appear anywhere in an operator name, since they will be taken as the start of a comment.

A multicharacter operator name cannot end in + or -, unless the name also contains at least one of these characters: ~ ! @ # % ^ & | ` ?

For example, @- is an allowed operator name, but *- is not. This restriction allows Database to parse SQL-compliant commands without requiring spaces between tokens.

The use of => as an operator name is deprecated. It may be disallowed altogether in a future release.

运算符 != 在输入时映射为 <>,因此这两个名称始终等价。

LEFTARG 和 RIGHTARG 中至少需定义其中一个。对于二元运算符,两者都必须定义。对于右单项运算符,仅需定义 LEFTARG;而对于左单项运算符,仅需定义 RIGHTARG。

注意:右一元运算符(也称为后缀运算符)已被弃用,可能在未来的数据库版本中被移除。

函数名 function 必须事先使用 CREATE FUNCTION 定义,必须为 IMMUTABLE 类型,且必须定义为接受指定类型且数量正确(一个或两个)的参数。

在 CREATE OPERATOR 的语法中,FUNCTION 和 PROCEDURE 关键字具有等效性,但被引用的对象必须是函数而非过程。此处使用 PROCEDURE 关键字属于历史遗留用法,现已弃用。

其余子句指定可选的运算符优化子句,其具体含义详见 PostgreSQL 运算符优化信息文档。

要创建运算符,必须对参数类型和返回类型拥有USAGE权限,并对底层函数拥有EXECUTE权限。若指定了交换运算符或取反运算符,则必须拥有这些运算符的所有权。

参数

  • name
    • 要定义的运算符名称(可选带模式限定)。允许使用的字符请参见上文描述。名称可带模式限定,例如 CREATE OPERATOR myschema.+ (...)。若未指定模式,则运算符创建于当前模式中。同一模式下,操作不同数据类型的两个运算符可使用相同名称,此称为重载。
  • function_name
    • 用于实现此运算符的函数(必须是IMMUTABLE函数)。
  • left_type
    • 操作符左操作数的数据类型(如有)。对于左一元操作符,此选项将被省略。
  • right_type
    • 操作符右操作数的数据类型(如有)。对于右单项操作符,此选项将被省略。
  • com_op
    • 该算符的交换子。可选的COMMUTATOR子句指定一个算符,该算符是正在定义的算符的交换子。若对于所有可能的输入值 x、y,均满足 (x A y) 等于 (y B x),则称运算符 A 是运算符 B 的交换子。需注意此时 B 也是 A 的交换子。例如,特定数据类型的 < 和 > 运算符通常互为交换子,而 + 运算符通常与自身交换。但 - 运算符通常与任何运算符都不交换。可交换运算符的左操作数类型与其交换子的右操作数类型相同,反之亦然。因此在COMMUTATOR子句中只需提供交换子运算符的名称即可。
  • neg_op
    • 该运算符的否定运算符。可选的NEGATOR子句指定一个作为被定义运算符否定运算符的运算符。当两个运算符均返回布尔值结果,且对于所有可能的输入x、y,(x A y)等于NOT (x B y)时,我们称运算符A是运算符B的否定运算符。需注意B同时也是A的否定运算符。例如<>=对大多数数据类型构成否定运算符对。否定运算符的左右操作数类型必须与待定义运算符一致,因此NEGATOR子句仅需指定运算符名称即可。
  • res_proc
    • 此运算符的限制选择性估计函数。可选参数 RESTRICT 为该运算符指定限制选择性估计函数。(请注意此处为函数名称而非运算符名称。)RESTRICT 子句仅适用于返回布尔值的二元运算符。
  • join_proc
    • 此运算符的连接选择性估计函数。可选的 JOIN 子句为该运算符指定连接选择性估计函数。(请注意,此处指函数名称而非运算符名称。)JOIN 子句仅适用于返回布尔值的二元运算符。
  • HASHES
    • 表示该运算符支持哈希连接。可选的HASHES子句告知系统,允许对基于此运算符的连接使用哈希连接方法。HASHES仅适用于返回布尔值的二元运算符。哈希连接运算符仅对左值与右值经哈希计算后得到相同哈希码的值对返回真值。若两个值被放入不同哈希桶,连接操作将永远不会比较它们,隐含地假定连接运算符的结果必须为假。因此,对于不表示相等的运算符,指定HASHES毫无意义。
  • MERGES
    • 表示该运算符支持合并连接。若存在MERGES子句,则告知系统允许对基于此运算符的连接操作使用合并连接方法。MERGES仅适用于返回布尔值的二元运算符,且在实际应用中该运算符必须表示某种数据类型或数据类型对之间的相等关系。 要在 com_op 或其他可选参数中指定带模式限定符的运算符名称,请使用 OPERATOR() 语法,例如:
      COMMUTATOR = OPERATOR(myschema.===) ,

      注意

      有关更多信息,请参阅 PostgreSQL 文档中的用户定义运算符。

用于实现运算符的任何函数都必须定义为 IMMUTABLE。

无法在 CREATE OPERATOR 中指定运算符的词法优先级,因为解析器的优先级行为是硬编码的。有关优先级的详细信息,请参阅 PostgreSQL 文档中的运算符优先级。

使用 DROP OPERATOR 从数据库中删除用户定义的运算符。使用 ALTER OPERATOR 修改数据库中的运算符。

示例

以下命令为数据类型 box 定义了一个新运算符 area-equality:

CREATE OPERATOR === (
    LEFTARG = box,
    RIGHTARG = box,
    FUNCTION = area_equal_function,
    COMMUTATOR = ===,
    NEGATOR = !==,
    RESTRICT = area_restriction_function,
    JOIN = area_join_function,
    HASHES, MERGES
);

以下示例创建了一个用于加法运算的复数运算符。该示例假设我们已经定义了复数类型。首先定义执行运算的函数,然后定义运算符:

CREATE FUNCTION complex_add(complex, complex)
    RETURNS complex
    AS 'filename', 'complex_add'
    LANGUAGE C IMMUTABLE STRICT;
CREATE OPERATOR + (
    leftarg = complex,
    rightarg = complex,
    procedure = complex_add,
    commutator = +
);

要在查询中使用此运算符:

SELECT (a + b) AS c FROM test_complex;

兼容性

CREATE OPERATOR 是对 SQL 标准的数据库扩展。SQL 标准本身并不支持用户自定义运算符。

另见

CREATE FUNCTION, CREATE TYPE, ALTER OPERATOR, CREATE OPERATOR CLASS, DROP OPERATOR