↑↓ 选择 ↵ 打开 ⌫ 改范围 完整检索页

pgsql.cc 提供对 postgresql.org 官网内容的中文翻译,由 Pigsty 团队维护。

受支持版本: 当前版本 (18) / 17 / 16 / 15 / 14
测试与开发版本: 19 / devel
不受支持的版本: 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 8.1 已于 2010 年 11 月结束社区维护,本页译文保留供仍在使用旧版本的读者参考。新系统请看当前版本。

10.3. 函数 #

函数调用所引用的具体函数按照下述过程确定。

函数类型解析

  1. 从系统目录pg_proc中选取要考虑的函数。如果使用的是未带模式限定的函数名,则考虑当前搜索路径中可见且名称和参数个数匹配的函数(见第 5.7.3 节)。如果给出了限定名,则只考虑指定模式中的函数。

    1. 如果搜索路径中找到多个参数类型完全相同的函数,只考虑路径中最早出现的那一个。参数类型不同的函数则不受搜索路径位置影响,处于同等地位。

  2. 检查是否存在一个恰好接受输入参数类型的函数。如果存在(在被考虑的函数集合中至多只有一个精确匹配),就使用它。(涉及unknown的情况在这一步永远找不到匹配。)

  3. 如果没有找到精确匹配,就检查该函数调用是否看起来像一个平凡的类型转换请求。这种情况发生在:函数调用只有一个参数,且函数名与某个数据类型的(内部)名称相同。此外,函数参数必须是unknown类型字面量,或者是一种与该命名数据类型二进制兼容的类型。满足这些条件时,函数参数会被直接转换为该命名数据类型,而不会发生实际的函数调用。

  4. 寻找最佳匹配。

    1. 丢弃那些输入类型不匹配,且也无法通过隐式类型转换实现匹配的候选函数。为此,假定unknown字面量可以转换为任何类型。如果只剩一个候选函数,就使用它;否则继续下一步。

    2. 遍历所有候选函数,保留那些在输入类型上精确匹配数最多的候选项。(在这一步中,域被视为与其基础类型相同。)如果没有任何候选项存在精确匹配,则保留全部候选项。如果只剩一个候选函数,就使用它;否则继续下一步。

    3. 遍历所有候选函数,在需要类型转换的位置上,保留接受首选类型(属于输入数据类型的类型分类)的位置数最多的候选项。如果没有候选项接受首选类型,则保留全部候选项。如果只剩一个候选函数,就使用它;否则继续下一步。

    4. 如果有任何输入参数是unknown,就检查剩余候选函数在这些参数位置上接受哪些类型分类。在每个位置上,如果有任何候选项接受string分类,就选择该分类。(这种偏向字符串的做法是合适的,因为unknown类型的字面量看起来像字符串。)否则,如果所有剩余候选项都接受同一种类型分类,就选择该分类;否则失败,因为在缺少更多线索的情况下无法推断出正确选择。然后丢弃不接受所选类型分类的候选项。此外,如果有任何候选项接受该分类中的首选类型,就丢弃在该参数上接受非首选类型的候选项。

    5. 如果只剩一个候选函数,就使用它。如果没有候选函数或者不止一个候选函数剩余,则失败。

注意,操作符类型解析和函数类型解析的“最佳匹配”规则是完全相同的。下面是一些示例。

例 10.4. round 函数参数类型解析

只有一个接受两个参数的round函数;它的第一个参数类型是numeric,第二个参数类型是integer。因此下面的查询会自动把类型为integer的第一个参数转换为numeric:

SELECT round(4, 4);

 round
--------
 4.0000
(1 row)

该查询实际上会被解析器改写成:

SELECT round(CAST (4 AS numeric), 4);

由于带小数点的数字常量最初会被赋予numeric类型,下面的查询不需要类型转换,因此可能稍微更高效一些:

SELECT round(4.0, 4);

例 10.5. substr 函数类型解析

存在多个substr函数,其中一个接受text和integer。如果以未指定类型的字符串常量调用,系统会选择接受首选类型分类string参数的候选函数(也就是text类型的那个)。

SELECT substr('1234', 3);

 substr
--------
     34
(1 row)

如果字符串被声明为varchar类型,例如它来自表中的某一列,那么解析器会尝试把它转换为text:

SELECT substr(varchar '1234', 3);

 substr
--------
     34
(1 row)

解析器会把它改写成如下形式:

SELECT substr(CAST (varchar '1234' AS text), 3);

注意

解析器从pg_cast目录得知text与varchar二进制兼容,这意味着把其中一种类型传给接受另一种类型的函数时,无需做任何物理转换。因此,这种情况下实际上不会插入类型转换调用。

如果用integer类型参数调用该函数,解析器会尝试把它转换为text:

SELECT substr(1234, 3);

 substr
--------
     34
(1 row)

它实际执行的是

SELECT substr(CAST (1234 AS text), 3);

这种自动转换之所以能够成功,是因为存在从integer到text的隐式可调用类型转换。


提交更正

译文有误、术语不当或页面显示问题,请到译文仓库 pgsty/pgdoc 报告译文问题。 英文原文本身的问题,请在当前版本的对应页面向上游反馈;上游不再修订已结束维护的版本。