Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to pass a table or rows to a function in Postgresql?

Here is the code, the current type of argument is array, but I want to pass a table or rows instead.

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;
like image 201
Chen Avatar asked Mar 07 '26 02:03

Chen


2 Answers

A row is represented by a composite type, like

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

You can use such a type as function argument.

For each PostgreSQL table, there automatically exists a type with the same name and columns:

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

So you can create a function that takes an array of this type as argument:

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;$$;

You can call it like this (assuming that there are two rows in mytable):

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

Alternatively, you can create a function that takes a cursor as argument:

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;$$;

This can be called in a transaction as follows:

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

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

COMMIT;
like image 170
Laurenz Albe Avatar answered Mar 08 '26 16:03

Laurenz Albe


You can use the ARRAY_AGG constructor to convert a rowset to an array. For example, the following expression results in an array of all rows from table t1:

(SELECT ARRAY_AGG(t1) FROM t1)

Full example:

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));
like image 39
Andomar Avatar answered Mar 08 '26 14:03

Andomar



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!