我正在try 编写一个带有可选参数的PL/pgSQL函数.它基于过滤后的记录集(如果指定)执行查询,否则会对表中的整个数据集执行查询.

例如(PSEUDO CODE):

CREATE OR REPLACE FUNCTION foofunc(param1 integer, param2 date, param2 date, optional_list_of_ids=[]) RETURNS SETOF RECORD AS $$
    IF len(optional_list_of_ids) > 0 THEN
        RETURN QUERY (SELECT * from foobar where f1=param1 AND f2=param2 AND id in optional_list_of_ids);
    ELSE
        RETURN QUERY (SELECT * from foobar where f1=param1 AND f2=param2);
    ENDIF
$$ LANGUAGE SQL;

实现这一功能的正确方法是什么?

顺便说一句,我想知道如何在另一个外部函数中调用这样的函数.我会这样做——是正确的,还是有更好的方法?

CREATE FUNCTION foofuncwrapper(param1 integer, param2 date, param2 date) RETURNS SETOF RECORD AS $$
BEGIN
   CREATE TABLE ids AS SELECT id from foobar where id < 100;
   RETURN QUERY (SELECT * FROM foofunc(param1, param2, ids));
END
$$ LANGUAGE SQL

推荐答案

自PostgreSQL 8.4(您似乎正在运行)以来,共有default values for function parameters个.如果将参数放在最后并提供默认值,则只需在调用中忽略它:

CREATE OR REPLACE FUNCTION foofunc(_param1 integer
                                 , _param2 date
                                 , _ids    int[] DEFAULT '{}')
  RETURNS SETOF foobar         -- declare return type!
  LANGUAGE plpgsql AS
$func$
BEGIN  -- required for plpgsql
   IF _ids <> '{}'::int[] THEN  -- exclude empty array and NULL
      RETURN QUERY
      SELECT *
      FROM   foobar
      WHERE  f1 = _param1
      AND    f2 = _param2
      AND    id = ANY(_ids);    -- "IN" is not proper syntax for arrays
   ELSE
      RETURN QUERY
      SELECT *
      FROM   foobar
      WHERE  f1 = _param1
      AND    f2 = _param2;
   END IF;
END  -- required for plpgsql
$func$;

要点:

  • 关键字100用于声明参数默认值.简短的备选方案:101.

  • 我从混乱的示例中删除了多余的param1.

  • 因为返回SELECT * FROM foobar,所以将返回类型声明为RETURNS SETOF foobar而不是RETURNS SETOF record.使用匿名记录的后一种形式非常笨拙,每次调用都必须提供一个列定义列表.

  • 我使用整数(int[])数组作为函数参数.相应地修改了IF表达式和WHERE条款.

  • IF条语句在普通SQL中不可用.必须是LANGUAGE plpgsql.

无论有没有_ids:

SELECT * FROM foofunc(1, '2012-1-1'::date);

实际上是一样的:

SELECT * FROM foofunc(1, '2012-1-1'::date, '{}'::int[]);

你必须确保电话是明确的.如果你有另一个同名的函数和两个参数,Postgres可能不知道该选哪个.显式铸造(就像我演示的)缩小了它的范围.除此之外,非类型化的字符串文字也可以工作,但显式永远不会有什么坏处.

从另一个函数中调用:

CREATE FUNCTION foofuncwrapper(_param1 integer, _param2 date)
  RETURNS SETOF foobar
  LANGUAGE plgpsql AS
$func$
DECLARE
   _ids int[] := '{1,2,3}';
BEGIN
   -- whatever

   RETURN QUERY
   SELECT * FROM foofunc(_param1, _param2, _ids);
END
$func$;

Postgresql相关问答推荐

Select 二维数组中的特定元素PostgreSQL

无法继承BYPASSRLS

Postgres:这是对OVERLAPS谓词的等效重写吗?

使用正则表达式计算 SQL 查询中 WHERE 过滤器的数量

PostgreSQL:如何避免被零除?

如何在 PostgreSQL hstore 中使用通配符查询值

Nodemon - 安装期间clean exit - waiting for changes before restart

如何在 Postgres 中的列上删除唯一约束?

INSERT RETURNING 是否保证以 right的顺序返回?

获取带有时区偏移的日期

SELECT INTO 具有多个归因

gem install pg 无法绑定到 libpq

避免 created_at 和 updated_at 由 sequelize 自动生成

Postgres 外键on update和on delete选项如何工作?

如何创建 postgres 数据库模式的 sql 脚本?

在 PostgreSQL 数组中查找值的位置

从长时间的postgres转换日期

python pip install psycopg2 安装错误

如何为 Postgres psql 设置时区?

PostgreSQL - pg_config -bash:pg_config:command not found