6

我正在 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;

什么是最好的?要创建一个函数update_site(<all the columns of table>)和一个单独的函数update_site(id integer, <varchar column to update>),还是使用一个函数中的模式来定义区别?哪个选项更有效?一个独特的功能还是针对每个目的的不同功能?

4

2 回答 2

12

VARIADIC像甚至多态输入类型和动态 SQL 这样的高级特性非常强大。此答案的最后一章提供了一个高级示例:

但是对于像您这样的简单情况,您可以只使用函数参数的默认值。这一切都取决于确切的要求。
如果有问题的列都已定义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;

阅读手册中的默认值!

为了避免参数和列名之间的命名冲突,我习惯于在输入参数前加上_. 这是品味和风格的问题。

  • 第一个参数name没有默认值,因为它始终是必需的。
  • 其他参数可以省略。
  • 至少需要一个,或者WARNING提出 a 并且没有其他任何事情发生。
  • UPDATE只会更改给定参数的列。
  • 可以很容易地扩展为N 个参数。

函数调用

Postgres 9.5 开始

简单的方法是使用参数的位置表示法。这只允许省略最右边的参数:

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

命名符号允许省略任何具有默认值的参数:

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

两者都可以以混合表示法组合:

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 12 中仍然有效,但使用现代符号。

于 2013-05-28T09:59:50.607 回答
4

您需要研究以下几件事:

  • format使用函数及其%I和说明符动态构建 SQL ,然后使用;%L执行它 EXECUTE ... USING

  • 使用VARIADIC参数将可变数量的参数传递给函数,但需要注意的是它们都必须是相同的数据类型。

于 2013-05-28T00:30:22.577 回答