【问题标题】:How to pass a table or rows to a function in Postgresql?如何将表或行传递给 Postgresql 中的函数?
【发布时间】:2017-05-15 12:17:29
【问题描述】:

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

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;

【问题讨论】:

    标签: database postgresql


    【解决方案1】:

    一行用复合类型表示,比如

    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;
    

    【讨论】:

    • 谢谢,顺便问一下,列名转换成数组后会保存吗?如果没有,如何访问特定列?
    • 数组是mytable的数组,所以每个entry都有mytable的属性。你可以这样引用它们:(arg[2]).name.
    【解决方案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));
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-08-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-06-22
      • 1970-01-01
      • 2014-07-16
      相关资源
      最近更新 更多