CREATE OPERATOR name ( PROCEDURE = func_name [, LEFTARG = type1 ] [, RIGHTARG = type2 ] [, COMMUTATOR = com_op ] [, NEGATOR = neg_op ] [, RESTRICT = res_proc ] [, JOIN = join_proc ] [, HASHES ] [, SORT1 = left_sort_op ] [, SORT2 = right_sort_op ] )
要定义的操作符。可用的字符见下文。
用于实现该操作符的函数。
如果存在的话,操作符左手边的参数类型. 如果是左目操作符,这个参数可以省略。
如果存在的话,操作符右手边的参数类型. 如果是右目操作符,这个参数可以省略。
该操作符对应的交换(commutator)操作符。
对应的负操作符。
此操作符约束选择性计算函数。
此操作符连接选择性计算函数。
表明此操作符支持哈希(散列)连接。
如果此操作符支持融合连接(join),此操作符的左手边数据的排序操作符。
如果此操作符支持融合连接(join),此操作符的右手边数据的排序操作符。
CREATE OPERATOR 定义一个新的操作符, name. 定义该操作符的用户成为其所有者.
操作符 name 是一个最多 NAMEDATALEN-1 长的(缺省为 31 个)下列字符组成的字串:
+ - * / < > = ~ ! @ # % ^ & | ` ? $
"$" 和 ":" 不能定义为单字符操作符, 但是它们可以是一个多字符操作符的名称的一部分.
"--" 和 "/*" 不能在操作符名字的任何地方出现, 因为它们会被认为是一个注释的开始.
一个多字符的操作符名字不能以 "+" 或 "-" 结尾, 除非该名字还包含至少下面字符之一:
~ ! @ # % ^ & | ` ? $
注意: 当使用非 SQL-标准操作符名时, 你通常将需要用空白把联接的操作符分离开以避免含混. 例如,如果你定义了一个左目操作符,名为 "@",你不能写 X*@Y;你必须写成 X* @Y 以保证 Postgres 把它读做两个操作符而不是一个.
操作符 "!=" 在输入时映射成 "<>", 因此这两个名称总是相等的.
至少需要定义一个 LEFTARG 或 RIGHTARG. 对于双目操作符来说,两者都需要定义. 对右目操作符来说,只需要定义 LEFTARG, 而对于左目操作符来说,只需要定义 RIGHTARG.
同样, func_name 过程必须已经用 CREATE FUNCTION 定义过, 而且必须定义为接受正确数量的指定类型参数(一个或是两个).
如果存在换向操作符则必须指明,这样 Postgres 可以按它的意愿转换操作符的方向. 例如,操作符面积小于, <<<, 很有可能有一个转换操作符:面积大于操作符, >>>. 因此,查询优化器可以自由的将下面查询从:
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))'
如果提供了一个交换操作符名称, Postgres 将在表中查找它.如果找到, 而且其本身没有一个交换符,那么交换符表将被更新,以当前(最 新)创建的操作符作为它的交换符.这一点一样适用于负号操作符. 这就允许定义两个互为交换符或负号符的操作符. 第一个操作符应该定义为没有交换符 或负号符(as appropriate). 当定义第二个操作符时,将第一个符号作为交换符或负号符. 第一个将因上述的副作用一样被更新(而获得交换符 或负号符).(对于 Postgres 6.5,把两个操作符指向对方同样也行。)
HASHES,SORT1 和 SORT2 选项将为查询优化器进行连接查询时提供支持. Postgres 能够总是用反复替换来计算一个连接( 也就是说,处理这样的子句,该子句有两个元组变量, 这两个变量被一个操作符分开,这个操作符返回一个布尔量) [WONG76]. 另外, Postgres 可以延着 [SHAP86]实现一个散列-连接算法(hash-join algorithm); 但是,我们必须知道这个策略是否可行.目前的散列-连接算法只是对代表相等 测试的操作符有效;而且,数据类型的相等必须意味着类型的表现是按位相等的。 (例如,一个包含未用的位的数据类型,这些位对相等测试没有 影响,但却不能用于哈希连接。)HASHES 标记告诉优化器, 对这个操作符可以安全地使用哈希连接。
类似的,两目排序操作符告诉查询优化器一个融合-排序 (merge-sort)是否是一个可用的连接策略, 并且告诉优化器使用哪个操作符来对这两个操 作数表排序.排序操作符应该只提供给相等操作符, 并且它们应该对应用于相应的左边和右边数据类型的小于操作符。
如果发现有其他联合策略可用, Postgres 将更改优化器和运行时系统以利用这些策略, 并且在定义一个操作符时将需要更多的声明.幸运的是,研究 团队不经常发明新的联合策略, 而且增加用户定义联合策略的方法看来与其实现的复杂性相比是不值得的。
RESTRICT 和 JOIN 选项帮助优化器计算结果的尺寸大小.如果像下面的语句:
MYBOXES.description <<< box '((0,0),(1,1))'在判断条件中出现,那么 Postgres 将不得不估计 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))'之间的区别是 Postgres 试图优化操作符并且可以决定使用索引来缩小相关操作符的搜索区间. 但是,对函数将不会有任何优化的动作,而且是强制 执行.最后,函数可有任意个参数,而操作符限于一个或两个.