Reputation: 11
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
Upvotes: 1
Views: 9016
Reputation: 956
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
Upvotes: 1
Reputation:
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)
Upvotes: 0
Reputation:
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
Upvotes: 0