问题
Is the following possible?
I want to have a procedure written in PL/pgSQL that takes as parameter something like "collection of row", I mean I need to pass to function a dictionary-like structure:
Pseudocode:
function_name({key1:val1,key2:val2, key3:val3 [, ...] })
回答1:
With modern day PostgreSQL you can simplify such a function.
Test setup:
CREATE TABLE tbl1 (id int, value text);
No need to create a type explicitly in this case (if the type is based on a table row), it is created for every table implicitly.
Function:
CREATE FUNCTION f_insert_rows_into_tbl1(tbl1[])
RETURNS VOID AS
$BODY$
INSERT INTO tbl1 (id,value)
SELECT (a).*
FROM (SELECT unnest($1) AS a) x;
$BODY$ LANGUAGE sql;
Call:
SELECT f_insert_rows_into_tbl1('{"(1,foo)","(2,bar)"}');
Note the input syntax for an array of rows!
回答2:
Visit this site http://postgres.cz/wiki/PostgreSQL_SQL_Tricks and search for Array to table. There may be other ways on newer versions, but I had this in my bookmarks from awhile back. Source from website:
CREATE OR REPLACE FUNCTION unpack(anyarray)
RETURNS SETOF anyelement AS $$
SELECT $1[i]
FROM generate_series(array_lower($1,1),
array_upper($1,1)) g(i);
$$ LANGUAGE sql STRICT IMMUTABLE;
select unpack(array['a','b','c']);
回答3:
I think you can use a composite type and array argument. Something like (untested):
create type keyvalue as (
key text,
value text
);
create function function_name(keyvalue[]) returns null as $$
declare
keyvalue x;
begin
foreach x in array $1 loop
insert into tablename(key,value) values (x.key, x.value);
end loop
end;
$$ language plpgsql;
This will not be a true dictionary, as you can add duplicate keyvalues and keyvalues with the same key and different value to this array. But just for passing arguments to a function it should be enough.
Using unpack() mentioned by JustBob will allow to not use a loop, which is not very SQL-y, but treat this array as a set.
来源:https://stackoverflow.com/questions/9640087/pl-pgsql-array-of-rows