我使用 PostgreSQL 10.3。
我创建了以下域:
CREATE DOMAIN common.citext_nullable
AS extensions.citext;
CREATE DOMAIN common.citext_not_null
AS extensions.citext NOT NULL;
CREATE DOMAIN common.smallint_ge_zero_nullable
AS smallint;
ALTER DOMAIN common.smallint_ge_zero_nullable
ADD CONSTRAINT smallint_ge_zero_nullable_check CHECK (value >= 0);
和以下函数:
CREATE OR REPLACE FUNCTION common.fun_name(
p_1 common.citext_not_null,
p_2 common.citext_nullable,
p_3 common.citext_nullable,
p_4 common.smallint_ge_zero_nullable)
RETURNS ...
LANGUAGE 'plpgsql'
AS $BODY$
DECLARE
...
BEGIN
...
END;
$BODY$;
注意事项:
- 所有参数/参数都是域类型。
- 领域和功能在同一架构中“通用”。
- 模式“common”包含在搜索路径中。
- 所有扩展都在“扩展”架构中。
- 模式“扩展”也包含在搜索路径中。
- 基于“citext”的域按预期工作。
- 基于“smallint”的域运行异常。
- 针对问题的范围简化了上述领域和功能。
我可以通过以下方式调用该函数
SELECT fun_name('any', 'any', 'any', 5::smallint_ge_zero_nullable);
甚至通过
SELECT fun_name('any', 'any', 'any', '5');
但我不能通过以下方式调用它:
SELECT fun_name('any', 'any', 'any', 5);
我收到以下错误:
SQL Error [42883]: ERROR: function fun_name(unknown, unknown, unknown, integer) does not exist
Hint: No function matches the given name and argument types. You might need to add explicit type casts.
Position: 8
为什么基于“citext”的参数显示为“未知”?根据文档,第 1431 页
argtype
The data type(s) of the function's arguments (optionally schema-qualified), if any. The argument types can be base, composite, or domain types, or ...
(“有趣”的是“unknown”参数最终被接受并按预期工作,而“integer”参数不被接受并表现得很奇怪。)
最佳答案
此行为与 int - smallint 转换有关,与域无关。
您可以找到将函数调用与具有适当参数的函数相关联的规则 here .它将在可用时使用隐式转换,并将始终将“未知”类型与任何内容匹配。由于您的函数只有一个签名,因此情况 1(显式强制转换)和情况 2(全部未知)将与您的函数匹配。
没有自动向下转换,所以 integer -> smallInt 不会隐式出现。让我们考虑一个具有两个签名的函数 f(input as int)
和 f(input as smallint)
如果要进行向下转换,调用 f(5)
时应使用哪一个?此邮件列表 thread将提供更多详细信息。
所以解决方案要么
- 进行显式转换(案例 1)
- 或者拥有一个具有通用类型(整数)的函数包装器,为您进行转换(并处理错误..)
- 或者使用具有正确类型的表列的输出来调用该函数。
关于postgresql - PostgreSQL 中的函数调用行为不当,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49129211/