简体   繁体   中英

dynamic multidimensional array in PL/pgSQL

I want to create twodimensional array in PL/pgSQL.

I have found example like this: myarray1 INT[2][2]:=array[[NULL,NULL],[NULL,NULL]];

but in my case I don't know an array of the table when I create table because the data are read from select query. How I can declare dynamic array ?


I ask in another way. In Oracle I can declare:

CREATE OR REPLACE TYPE MY_TYPE AS OBJECT
(
  var1 VARCHAR(20),
  ...
)
...

This is correspondent to RECORD is plpsql.

And then in Oracle I can declared

CREATE OR REPLACE TYPE MY_TYPE_MY_TYPES IS
table of MY_TYPE;

So I can store my result of select query in type of types which is just two-dimensional table. And I don't have to know number of rows returned by select query.

How I can acomplish this in plpsql ?

Thanks

in PostgreSQL, all types -including user defined ones- has respective array types.

so if you declare a composite type, you'll have an array type as well. you can find info about composite types here: https://www.postgresql.org/docs/current/static/rowtypes.html

here's an example:

1) create a new composite type

CREATE TYPE "myType" AS ( "id" INT, "name" VARCHAR );

2) demonstrate array presentation. type of the result is "myType"[]

SELECT
    ARRAY_AGG( v::"myType" ) AS v
FROM
    ( VALUES ( 1, 'a' ), ( 2, 'b' ), ( 3, 'c' ), ( 4, 'd' ) ) AS v

result is: {"(1,a)","(2,b)","(3,c)","(4,d)"}

3) unnesting "myType"[] array and returning as records

SELECT ( UNNEST( '{"(1,a)","(2,b)","(3,c)","(4,d)"}'::"myType"[] ) ).*

result is:

id | name
---|-----
 1 | a
 2 | b
 3 | c
 4 | d

You don't have to specify the size of arrays when you declare them :

myarray1 int[][];

but note that 2-dimensional arrays do not grow like 1-dimensional arrays :

create or replace function testfunc() returns void language plpgsql as $$
declare
  myarray1 int[][];
begin
  for i in 1..2 loop
    for j in 1..2 loop
      raise notice '% %', i, j;
      myarray1[i][j] := 1;
    end loop;
  end loop;
end$$;
select testfunc();

NOTICE:  1 1
NOTICE:  1 2
ERROR:  array subscript out of range
CONTEXT:  PL/pgSQL function "testfunc" line 7 at assignment

However you can assign another array to this variable:

create or replace function testfunc() returns void language plpgsql as $$
declare
  myarray1 int[][];
begin
  myarray1 := array[[NULL,NULL],[NULL,NULL]];
  for i in 1..2 loop
    for j in 1..2 loop
      raise notice '% %', i, j;
      myarray1[i][j] := 1;
    end loop;
  end loop;
end$$;
select testfunc();
NOTICE:  1 1
NOTICE:  1 2
NOTICE:  2 1
NOTICE:  2 2

I answer in another way :)

create view v as
select * 
from (values (1, 'Adam'), (2, 'Bob'), (3, 'Chris')) as foo(id, forename);

create or replace function f() returns text language plpgsql as $$
declare
  myarray1 v[];
begin
  select array_agg(row(id, forename)) from v into myarray1;
  return myarray1::text;
end$$;

select f();

                 f
------------------------------------
 {"(1,Adam)","(2,Bob)","(3,Chris)"}
(1 row)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM