CREATE OPERATOR
CREATE OPERATOR — 定义一个新的用户操作符
大纲
CREATE OPERATORname( PROCEDURE =func_name[, LEFTARG =type1] [, RIGHTARG =type2] [, COMMUTATOR =com_op] [, NEGATOR =neg_op] [, RESTRICT =res_proc] [, HASHES ] [, JOIN =join_proc] [, SORT =sort_op[, ...] ] )
输入
-
name 要定义的操作符。允许的字符见下文。
-
func_name 用于实现该操作符的函数。
-
type1 操作符左侧的类型(如果有的话)。对于右一元操作符,这个选项要省略。
-
type2 操作符右侧的类型(如果有的话)。对于左一元操作符,这个选项要省略。
-
com_op 相应的可交换操作符。
-
neg_op 相应的求反操作符。
-
res_proc 相应的限制操作符。
- HASHES
此操作符可以支持哈希连接算法。
-
join_proc 支持表连接的过程。
-
sort_op 用于排序的操作符。
输出
- →
CREATE 操作符创建成功时返回的消息。
描述
CREATE OPERATOR 定义一个新的操作符
name。定义操作符的用户将成为其所有者。
操作符的
name
是一个最多由三十二(32)个字符组成的序列,这些字符可以从下列字符中任意组合:
+ - * / < > = ~ ! @ # % ^ & | ` ? $ :
注意
操作符名称中不允许使用字母字符。这使 Postgres 能够把 SQL 输入解析成记号而无需在每个记号之间加空格。
操作符 "!=" 在输入时会被映射为 "<>",因此二者等效。
LEFTARG 和 RIGHTARG 至少必须定义一个。对于二元操作符,两者都应定义。对于右一元操作符,只应定义 LEFTARG;对于左一元操作符,只应定义 RIGHTARG。
此外,过程
func_name 必须此前已用
CREATE FUNCTION 定义,并且必须定义为接受正确数量的参数(一个或两个)。
交换子操作符的存在是为了让 Postgres 可以在需要时反转操作数的顺序。例如,面积小于操作符 <<< 会有一个交换子操作符——面积大于 >>>。于是,查询优化器就可以自由地把:
"0,0,1,1"::box >>> MYBOXES.description
转换为
MYBOXES.description <<< "0,0,1,1"::box
这使执行代码总能使用后一种表示,并在一定程度上简化了查询优化器。
假设存在一个操作符——面积等于 ===,同时也存在面积不等于 !==。求反器操作符使查询优化器可以把
NOT MYBOXES.description === "0,0,1,1"::box
转换为
MYBOXES.description !== "0,0,1,1"::box
如果给出了交换子操作符的名称,Postgres 会在目录中搜索它。如果找到了,而它自己还没有交换子,那么该交换子的条目就会被更新,把当前(新)操作符作为其交换子。这对求反器同样适用。
这样做的目的是允许定义两个互为交换子或互为求反器的操作符:第一个操作符应当不带交换子或求反器(视情况而定)先定义;定义第二个操作符时,把第一个指名为交换子或求反器,第一个就会作为副作用被更新。
后两项说明的存在是为了支持查询优化器执行连接。Postgres 总是能通过迭代替换 [WONG76] 求一个连接的值(即处理一个由返回 boolean 的操作符分隔两个元组变量的子句)。此外,Postgres 计划实现一种类似 [SHAP86] 的哈希连接算法;但它必须知道这一策略是否适用。例如,哈希连接算法可用于形如:
MYBOXES.description === MYBOXES2.description
的子句,但不能用于形如:
MYBOXES.description <<< MYBOXES2.description.
HASHES 标志向查询优化器提供所需的信息,指明哈希连接策略对所讨论的操作符是否可用。
类似地,两个排序操作符向查询优化器指明归并排序是否是可用的连接策略,以及应该用哪些操作符来排序两个操作数类。对于上面的 === 子句,优化器必须用操作符 <<< 对两个关系都排序。而另一方面,归并排序不能用于子句:
MYBOXES.description <<< MYBOXES2.description
如果将来发现其他连接策略切实可行,Postgres 会修改优化器和运行时系统来使用它们,并在定义操作符时要求额外的说明。幸运的是,研究界并不经常发明新的连接策略,而用户自定义连接策略带来的额外通用性被认为不值得为之增加复杂度。
说明的最后两项是为了让查询优化器能够估算结果大小。如果限定条件中出现了形如:
MYBOXES.description <<< "0,0,1,1"::box
的子句,那么
Postgres
可能必须估算
MYBOXES
中满足该子句的实例比例。函数
res_proc
必须是一个已注册的函数(即已用
define function(l) 定义),它接受一个正确数据类型的参数并返回一个浮点数。查询优化器只需调用该函数,传入参数
"0,0,1,1",再把结果乘以关系的大小,就得到想要的预期实例数。
类似地,当操作符的两个操作数都含有实例变量时,查询优化器必须估算所得连接的大小。函数 join_proc 会返回另一个浮点数,把它乘以所涉及两个类的基数,就得到想要的预期结果大小。
函数
my_procedure_1 (MYBOXES.description, "0,0,1,1"::box)
与操作符
MYBOXES.description === "0,0,1,1"::box
的区别在于:Postgres 会尝试优化操作符,并可在涉及操作符时决定使用索引来限制搜索空间。但系统不会尝试优化函数,函数是靠蛮力执行的。此外,函数可以有任意数量的参数,而操作符只能有一个或两个。
注意
更多信息参见
PostgreSQL 用户指南中关于操作符的章节。参见
DROP OPERATOR 以从数据库中删除用户定义的操作符。
用法
下面的命令为 BOX 数据类型定义一个新的操作符——面积相等。
CREATE OPERATOR === (
LEFTARG = box,
RIGHTARG = box,
PROCEDURE = area_equal_procedure,
COMMUTATOR = ===,
NEGATOR = !==,
RESTRICT = area_restriction_procedure,
HASHES,
JOIN = area-join-procedure,
SORT = <<<, <<<)
兼容性
CREATE OPERATOR 是 Postgres 的扩展。
SQL92
在 SQL92 中没有 CREATE OPERATOR 语句。