PostgreSQL7.0手册-用户手册-19. SQL命令-CREATE OPERATOR
名称
CREATE OPERATOR — 定义一个新的用户操作符
语法
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 ] )
输入
name
定义的操作符名.可用的字符见下文。
func_name
用于实现该操作符的函数。
type1
如果存在的话,操作符左手边的参数类型.如果是右目操作符,这个参数可以省略。
type2
如果存在的话,操作符右手边的参数类型.如果是左目操作符,这个参数可以省略。
com_op
对应的换向(commutative)操作符。
neg_op
对应的负操作符。
res_proc
此操作符约束选择性评估函数。
join_proc
此操作符的联合选择性评估函数。
HASHES
表明此操作符支持哈希(散列)联合算法。
left_sort_op
如果此操作符支持融合联合(join),此操作符的左边数据的排序操作符。
right_sort_op
如果此操作符支持融合联合(join),此操作符的右边数据的排序操作符。
输出
CREATE
成功创建操作符后的返回信息.
描述
CREATE OPERATOR 定义一个新的操作符, name .定义该操作符的用户成为其所有者.
操作符 name 是一个最多 NAMEDATALEN-1 长的(缺省委 31 个)下列字符组成的字串.
+ - * / < > = ~ ! @ # % ^ & ` ? $ :
你选择名字的时候有几个限制:
"$" 和 ":" 不能定义为单字符操作符,尽管它们可以是一个多字符操作符的名称的一部分.
"--" 和 "/*" 不能在操作符名字的任何地方出现,因为它们会被认为是一个注释的开始.
一个多字符的操作符名字不能以 "+" 或 "-" 结尾,除非该名字还包含至少下面字符之一:
~ ! @ # % ^ & ` ? $ :
例如,@- 是一个允许的操作符名,但 *- 不是.这个限制允许 Postgres 分析 SQL-有问题的查询而不要求在符号之间有空白.
请注意:当使用非 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 试图优化操作符并且可以决定使用索引来缩小相关操作符的搜索区间.但是,对函数将不会有任何优化的动作,而且是强制执行.最后,函数可有任意个参数,而操作符限于一个或两个.
注意
请参阅PostgreSQL 用户手册 中操作符章节获取更多信息.请使用 DROP OPERATOR 从数据库中删除用户定义操作符.
用法
下面命令定义一个新操作符,面积相等,用于 BOX 数据类型.
CREATE OPERATOR === (
LEFTARG = box,
RIGHTARG = box,
PROCEDURE = area_equal_procedure,
COMMUTATOR = ===,
NEGATOR = !==,
RESTRICT = area_restriction_procedure,
JOIN = area_join_procedure,
HASHES,
SORT1 = <<<,
SORT2 = <<<
);
兼容性
SQL92
CREATE OPERATOR 是 Postgres 扩展.在 SQL92 中没有 CREATE OPERATOR 语句.