sql >> Base de Datos >  >> RDS >> PostgreSQL

Creando una secuencia de caracteres en postgreSQL

Reto aceptado;)

No creo que haya forma de hacerlo solo con el mecanismo de secuencia de PostgreSQL ( 1 ) Pero si realmente necesita algo como eso (y estoy muy interesado en saber por qué necesita algo como esto), puede hacer una función que le devuelva el siguiente valor que desea y ponerlo en un activador.

Por ejemplo, cree una tabla primero:

create table test (test_id varchar);

Use una función como esta a continuación

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

Adjunte la función a un disparador anterior

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

Inserte un valor que realmente no importe (se cambiará de todos modos)

insert into test values ('ttt');

Entonces puedes observar que tienes el carácter correcto.

select *
from test;

Sé que es un poco pesado, pero no veo ningún otro. La función probablemente no sea perfecta, pero no tengo mucho tiempo :)

Espero que te ayude;)