PostgreSQL 中文参考文档
🌐 英文原版 官方 ↗

36.6. 函数重载 #

只要所接受的参数不同,就可以使用相同的 SQL 名称定义多个函数。换言之,函数名可以被重载(overloaded)。无论是否使用重载,在存在互不信任用户的数据库中调用函数时都需要采取安全防范措施(参见 Section 10.3)。执行查询时,服务器会根据提供的实参数据类型和数量来决定调用哪一个函数。重载还可以用于模拟具有可变参数数量的函数(直至有限的最大数量)。

在创建一组重载函数时,应格外小心避免产生歧义。例如给定以下两个函数:

CREATE FUNCTION test(int, real) RETURNS ...
CREATE FUNCTION test(smallint, double precision) RETURNS ...

对于诸如 test(1, 1.5) 这样简单的调用,并不容易立即确定会调用哪个函数。当前实现的类型匹配消歧规则在 Chapter 10 中有详细说明,但在系统设计中微妙地依赖这些复杂规则是不明智的。

接受复合类型单个参数的函数通常不应与该类型的任何属性(字段)同名。请回顾 attribute(table) 与 table.attribute 是等价的。当复合类型上的函数与该类型的属性发生命名冲突时,属性始终具有优先权。可以通过用模式名限定函数名(即 schema.func(table))来强制调用函数,但最佳实践是通过避免命名冲突来彻底消除隐患。

另一种潜在的冲突发生在变长参数函数与非变长参数函数之间。例如,可以同时创建 foo(numeric) 和 foo(VARIADIC numeric[])。在这种情况下,传入单个数值参数的调用(如 foo(10.1))匹配哪一个并不明显。解析规则是:优先使用搜索路径中靠前模式下的函数;若两个函数位于同一个模式中,则优先选用非变长参数函数。

在重载 C 语言函数时存在额外约束:重载函数族中每个函数的 C 语言函数名必须与所有其他函数(无论是内部函数还是动态加载的函数)的 C 语言符号名互不相同。如果违反该规则,其行为将不可移植。您可能会遇到运行时链接器错误,或者错误调用了其中某一个函数(通常是内部函数)。SQL CREATE FUNCTION 命令的 AS 子句的替代形式可以将 SQL 函数名称与 C 源码中的函数符号名称解耦。例如:

CREATE FUNCTION test(int) RETURNS int
    AS 'filename', 'test_1arg'
    LANGUAGE C;
CREATE FUNCTION test(int, int) RETURNS int
    AS 'filename', 'test_2arg'
    LANGUAGE C;

此处的 C 函数命名方式反映了诸多可行命名规范之一。