pgsql.cc 提供对 postgresql.org 官网内容的中文翻译,由 Pigsty 团队维护。
操作符求值
在 pg_operator 系统目录中检查精确匹配。
如果二元操作符的一个参数是 unknown, 就假定它与另一个参数的类型相同。
交换参数,寻找与一个指向自身为可交换的 操作符的精确匹配。 如果找到,就在解析树中交换参数并使用该操作符。
寻找最佳匹配。
列出所有同名的操作符。
如果列表中只有一个操作符,输入类型可强制转换时就使用它, 类型不能强制转换时就报错。
保留类型显式匹配最多的操作符。如果没有 显式匹配则全部保留并进入下一步。 如果只剩一个候选,类型可强制转换时就使用它。
如果有输入参数是"unknown",把输入候选归类为 boolean、numeric、string、geometric 或用户自定义。如果类别 混合,或者用户定义类型多于一个,就报错,因为 没有更多线索就无法推断出正确的选择。 如果只有一个类别,就把"首选类型"赋给 先前为"unknown"的输入列。
选择类型精确匹配最多且与上一步中每个列类别的 "首选类型"匹配的候选。 如果候选仍多于一个,或者一个也没有, 就报错。
目录中只定义了一个求幂 运算符,它接受 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)
最后这种形式的开销最小,因为没有调用任何函数来做 隐式类型转换。这对小查询不是问题,但可能 影响涉及大表的查询的性能。
类字符串的语法既用于处理字符串类型,也用于 处理复杂的扩展类型。 未指定类型的字符串会与可能的操作符候选 匹配。
一个参数未指定类型:
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。
如果用户定义了一个新类型并为它定义了 “||” 操作符来配合它工作,这个查询就会 不再按原样成功。解析器此时会 有来自两个类别的候选类型,无法决定用哪一个。
这个例子说明了一个有趣的结果。传统上, 阶乘运算符只为整数定义。Postgres 的运算符目录中阶乘只有一个条目,接受整数操作数。 如果给定非整数的数值参数,Postgres 会试图把该参数转换成整数来求 阶乘。
tgl=> select (4.3 !);
?column?
--------
24
(1 row)
当然,这在数学上是可疑的结果, 因为原则上非整数的阶乘没有定义。 不过,数据库的职责不是教数学,而是做数据操纵的工具。 如果用户选择对浮点数求阶乘, Postgres 也会照办。
译文有误、术语不当或页面显示问题,请到译文仓库 pgsty/pgdoc 报告译文问题。 英文原文本身的问题,请在当前版本的对应页面向上游反馈;上游不再修订已结束维护的版本。