具有可变数量输入参数的函数 [英] Functions with variable number of input parameters

查看:137
本文介绍了具有可变数量输入参数的函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在PostgreSQL数据库中创建一个存储过程(函数),根据其输入更新表。为了创建可变数量的参数函数,我创建了一个名为mode的额外输入参数,用于控制在更新查询中使用哪些参数。



<$ (
模式整数,
名称字符变化,
城市字符变化,
电话整数,
> CREATE OR REPLACE FUNCTION )
RETURNS integer AS
$$
BEGIN
IF mode = 0 THEN
BEGIN
UPDATESitesSET
(City ,电话)=(城市,电话)
其中SiteName=姓名;
RETURN 1;
例外情况下其他则
RAISE NOTICE'网站更新错误:%,%',SQLERRM,SQLSTATE;
RETURN 0;
END;
ELSIF mode = 1 THEN
BEGIN
UPDATESitesSETCity= city
WHERESiteName= name;
RETURN 1;
例外情况下其他则
RAISE NOTICE'网站更新错误:%,%',SQLERRM,SQLSTATE;
RETURN 0;
END;
ELSIF mode = 2 then
BEGIN
UPDATESitesSETTelephone= telephone
WHERESiteName= name;
RETURN 1;
例外情况下其他则
RAISE NOTICE'网站更新错误:%,%',SQLERRM,SQLSTATE;
RETURN 0;
END;
ELSE
RAISE NOTICE'网站更新错误:%,%',SQLERRM,SQLSTATE;
RETURN 0;
END IF;
END;
$$语言plpgsql;

什么最好?要创建一个函数 update_site(<表格>的所有列)和一个单独的函数 update_site(id integer,< varchar column to update> ),或者在一个函数中使用模式来定义差异?哪个选项更高效?一个独特的功能或不同的功能用于各种用途?

解决方案

高级功能如 VARIADIC 甚至多态输入类型和动态SQL非常强大。本答案的最后一章提供了一个高级示例:

重构PL / pgSQL函数以返回各种SELECT查询的输出



但是对于像您这样的简单案例,您可以只使用默认值作为函数参数。这一切都取决于具体的要求。

如果列中的所有列都定义为 NOT NULL ,那么这可能是更简单,更快:

 创建或替换函数update_site(
_name text - 总是必需的,所以没有默认值
,_city text DEFAULT NULL
,_telephone integer DEFAULT NULL)
RETURNS integer AS
$ func $
BEGIN

IF_city IS NULL
AND _telephone IS NULL THEN
RAISE警告'至少需要更新一个值!';
RETURN; - 没有更新
END IF;

UPDATESites
SETCity= COALESCE(_city,City)
SETTelephone= COALESCE(_telephone,Telephone)
WHERESiteName= _name;

END
$ func $ LANGUAGE plpgsql;

请务必阅读有关手册中默认值的详细信息

为避免命名冲突在参数和列名之间,我习惯于用 _ 作为输入参数的前缀。




  • 第一个参数 name 没有默认值,因为它在任何时候都是必需的。

  • 其他参数可以被赋予或不被赋予。
  • 至少需要一个,或者警告被引发,没有其他事情发生。
  • UPDATE 只会改变给出参数。
  • 可以轻松地扩展为 n 参数。


< h3> Call

您可以使用传统方式调用此方法,使用 位置表示法 。这只允许你省略最右边的参数:

$ p $ SELECT update_site('foo','New York') - - 无电话

为了能够省略任何参数的默认值,您需要使用 命名符号

  SELECT update_site(name:= 'foo',_telephone:= 123); - 无市

或者,为了更简化,您可以使用 混合符号

  SELECT update_site('foo',_telephone:= 123); 


I'm creating a stored procedure (function) in a PostgreSQL DB, which updates a table depending on its input. In order to create a variable number of parameter function, I'm creating an extra input parameter called mode, which I use to control which parameters I use on the update query.

CREATE OR REPLACE FUNCTION update_site(
    mode integer,
    name character varying,
    city character varying,
    telephone integer,
)
RETURNS integer AS
$$
BEGIN
IF mode = 0 THEN
BEGIN
    UPDATE "Sites" SET 
    ("City","Telephone") = (city,telephone)
    WHERE "SiteName" = name;
    RETURN 1;
    EXCEPTION WHEN others THEN
    RAISE NOTICE 'Error on site update: %, %',SQLERRM,SQLSTATE;
    RETURN 0;
END;
ELSIF mode = 1 THEN
BEGIN
    UPDATE "Sites" SET "City" = city
    WHERE "SiteName" = name;
    RETURN 1;
    EXCEPTION WHEN others THEN
    RAISE NOTICE 'Error on site update: %, %',SQLERRM,SQLSTATE;
    RETURN 0;
END;
    ELSIF mode = 2 THEN
BEGIN
    UPDATE "Sites" SET "Telephone" = telephone
    WHERE "SiteName" = name;
    RETURN 1;
    EXCEPTION WHEN others THEN
    RAISE NOTICE 'Error on site update: %, %',SQLERRM,SQLSTATE;
    RETURN 0;
END;
    ELSE
            RAISE NOTICE 'Error on site update: %, %',SQLERRM,SQLSTATE;
    RETURN 0;
    END IF;
END;
$$ LANGUAGE plpgsql;

What would be best? To create a function update_site(<all the columns of table>) and a separate function update_site(id integer, <varchar column to update>), or use the mode in one function to define the difference? Which option is more efficient? One unique function or different ones for each purpose?

解决方案

Advanced features like VARIADIC or even polymorphic input types and dynamic SQL are very powerful. The last chapter in this answer provides an advanced example:
Refactor a PL/pgSQL function to return the output of various SELECT queries

But for a simple case like yours, you can just use of default values for function parameters. It all depends on the exact requirements.
If the columns in question are all defined NOT NULL, this would probably be simpler and faster:

CREATE OR REPLACE FUNCTION update_site(
     _name      text             -- always required, so no default
   , _city      text DEFAULT NULL
   , _telephone integer DEFAULT NULL)
  RETURNS integer AS
$func$
BEGIN

IF  _city IS NULL
AND _telephone IS NULL THEN
   RAISE WARNING 'At least one value to update required!';
   RETURN;  -- nothing to update
END IF;

UPDATE "Sites"
SET    "City" = COALESCE(_city, "City")
SET    "Telephone" = COALESCE(_telephone, "Telephone")
WHERE  "SiteName" = _name;

END
$func$  LANGUAGE plpgsql;

Be sure to read about the details on default values in the manual!

To avoid naming conflicts between parameters and column names I make it a habit to prefix input parameters with _. That's a matter of taste and style.

  • The first parameter name has no default, since it is required at all times.
  • Other parameters can be given or not.
  • At least one is required, or a WARNING is raised and nothing else happens.
  • The UPDATE will only change columns for the given parameters.
  • Can easily be expanded for n parameters.

Call

You can either call this the traditional way, with positional notation for parameters. This only allows you to omit the rightmost parameter(s):

SELECT update_site('foo', 'New York') -- no telephone

To be able to omit any parameter with a default value, you need to employ named notation in the call:

SELECT update_site(name := 'foo', _telephone := 123); -- no city

Or, to simplify even more, you can use mixed notation:

SELECT update_site('foo', _telephone := 123);

这篇关于具有可变数量输入参数的函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆