Postgresql 中文操作指南

10.3. Functions #

函数调用所引用的特定函数使用以下过程来确定。

Function Type Resolution

注意,对于运算符和函数类型解决方案,“最佳匹配”规则相同。下面是某些示例。

Example 10.6. Rounding Function Argument Type Resolution

只有一个 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);

Example 10.7. Variadic Function Resolution

CREATE FUNCTION public.variadic_example(VARIADIC numeric[]) RETURNS int
  LANGUAGE sql AS 'SELECT 1';
CREATE FUNCTION

此函数接受 VARIADIC 关键字,但不要求它。它容忍整数和数字参数:

SELECT public.variadic_example(0),
       public.variadic_example(0.0),
       public.variadic_example(VARIADIC array[0.0]);
 variadic_example | variadic_example | variadic_example
------------------+------------------+------------------
                1 |                1 |                1
(1 row)

但是,第一个和第二个调用会优先使用更具体的函数(如果可用):

CREATE FUNCTION public.variadic_example(numeric) RETURNS int
  LANGUAGE sql AS 'SELECT 2';
CREATE FUNCTION

CREATE FUNCTION public.variadic_example(int) RETURNS int
  LANGUAGE sql AS 'SELECT 3';
CREATE FUNCTION

SELECT public.variadic_example(0),
       public.variadic_example(0.0),
       public.variadic_example(VARIADIC array[0.0]);
 variadic_example | variadic_example | variadic_example
------------------+------------------+------------------
                3 |                2 |                1
(1 row)

考虑到默认配置并且仅存在第一个函数,第一个和第二个调用是不安全的。任何用户都可以通过创建第二个或第三个函数来拦截它们。通过精确匹配参数类型并使用 VARIADIC 关键字,第三个调用是安全的。

Example 10.8. Substring Function Type Resolution

有几个 substr 函数,其中一个函数接受类型 textinteger。如果使用未指定类型的字符串常量调用该函数,那么系统会选择接受首选类别(即类型 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);

Note

解析器从 pg_cast 目录了解到 textvarchar 是二进制兼容的,这意味着可以将一个传递给一个接受另一个的函数,而无需执行任何物理转换。因此,在这种情况下不会真正插入类型转换调用。

而且,如果使用类型 integer 的参数调用该函数,解析器将尝试将其转换为 text

SELECT substr(1234, 3);
ERROR:  function substr(integer, integer) does not exist
HINT:  No function matches the given name and argument types. You might need
to add explicit type casts.

这不起作用,因为 integer 没有 text 的隐式强制转换。但是,显式强制转换会起作用:

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

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

[10 ] 如果搜索路径含允许不受信任用户创建对象的模式,则不会出现非模式限定名称的危险,因为它不是 secure schema usage pattern

[11 ] 执行此步骤的目的是支持没有实际转换函数的情况下函数样式的转换规范。如果有转换函数,通常以其输出类型命名,因此不必有特殊情况。有关其他评论,请参见 CREATE CAST