5.2. 操作符

操作符类型解析

  1. 在 pg_operator 系统表里找出准确的匹配.

    1. 如果一个双目操作符的一个参数是 unknown, 则假设其与另一个参数类型相同. 其他涉及 unknown 的情况不会在这一步找到匹配.

  2. 寻找最优匹配.

    1. 生成一个同名的操作符的列表:它们的输入类型匹配或者可以转换成匹配的。 (unknown 文本认为可以为此目的转换成任何类型) 如果只有一个,用之,否则继续下一步.

    2. 遍历所有候选操作符,保留那些输入类型有最多准确匹配的. 如果没有完全准确匹配的操作符,保留所有候选. 如果只有一个,用之,否则继续下一步.

    3. 遍历所有候选操作符,保留那些输入类型有最多准确匹配或者二进制兼容匹配的. 如果没有完全准确匹配或者二进制兼容匹配的操作符,保留所有候选. 如果只有一个,用之,否则继续下一步.

    4. 遍历所有候选操作符,保留那些输入类型有最多准确匹配或者二进制兼容匹配的. 如果没有完全准确匹配或者二进制兼容匹配的操作符,保留所有候选. 如果只有一个,用之,否则继续下一步.

    5. 如果任何输入参数是 "unknown",检查剩下的候选操作符对应参数位置的 类型表.如果任何候选操作符接受 "string" 类型,则在那些位置选 "string" 类型(这个假设认为 string 是合适的,因为 unknown 类型文本确实象 string). 否则,如果所有剩下的候选操作符接受相同的类型,选择该类型; 否则抛出一个错误,因为在没有更多线索的条件下不能导出正确的选择. 还要注意是否有哪个候选操作符在选出的类型表中有优选类型. 现在抛弃不接受选定的类型表的候选操作符;然后, 如果任意候选操作符在某个给定的参数位置接受一个优选类型, 则抛弃那些在该参数位置接受非优选类型的候选操作符.

    6. 如果只剩下一个操作符,用之. 如果还有超过一个的候选操作符或是没有候选操作符,则产生一个错误.

5.2.1. 例子

5.2.1.1. 指数操作符

在分类里只有一个指数操作符,它以 double precision 作为参数.扫描器给下面查询表达式的两个参数赋予 int4 的初始类型:

tgl=> select 2 ^ 3 AS "Exp";
 Exp
-----
   8
(1 row)
分析器对两个参数都做类型转换,查询等效于:
tgl=> select CAST(2 AS double precision) ^ CAST(3 AS double precision) AS "Exp";
 Exp
-----
   8
(1 row)
tgl=> select 2.0 ^ 3.0 AS "Exp";
 Exp
-----
   8
(1 row)

注意: 最后的形式最高效,因为不用调用函数做隐含类型转换. 这对小查询没有什么影响,但可能对那些操 作大表的查询的性能产生较大影响.

5.2.1.2. 字符串连接

一种类字符串的语法既可以用于字符串也可以用于复杂的扩展类型. 包含不明类型的字串使用可能的候选操作符匹配.

有一个未声明的参数:

tgl=> SELECT text 'abc' || 'def' AS "Text and Unknown";
 Text and Unknown
------------------
 abcdef
(1 row)

本例中分析器寻找一个两个参数都是 text 的操作符.因为有一个这样的操作符,它认为另一个参数的类型是 text

联接未声明类型:

tgl=> SELECT 'abc' || 'def' AS "Unspecified";
 Unspecified
-------------
 abcdef
(1 row)

本例中对类型的初始值没有任何提示,因为查询中没有声明任何类型. 因此,分析器查找所有参数都是字符串类的候选操作符. 并且它选择"优选类型", text,作为本查询字符串类的类型.

5.2.1.3. 阶乘

本例演示了一个有趣的结果.一般来说,阶乘只用于整数, Postgres 操作符类别中用于阶乘的只有一个, 其以整数为操作数.如果输入一个非整数数字参数. Postgres 将试图把该参数转换成整数进行阶乘运算.

tgl=> select (4.3 !);
 ?column?
----------
       24
(1 row)

注意: 这样做当然会导致一个数学上有疑问的结果,因为非整数的阶乘原则没有定义. 但是,数据库的角色 不是数学教学,而是数据操作.如果用户一定要进行浮点数的阶乘, Postgres 将尽可能服从.