postgresql 具有可变数量输入参数的函数
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16782199/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Functions with variable number of input parameters
提问by anairinac
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.
我正在 PostgreSQL 数据库中创建一个存储过程(函数),它根据输入更新表。为了创建可变数量的参数函数,我创建了一个名为 mode 的额外输入参数,我用它来控制我在更新查询中使用的参数。
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?
什么是最好的?创建一个函数update_site(<all the columns of table>)
和一个单独的函数update_site(id integer, <varchar column to update>)
,还是在一个函数中使用模式来定义区别?哪个选项更有效?一种独特的功能还是针对每种用途的不同功能?
回答by Erwin Brandstetter
Advanced features like VARIADIC
or even polymorphic input typesand dynamic SQL are very powerful. The last chapter in this answer provides an advanced example:
诸如VARIADIC
甚至多态输入类型和动态 SQL 之类的高级功能非常强大。本答案的最后一章提供了一个高级示例:
But for a simple case like yours, you can just use default valuesfor function parameters. It all depends on exact requirements.
Ifthe columns in question are all defined NOT NULL
, this would probably be simpler and faster:
但是对于像您这样的简单情况,您可以只使用函数参数的默认值。这一切都取决于确切的要求。
如果有问题的列都已定义NOT NULL
,这可能会更简单、更快:
CREATE OR REPLACE FUNCTION update_site(_name text -- always required
, _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")
, "Telephone" = COALESCE(_telephone, "Telephone")
WHERE "SiteName" = _name;
END
$func$ LANGUAGE plpgsql;
Read about 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 omitted.
- At least one is required, or a
WARNING
is raised and nothing else happens. - The
UPDATE
will only change columns for given parameters. - Can easily be expanded for Nparameters.
- 第一个参数
name
没有默认值,因为它始终是必需的。 - 其他参数可以省略。
- 至少需要一个,或者 a
WARNING
被引发并且没有其他任何事情发生。 - 将
UPDATE
只会更改列给定参数。 - 可以轻松扩展N 个参数。
Function call
函数调用
Since Postgres 9.5:
从Postgres 9.5 开始:
The simple way is with positional notationfor parameters. This only allows to omit the rightmost parameter(s):
简单的方法是使用参数的位置符号。这只允许省略最右边的参数:
SELECT update_site('foo', 'New York'); -- no telephone
Named notationallows to omit anyparameter that has a default value:
命名符号允许省略任何具有默认值的参数:
SELECT update_site(name => 'foo', _telephone => 123); -- no city
Both can be combined in mixed notation:
两者都可以混合表示法组合:
SELECT update_site('foo', _telephone => 123); -- still no city
In Postgres 9.4or older, :=
was used for assignment in the call:
在Postgres 9.4或更早版本中,:=
用于调用中的赋值:
SELECT update_site(name := 'foo', _telephone := 123);
SELECT update_site('foo', _telephone := 123);
Still valid in Postgres 12 for backward compatibility, but rather use the modern notation.
为了向后兼容,在 Postgres 12 中仍然有效,而是使用现代表示法。
回答by Craig Ringer
There are a few things you'll want to look into:
您需要了解以下几点:
Dynamically building the SQL using the
format
function and its%I
and%L
specifiers, then executing it withEXECUTE ... USING
; andUsing
VARIADIC
parameters to take variable numbers of arguments to the function, with the caveat that they must all be the same data type.
动态使用生成SQL
format
函数及其%I
与%L
符,然后执行它EXECUTE ... USING
; 和使用
VARIADIC
参数将可变数量的参数传递给函数,但需要注意的是它们都必须是相同的数据类型。