CREATE OPERATOR
CREATE OPERATOR — 定义一个新的操作符
大纲
CREATE OPERATORname( PROCEDURE =func_name[, LEFTARG =lefttype] [, RIGHTARG =righttype] [, COMMUTATOR =com_op] [, NEGATOR =neg_op] [, RESTRICT =res_proc] [, JOIN =join_proc] [, HASHES ] [, MERGES ] [, SORT1 =left_sort_op] [, SORT2 =right_sort_op] [, LTCMP =less_than_op] [, GTCMP =greater_than_op] )
输入
name要定义的操作符。允许的字符见下文。名称可以带模式限定,例如
CREATE OPERATOR myschema.+ (...)。func_name用于实现该操作符的函数。
lefttype操作符左参数的类型(如果有的话)。对于左一元操作符,这个选项要省略。
righttype操作符右参数的类型(如果有的话)。对于右一元操作符,这个选项要省略。
com_op该操作符的交换子。
neg_op该操作符的求反器。
res_proc该操作符的限制选择度估计函数。
join_proc该操作符的连接选择度估算函数。
- HASHES
表示该操作符可以支持哈希连接。
- MERGES
表示该操作符可以支持归并连接。
left_sort_op如果该操作符能支持归并连接,则为对该操作符左手数据类型排序的小于操作符。
right_sort_op如果该操作符能支持归并连接,则为对该操作符右手数据类型排序的小于操作符。
less_than_op如果该操作符能支持归并连接,则为比较该操作符输入数据类型的小于操作符。
greater_than_op如果该操作符能支持归并连接,则为比较该操作符输入数据类型的大于操作符。
输出
CREATE OPERATOR操作符创建成功时返回的消息。
描述
CREATE OPERATOR 定义一个新的操作符
name。定义操作符的用户将成为其所有者。
如果给出了模式名称,那么操作符会创建在指定的模式中。否则它创建在当前模式中(即搜索路径最前面的那个;见
CURRENT_SCHEMA())。
同一模式中的两个操作符如果作用于不同的数据类型,就可以同名。这称为重载。当出现歧义时,系统会尝试根据实际的输入数据类型选出预期的操作符。
操作符的
name
是一个最多由
NAMEDATALEN-1(默认
63)个字符组成的序列,这些字符取自下面的列表:
+ - * / < > = ~ ! @ # % ^ & | ` ? $
对名称的选择有若干限制:
$不能定义为单字符操作符,尽管它可以是多字符操作符名称的一部分。--和/*不能出现在操作符名称的任何位置,因为它们会被视为注释的开始。多字符操作符名称不能以
+或-结尾,除非该名称中还至少包含下列字符之一:~ ! @ # % ^ & | ` ? $
例如,
@-是允许的操作符名称,而*-不是。这一限制使 PostgreSQL 能够解析符合 SQL 的查询而无需在记号之间加空格。
注意
使用非
SQL 标准的操作符名称时,你通常需要用空格分隔相邻的操作符以避免歧义。例如,如果你定义了一个名为
@ 的左一元操作符,你就不能写
X*@Y;你必须写
X* @Y,以确保
PostgreSQL 把它读成两个操作符名而不是一个。
输入!=时会被映射为<>,因此这两个名称始终等效。
LEFTARG 和
RIGHTARG
至少必须定义一个。对于二元操作符,两者都应定义。对于右一元操作符,只应定义
LEFTARG;对于左一元操作符,只应定义
RIGHTARG。
过程
func_name 必须此前已用
CREATE FUNCTION 定义,并且必须定义为接受正确数量的参数(一个或两个),类型为所指明的类型。
如果存在交换子操作符,就应当把它指出来,这样 PostgreSQL 就可以在需要时反转操作数的顺序。例如,面积小于操作符 <<< 大概会有一个交换子操作符——面积大于 >>>。于是,查询优化器就可以自由地把:
box '((0,0), (1,1))' >>> MYBOXES.description
转换为
MYBOXES.description <<< box '((0,0), (1,1))'
这使执行代码总能使用后一种表示,并在一定程度上简化了查询优化器。
类似地,如果存在求反器操作符,也应当把它指出来。假设存在一个操作符——面积等于 ===,同时也存在面积不等于 !==。求反器链接使查询优化器可以把
NOT MYBOXES.description === box '((0,0), (1,1))'
化简为
MYBOXES.description !== box '((0,0), (1,1))'
如果给出了交换子操作符的名称,PostgreSQL
会在目录中搜索它。如果找到了,而它自己还没有交换子,那么该交换子的条目就会被更新,把新创建的操作符作为其交换子。这对求反器同样适用。这样做的目的是允许定义两个互为交换子或互为求反器的操作符:第一个操作符应当不带交换子或求反器(视情况而定)先定义;定义第二个操作符时,把第一个指名为交换子或求反器,第一个就会作为副作用被更新。(从
PostgreSQL 6.5
起,让两个操作符互相引用也可以。)
HASHES、MERGES、SORT1、SORT2、LTCMP 和
GTCMP 选项的存在是为了支持查询优化器执行连接。PostgreSQL
总是能通过迭代替换求一个连接的值(即处理一个由返回
boolean
的操作符分隔两个元组变量的子句)。此外,PostgreSQL
还可以使用哈希连接算法;但它必须知道这一策略是否适用。当前的哈希连接算法只对表示相等测试的操作符是正确的;而且,数据类型的相等必须意味着类型表示的按位相等。(例如,一个包含对相等测试无关紧要的未用位的数据类型就不能做哈希连接。)HASHES
标志向查询优化器指明,此操作符可以安全地用于哈希连接。
类似地,MERGES
标志指明归并排序对这一操作符是否是可用的连接策略。归并连接要求两个输入数据类型具有一致的排序,且归并连接操作符相对于该排序的行为像相等一样。例如,把两个输入都按普通数值顺序排序,就可以在整型和浮点变量之间做归并连接的相等。归并连接的执行要求系统能够识别出与该可归并连接相等操作符相关的四个操作符:左输入数据类型的小于比较、右输入数据类型的小于比较、两种数据类型之间的小于比较,以及两种数据类型之间的大于比较。可以分别通过名称指定它们,即
SORT1、SORT2、LTCMP 和
GTCMP 选项。系统在指定
MERGES
时若省略其中任何一个,将分别填入默认名称
<、<、<、>。此外,如果这四个操作符选项中任何一个出现,就会认为隐含了
MERGES。
如果将来发现其他连接策略切实可行,PostgreSQL 会修改优化器和运行时系统来使用它们,并在定义操作符时要求额外的说明。幸运的是,研究界并不经常发明新的连接策略,而用户自定义连接策略带来的额外通用性被认为不值得为之增加复杂度。
RESTRICT 和
JOIN 选项帮助查询优化器估算结果大小。如果限定条件中出现了形如:
myboxes.description <<< box '((0,0), (1,1))'
的子句,那么
PostgreSQL
可能必须估算
myboxes
中满足该子句的实例比例。函数
res_proc
必须是一个已注册的函数(即已用
CREATE FUNCTION 定义),它接受正确数据类型的参数并返回一个浮点数。查询优化器只需调用该函数,传入参数
((0,0), (1,1)),再把结果乘以关系的大小,就得到预期的实例数。
类似地,当操作符的两个操作数都含有实例变量时,查询优化器必须估算所得连接的大小。函数
join_proc
会返回另一个浮点数,把它乘以所涉及两个表的基数,就得到预期的结果大小。
函数
my_procedure_1 (MYBOXES.description, box '((0,0), (1,1))')
与操作符
MYBOXES.description === box '((0,0), (1,1))'
的区别在于:PostgreSQL 会尝试优化操作符,并可在涉及操作符时决定使用索引来限制搜索空间。但系统不会尝试优化函数,函数是靠蛮力执行的。此外,函数可以有任意数量的参数,而操作符只能有一个或两个。
注意
更多信息请参考
PostgreSQL 用户指南中关于操作符的章节。要删除数据库中用户定义的操作符,请参阅
DROP OPERATOR。
要在com_op或其他可选参数中给出带模式限定的操作符名称,请使用OPERATOR()语法,例如:
COMMUTATOR = OPERATOR(myschema.===) ,
用法
下面的命令为 BOX 数据类型定义一个新的操作符——面积相等:
CREATE OPERATOR === ( LEFTARG = box, RIGHTARG = box, PROCEDURE = area_equal_procedure, COMMUTATOR = ===, NEGATOR = !==, RESTRICT = area_restriction_procedure, JOIN = area_join_procedure, HASHES, SORT1 = <<<, SORT2 = <<< -- Since sort operators were given, MERGES is implied. -- LTCMP and GTCMP are assumed to be < and > respectively );
兼容性
SQL92
CREATE OPERATOR
是
PostgreSQL 的扩展。在
SQL92 中没有
CREATE OPERATOR
语句。