↑↓ 选择↵ 打开⌫ 切换范围完整搜索

PG.CENTER 连接 PostgreSQL 文档、百科与生态知识。由 Pigsty 维护。

支持中的版本: 当前版本 (18) / 17 / 16 / 15 / 14
开发中的版本: 19 / 20devel
已结束支持的版本: 13 / 12 / 11 / 10 / 9.6 / 9.5 / 9.4 / 9.3 / 9.2 / 9.1 / 9.0 / 8.4 / 8.3 / 8.2 / 8.1 / 8.0 / 7.4 / 7.3 / 7.2 / 7.1
历史版本。 PostgreSQL 7.1 已结束支持。 请参阅 当前版本手册.

5.2. 操作符 #

操作符类型解析

  1. 在 pg_operator 系统目录中检查精确匹配。

    1. 如果二元操作符的一个参数是 unknown 类型,那么在这一步检查中假定它与另一个参数的类型相同。其他涉及 unknown 的情况在这一步永远找不到匹配。

  2. 寻找最佳匹配。

    1. 列出所有同名且输入类型匹配或可以强制转换成匹配的操作符。(为此目的,假定 unknown 字面量可以转换成任何类型。)如果只有一个,就使用它;否则继续下一步。

    2. 遍历所有候选,保留输入类型精确匹配最多的。如果没有任何精确匹配,则保留全部候选。如果只剩一个候选,就使用它;否则继续下一步。

    3. 遍历所有候选,保留输入类型精确匹配或二进制兼容匹配最多的。如果没有任何精确或二进制兼容匹配,则保留全部候选。如果只剩一个候选,就使用它;否则继续下一步。

    4. 遍历所有候选,保留在需要类型强制转换的最多个位置上接受首选类型的。如果没有任何候选接受首选类型,则保留全部候选。如果只剩一个候选,就使用它;否则继续下一步。

    5. 如果有输入参数是"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)

这种情况下没有关于使用哪个类型的初始提示,因为查询中没有指定类型。于是解析器查找所有候选操作符,发现有候选既接受 string 类别也接受 bitstring 类别的输入。由于 string 类别可用时会被优先选择,就选择了该类别,然后把字符串的 "preferred type"(首选类型)text 用作解析未知字面量的具体类型。

5.2.1.3. 阶乘

这个例子说明了一个有趣的结果。传统上,阶乘运算符只为整数定义。Postgres 的运算符目录中阶乘只有一个条目,接受整数操作数。如果给定非整数的数值参数,Postgres 会试图把该参数转换成整数来求阶乘。

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

注意

当然,这在数学上是可疑的结果,因为原则上非整数的阶乘没有定义。不过,数据库的职责不是教数学,而是做数据操纵的工具。如果用户选择对浮点数求阶乘,Postgres 也会照办。

报告文档问题

阅读 上游文档. 反馈更正前请先核对 当前版本手册.