我正在PostgreSQL DB中创建一个存储过程(函数),它根据输入更新表。为了创建一个可变数量的参数函数,我正在创建一个名为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;
什么是最好的?要创建函数update_site(<all the columns of table>)
和单独的函数update_site(id integer, <varchar column to update>)
,还是在一个函数中使用模式来定义差异?哪个选项更有效?一个独特的功能或不同的功能用于各种目的?
答案 0 :(得分:9)
VARIADIC
甚至polymorphic input types和动态SQL等高级功能非常强大。本答案的最后一章提供了一个高级示例:
但对于像您这样的简单案例,您可以使用默认值作为函数参数。这完全取决于具体要求
如果,相关列都已定义NOT NULL
,这可能会更简单,更快:
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")
, "Telephone" = COALESCE(_telephone, "Telephone")
WHERE "SiteName" = _name;
END
$func$ LANGUAGE plpgsql;
请务必阅读default values in the manual!
为了避免参数和列名之间的命名冲突,我习惯在输入参数前加_
。这是品味和风格的问题。
name
没有默认值,因为它始终是必需的。WARNING
被引发,没有其他事情发生。UPDATE
只会更改给定参数的列。对于 Postgres 9.5 或更新版本:
简单的方法是使用positional notation参数。这只允许省略最右边的参数:
SELECT update_site('foo', 'New York'); -- no telephone
Named notation允许省略任何具有默认值的参数:
SELECT update_site(name => 'foo', _telephone => 123); -- no city
两者都可以合并到mixed notation:
SELECT update_site('foo', _telephone => 123); -- still no city
在 Postgres 9.4 之前, :=
在通话中用于分配:
SELECT update_site(name := 'foo', _telephone := 123);
SELECT update_site('foo', _telephone := 123);
在Postgres 11中仍然有效,以实现向后兼容,但不要在当前版本中使用它。
答案 1 :(得分:3)
您需要了解一些事项:
使用format
函数及其%I
和%L
说明符动态构建SQL,然后使用EXECUTE ... USING
执行它;以及
使用VARIADIC
参数为函数提供可变数量的参数,但需要注意的是它们必须都是相同的数据类型。