Создание последовательности символов на postgreSQL - PullRequest
0 голосов
/ 23 апреля 2019

Итак, у меня есть эта последовательность, на которую ссылаются в столбце таблицы, где каждый раз, когда я делаю вставку, ее значение определяется как nextval('ptable_pr_codigo_seq'::regclass)

CREATE SEQUENCE public.ptable_pr_codigo_seq
  INCREMENT 1
  MINVALUE 1
  MAXVALUE 9223372036854775807
  START 103
  CACHE 1;
ALTER TABLE public.ptable_pr_codigo_seq
  OWNER TO postgres;

Теперь, как я могу создать новую последовательность так, каждый раз, когда я делаювставить значение не число, а символ в диапазоне [A ~ ZZZ]?.


Example: First insert column value = A
         Second                    = B
         Third                     = C
         27th                      = AA
         ...
         ?Th                       = ZZZ

1 Ответ

0 голосов
/ 24 апреля 2019

Вызов принят;)

Я не думаю, что есть какой-либо способ сделать это только с помощью механизма последовательности PostgreSQL ( 1 ), но если вам действительно нужно что-то подобное (и яочень интересно, почему вам нужно что-то подобное), вы можете сделать функцию, которая вернет вам следующее желаемое значение и поместить его в триггер.

Например, сначала создайте таблицу:

create table test (test_id varchar);

Используйте функцию, подобную приведенной ниже

create or replace function next_id_test()
 returns trigger language plpgsql as $function$
begin
    with cte_conform_char_list as
    (
        select val, row_number() over (order by val), lead(val) over (order by val)
        from (values ('A'), ('B'), ('C'), ('D'), ('E'), ('F')) as t(val) -- you can continue this list as much as you want it ;)
        order by 1
    )
    , cte_built_char_list as
    (
        select 
            cte.val
            , cte.row_number
            , coalesce(cte.lead, cte_2.val) as next_char
        from cte_conform_char_list cte
            left outer join cte_conform_char_list cte_2
                on cte_2.row_number = cte.row_number - (select max(row_number) from cte_conform_char_list) +1
    )
    select 
        case 
            when row_number < (select max(row_number) from cte_built_char_list)
                then repeat(next_char, cast(rank() over (partition by row_number order by test_id) as int)) 
                else repeat(next_char, cast(rank() over (partition by row_number order by test_id) + 1 as int))
        end as next_test_id into new.test_id
    from test T
        inner join cte_built_char_list cte on substring(T.test_id from 1 for 1) = cte.val
    order by char_length(test_id), test_id;

    return new;
end;
$function$;

Прикрепите функцию к триггеру до

create trigger tg_test before insert on test for each row execute procedure next_id_test();

Вставьте значение, которое на самом деле не имеет значения (оно будетв любом случае изменилось)

insert into test values ('ttt');

Тогда вы можете заметить, что у вас правильный персонаж.

select *
from test;

Я знаю, что это немного тяжелый путь, но я не вижу другого.Функция, вероятно, не идеальна, но у меня не так много времени:)

Надеюсь, она вам поможет;)

...