类型表,从Oracle到PostgreSQL

时间:2018-09-12 22:34:50

标签: sql oracle postgresql plpgsql

我目前正在将一些过程从Oracle迁移到Postgres,这些过程使用的类型是为处理未知数量的值而创建的:

TYPE array_text IS TABLE OF VARCHAR2 (50);

因此他们可以声明一个变量,例如:

myValues in array_text;

并稍后以这种方式使用它:

myValues(1) := 'VALUE1';
myValues(2) := 'VALUE2';
...

因此,我一直在学习并尝试使用Postgres复制此行为,但直到现在我仍找不到正确的方法。我尝试创建一个像这样的复合类型:

CREATE TYPE array_text AS (
    val varchar(50)
);

CREATE TYPE array_text AS (
    v varchar(50)[]
);

但是我不能像使用原始方法那样使用它们,实际上我无法创建成功的测试。

如何获得这种行为或类似的东西?因此,我可以像在Oracle中一样设置和获取值,甚至计算其长度

2 个答案:

答案 0 :(得分:4)

在Postgres中,它比在Oracle中简单得多-您无需定义集合类型。只需声明一个数组即可。

在Postgres中,TYPE array_text IS TABLE OF VARCHAR2 (50);text[]的明智,最有效的替代方法。

要获取数组的长度,请使用cardinality()。您不需要特殊的方法来扩展其容量,只需为所需的索引分配一个值即可。唯一的主要区别是,Postgres中没有缩小数组的简单方法。

declare
   myValues text[];
   num_values int;
begin

  myValues[1] := 'VALUE1';
  myValues[2] := 'VALUE2';

  num_values := cardinality(myvalues); // yields 2

  myValues[3] := 'VALUE3';
  num_values := cardinality(myvalues); // yields 3
end;

要扩展答案:您还可以使用类似的表类型。因此,您无需定义中间的“表”集合类型,只需将表的类型用于数组即可。

create table person
(
  id integer,
  firstname text,
  lastname text
);

然后您可以使用

do
$$
declare
  people_list person[];
begin
  people_list[1] := row(42, 'Arthur', 'Dent')::person;
  raise notice 'Name %', people_list[1].firstname;
end;
$$

答案 1 :(得分:2)

postgres不允许具有未命名列的表(或复合类型)

与表数组不同的是,数组可以是多维的,也可以从[1]或[0]处开始,因此您可能需要检查输入格式是否正确(除非输入错误) 隐式导致错误)

CREATE TYPE array_text AS (
    val varchar(50)[]
);

但这会创建一个具有一个属性的复合类型,该属性是一个数组...因此您需要使用.val来访问该数组。

jasen=# do $$ 
declare a array_text;
begin 
   a.val[0]='won';
   a.val[1]='too';
   raise notice 'len=%',array_length(a.val,1); end;
$$;
NOTICE:  len=2
DO

但是如果您在线声明数组,则可以使用简单的名称。

jasen=# do $$ 
declare a varchar(50)[];
begin 
   a[5]='eigh';
   a[6]='bee';
   raise notice 'len=%',array_length(a,1); end;
$$;
NOTICE:  len=2
DO