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

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

已结束支持的版本: 7.0 / 6.4
历史版本。 PostgreSQL 6.4 已结束支持。 请参阅 当前版本手册.

11.2. 操作符

11.2.1. 转换过程

操作符求值

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

    1. 如果二元操作符的一个参数是 unknown,就假定它与另一个参数的类型相同。

    2. 交换参数,寻找与一个指向自身为可交换的操作符的精确匹配。如果找到,就在解析树中交换参数并使用该操作符。

  2. 寻找最佳匹配。

    1. 列出所有同名的操作符。

    2. 如果列表中只有一个操作符,输入类型可强制转换时就使用它,类型不能强制转换时就报错。

    3. 保留类型显式匹配最多的操作符。如果没有显式匹配则全部保留并进入下一步。如果只剩一个候选,类型可强制转换时就使用它。

    4. 如果有输入参数是"unknown",把输入候选归类为 boolean、numeric、string、geometric 或用户自定义。如果类别混合,或者用户定义类型多于一个,就报错,因为没有更多线索就无法推断出正确的选择。如果只有一个类别,就把"首选类型"赋给先前为"unknown"的输入列。

    5. 选择类型精确匹配最多且与上一步中每个列类别的 "首选类型"匹配的候选。如果候选仍多于一个,或者一个也没有,就报错。

11.2.2. 示例

11.2.2.1. 求幂操作符

目录中只定义了一个求幂操作符,它接受 float8 参数。扫描器为这个查询表达式的两个参数都赋予初始类型 int4:

tgl=> select 2 ^ 3 AS "Exp";
Exp
---
  8
(1 row)

于是解析器对两个操作数都做类型转换,查询等价于

tgl=> select float8(2) ^ float8(3) AS "Exp";
Exp
---
  8
(1 row)

或

tgl=> select 2.0 ^ 3.0 AS "Exp";
Exp
---
  8
(1 row)

注意

最后这种形式的开销最小,因为不需要调用任何函数来做隐式类型转换。这对小查询不是问题,但可能影响涉及大表的查询的性能。

11.2.2.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 类型。它为这个查询选择 string 的"首选类型" text。

注意

如果用户定义了一个新类型并为它定义了 “||” 操作符来配合它工作,这个查询就会不再按原样成功。解析器此时会有来自两个类别的候选类型,无法决定用哪一个。

11.2.2.3. 阶乘

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

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

注意

当然,这会得到数学上可疑的结果,因为原则上非整数的阶乘是没有定义的。不过,数据库的角色不是教数学,而是做数据操作的工具。如果用户选择求浮点数的阶乘,Postgres 会尽量照办。

报告文档问题

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