【问题标题】:Creating a character sequence on postgreSQL在 postgreSQL 上创建字符序列
【发布时间】:2019-04-23 17:37:15
【问题描述】:

所以,我在表列上引用了这个序列,每次插入时,它的值都由 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

【问题讨论】:

标签: sql postgresql postgresql-9.1


【解决方案1】:

接受挑战 ;)

我认为仅使用 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;

我知道这有点沉重,但我没有看到任何其他方式。 该功能可能并不完美,但我没有很多时间:)

希望对你有所帮助;)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-11
    • 2013-06-16
    • 1970-01-01
    • 2014-08-30
    • 1970-01-01
    相关资源
    最近更新 更多