PostgreSQL 教程: PL/pgSQL 函数重载

八月 18, 2023

摘要:在本教程中,您将了解 PostgreSQL 中的函数重载。

PL/pgSQL 函数重载简介

PostgreSQL 允许多个函数共享相同的名称,只要它们具有不同的参数即可。

如果两个或多个函数共享相同的名称,则函数名称被重载。

当您可以调用重载函数时,PostgreSQL 根据函数参数列表选择最佳候选函数来执行。

以下get_rental_duration()函数返回指定客户的总租赁天数:

create or replace function get_rental_duration(
	p_customer_id integer
)
returns integer 
language plpgsql
as $$
declare 
	rental_duration integer; 
begin
	select 
		sum( extract(day from return_date - rental_date)) 
	into rental_duration 
    from rental 
	where customer_id = p_customer_id;

	return rental_duration;
end; $$

get_rental_function函数有一个in模式的p_customer_id参数。

以下返回 id 为 232 的客户租赁天数:

SELECT get_rental_duration(232);
 get_rental_duration
---------------------
                  90
(1 row)

假设您想了解客户从特定日期到现在的租赁时长。

为此,您可以向该get_retal_duration()函数再添加一个参数p_from_date。或者您可以开发一个具有相同名称但具有两个参数的新函数,如下所示:

create or replace function get_rental_duration(
	p_customer_id integer, 
	p_from_date date
)
returns integer 
language plpgsql
as $$
declare 
	rental_duration integer;
begin
	-- get the rental duration based on customer_id 
	-- and rental date
	select sum( extract( day from return_date + '12:00:00' - rental_date)) 
	into rental_duration
	from rental 
	where customer_id = p_customer_id and 
		  rental_date >= p_from_date;
	
	-- return the rental duration in days
	return rental_duration;
end; $$

该函数与第一个函数同名,只是它有两个参数。

换句话说,get_rental_duration(integer)函数被get_rental_duration(integer,date)函数重载了。

以下语句返回自July 1st 2005以来 ID 为232的客户租赁天数:

SELECT get_rental_duration(232,'2005-07-01');
 get_rental_duration
---------------------
                  85
(1 row)

请注意,如果省略第二个参数,PostgreSQL 将调用只有一个参数的get_rental_duration(integer)函数。

PL/pgSQL 函数重载和默认值

get_rental_duration(integer,date)函数中,如果要为第二个参数设置默认值,如下所示:

create or replace function get_rental_duration(
	p_customer_id integer, 
	p_from_date date default '2005-01-01'
)
returns integer
language plpgsql
as $$
declare 
	rental_duration integer;
begin
	select sum( 
		extract( day from return_date + '12:00:00' - rental_date)
	) 
	into rental_duration
	from rental 
	where customer_id= p_customer_id and 
		  rental_date >= p_from_date;
	 
	return rental_duration;

end; $$

下面调用get_rental_duration()函数并传递客户 ID 为 232:

SELECT get_rental_duration(232);

PostgreSQL 发出错误:

ERROR:  function get_rental_duration(integer) is not unique
LINE 1: SELECT get_rental_duration(232);
               ^
HINT:  Could not choose the best candidate function. You might need to add explicit type casts.
SQL state: 42725
Character: 8

在这种情况下,PostgreSQL 无法选择最佳的候选函数来执行。

在这种情况下,您具有三个函数:

get_rental_duration(p_customer_id integer);
get_rental_duration(p_customer_id integer, p_from_date date)
get_rental_duration(p_customer_id integer, p_from_date date default '2005-01-01')

PostgreSQL 不知道它应该执行第一个还是第三个函数。

根据经验,当您重载函数时,应该始终使其参数列表唯一。

概括

  • 多个函数可以共享相同的名称,只要它们具有不同的参数即可。这些函数名是重载的。

  • 使用唯一的函数参数列表来定义重载函数。