具有可变数量输入参数的函数 [英] Functions with variable number of input parameters
问题描述
我在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屋!