ТИП ТАБЛИЦЫ, от Oracle до PostgreSQL - PullRequest
       1

ТИП ТАБЛИЦЫ, от Oracle до PostgreSQL

0 голосов
/ 13 сентября 2018

В настоящее время я перемещаю некоторые процедуры из 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 голосов
/ 13 сентября 2018

В 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;

Чтобы расширить ответ: вы также можете использовать такие типы таблиц. Таким образом, вам не нужно определять промежуточную «таблицу» типа коллекции, просто чтобы использовать тип таблицы для массива.

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;
$$
0 голосов
/ 13 сентября 2018

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
...