Генерация следующей алфавитной последовательности из данного алфавита в оракуле - PullRequest
0 голосов
/ 13 декабря 2018

Мне нужно сгенерировать идентификаторы в алфавитном порядке.

Предположим, существующий идентификатор - A
Поэтому мне нужно проверить максимальное количество существующих букв, а затем сгенерировать следующее.
Как следующий будет - B и так далее.Таким образом, я сгенерировал от A до Z.

Но после "Z" снова нужно сгенерировать AA, AB и т. Д. Как мудрый.

Я попытался использовать ниже запрос-

SELECT REGEXP_SUBSTR(CHR(ASCII(TRIM (REGEXP_SUBSTR ('Z_2203','[^_]+')))+1),'[A-Za-z]') FROM DUAL;

пример данных из комментария:

Present_id

    A_2004 
    B_2004
    C_2004
    '
    '
    '
    Z_2004

Ожидаемый результат -

 B 
 C
 D
 '
 '
 '
 AA
 AB

Ответы [ 2 ]

0 голосов
/ 13 декабря 2018

Вы можете использовать что-то похожее на эту рекурсивную функцию:

create or replace function alpha_id(i_id in varchar2) return varchar2 is
begin
  if trim(translate(i_id, 'Z', ' ')) is null then 
    return rpad('A', nvl(length(i_id), 0) + 1, 'A');
  end if;

  if substr(i_id, length(i_id), 1) = 'Z' then 
    return alpha_id(substr(i_id, 1, length(i_id) - 1))||'A';
  else
    return substr(i_id, 1, length(i_id) - 1) 
        || chr(ascii(substr(i_id, length(i_id), 1)) + 1);
  end if;
end alpha_id;

Здесь особо отмечаются только манипуляции со строками и рекурсивный вызов, если последний символ равен Z.Тест:

with t(rn, id) as (
    select 1, 'A'   from dual union all
    select 2, 'N'   from dual union all
    select 3, 'Z'   from dual union all
    select 4, 'AA'  from dual union all
    select 5, 'BP'  from dual union all
    select 6, 'QZ'  from dual union all
    select 7, 'ZZ'  from dual union all
    select 8, 'BPZ' from dual union all
    select 9, 'ZZZ' from dual )
select rn, id, alpha_id(id) next_id from t;

Результат:

    RN ID  NEXT_ID
 ----- --- ---------
     1 A   B
     2 N   O
     3 Z   AA
     4 AA  AB
     5 BP  BQ
     6 QZ  RA
     7 ZZ  AAA
     8 BPZ BQA
     9 ZZZ AAAA
0 голосов
/ 13 декабря 2018

это будет работать:

SELECT * FROM D061_WORDS;
A_2004
B_2004
Z_2004

select case when ascii(chr(ascii(substr(a,1,1))+1))<=ascii('Z') then
chr(ascii(substr(a,1,1))+1) when ascii(chr(ascii(substr(a,1,1))+1))>=ascii('Z') then
'A'||chr(ascii(chr(ascii(substr(a,1,1))+1))-26) end from D061_WORDS;

B
C
AA
...