TYPE IS TABLE OF,从 Oracle 到 PostgreSQL

KES*_*ESO 2 sql oracle postgresql plpgsql

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

TYPE array_text IS TABLE OF VARCHAR2 (50);
Run Code Online (Sandbox Code Playgroud)

所以他们可以声明一个变量,如:

myValues in array_text;
Run Code Online (Sandbox Code Playgroud)

稍后以这种方式使用它:

myValues(1) := 'VALUE1';
myValues(2) := 'VALUE2';
...
Run Code Online (Sandbox Code Playgroud)

所以我一直在学习并尝试使用 Postgres 复制这种行为,但直到现在我找不到合适的方法。我尝试创建一个复合类型,如:

CREATE TYPE array_text AS (
    val varchar(50)
);
Run Code Online (Sandbox Code Playgroud)

或者

CREATE TYPE array_text AS (
    v varchar(50)[]
);
Run Code Online (Sandbox Code Playgroud)

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

我怎么能得到这种行为或类似的东西?所以我可以设置和获取值,甚至像在 Oracle 中一样计算它的长度

a_h*_*ame 5

在 Postgres 中它比在 Oracle 中简单得多——您不需要定义集合类型。只需声明一个数组。

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

要获取数组的长度,请使用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;
Run Code Online (Sandbox Code Playgroud)

扩展答案:您也可以使用这样的表类型。所以你不需要定义一个中间的“表”集合类型,只需要将表的类型用于数组。

create table person
(
  id integer,
  firstname text,
  lastname text
);
Run Code Online (Sandbox Code Playgroud)

然后你可以使用

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