如何将一个或多个表传递给Postgresql中的函数?

时间:2017-05-15 12:17:29

标签: database postgresql

这是代码,当前的参数类型是数组,但我想传递一个或多个表。

create or replace function skyband_sortedlist(rest point[]) 
    returns setof point
as $$ 
declare

    last_x integer :=0;
    last_y integer :=0;
begin
    for ipoint in (select s0.x,s0.y from unnest(rest))
    loop 
        if ipoint.x>last_x and ipoint.y<>last_y then
            last_x = ipoint.x;
            last_y = ipoint.y;
            return next;
        end if;
    end loop;
end;
$$ language plpgsql;

2 个答案:

答案 0 :(得分:2)

行由复合类型表示,如

CREATE TYPE mytype  AS (
   id integer,
   name text,
   fromdate timestamp with time zone
);

您可以将此类型用作函数参数。

对于每个PostgreSQL表,会自动存在一个具有相同名称和列的类型:

CREATE TABLE mytable (
   id integer PRIMARY KEY,
   name text,
   fromdate timestamp with time zone NOT NULL
);

因此,您可以创建一个函数,该函数将此类型的数组作为参数:

CREATE OR REPLACE FUNCTION myfunc(arg mytable[]) RETURNS void
   LANGUAGE plpgsql IMMUTABLE STRICT AS
$$DECLARE
   t mytable;
BEGIN
   FOREACH t IN ARRAY arg LOOP
      RAISE NOTICE 'id = %', t.id;
   END LOOP;
END;$$;

您可以这样调用它(假设mytable中有两行):

SELECT myfunc(array_agg(mytable)) FROM mytable;
NOTICE:  id = 1
NOTICE:  id = 2
┌────────┐
│ myfunc │
├────────┤
│        │
└────────┘
(1 row)

或者,您可以创建一个将游标作为参数的函数:

CREATE OR REPLACE FUNCTION myfunc(arg refcursor) RETURNS void
   LANGUAGE plpgsql IMMUTABLE STRICT AS
$$DECLARE
   t mytable;
BEGIN
   LOOP
      FETCH NEXT FROM arg INTO t;
      EXIT WHEN NOT FOUND;
      RAISE NOTICE 'id = %', t.id;
   END LOOP;
END;$$;

这可以在事务中调用如下:

BEGIN;
DECLARE c CURSOR FOR SELECT * FROM mytable;
SELECT myfunc('c');

NOTICE:  id = 1
NOTICE:  id = 2
┌────────┐
│ myfunc │
├────────┤
│        │
└────────┘
(1 row)

COMMIT;

答案 1 :(得分:2)

您可以使用ARRAY_AGG构造函数将行集转换为数组。例如,以下表达式将生成表t1中所有行的数组:

(SELECT ARRAY_AGG(t1) FROM t1)

完整示例:

CREATE TABLE t1 (id INT, name TEXT);
INSERT INTO t1 values (1, 'Joe'), (2, 'Arnold');

CREATE OR REPLACE FUNCTION public.f1(arg t1[])
 RETURNS SETOF t1
 LANGUAGE sql
AS $$
SELECT * FROM UNNEST(arg);
$$;

SELECT f1((SELECT ARRAY_AGG(t1) FROM t1));