【问题标题】:Creating an alphanumeric sequence创建字母数字序列
【发布时间】:2015-08-25 13:57:27
【问题描述】:

我想创建一个生成如下值的序列:

A00000000
A00000001
..
..
..
A99999999
B00000000
B00000001
..
..

它应该使用初始字母字符 A 生成,一旦达到 A99999999,它应该更改为 B 等等。

Oracle 中的正常序列不会给出字母数字序列。如何在这种模式中生成顺序值?

【问题讨论】:

  • 这个答案可能会有所帮助:stackoverflow.com/questions/26943146/…
  • 标题中的“随机”是指什么?
  • 随机意味着以该格式生成的序列
  • @Loci ..在那个问题中,有一个不变的词'INV',但在我的情况下,它应该与字母 A 一起生成,一旦达到 99 ..它应该更改为 B 和儿子跨度>
  • @Arun 只能创建整数值序列。

标签: sql oracle function plsql sequence


【解决方案1】:

您必须创建 1 个序列和 1 个转换函数:

CREATE SEQUENCE num_seq
START WITH 6500000000
INCREMENT BY 1
MAXVALUE 9099999999;

FUNCTION next_id(seq_name) RETURN VARCHAR2 IS
  x VARCHAR2(28);
BEGIN
  EXECUTE IMMEDIATE 'SELECT TRIM(TO_CHAR(' || seq_name || '.NextVal)) FROM dual' INTO x;
  RETURN CHR(TO_NUMBER(SUBSTR(x, 1, 2))) || SUBSTR(x, 3);
END;

当使用next_id('num_seq') 调用时,该函数会生成从A00000000Z99999999 的ID。诀窍是 CHR(ascii_code) 函数,它返回位置 65-90 上的字符,即 A-Z。

已编辑:
函数更通用 - 您可以将任何序列作为参数传递,并且可以在 SEQUENCE 定义的 START WITH 和 MAXVALUE 子句中简单地添加/删除数字,而无需更改函数。

【讨论】:

  • 感谢 Pavel :) 它可以正常工作,我将根据我的要求修改序列
  • 不管怎样,一旦它到达 Z99999999,我需要从 AA0000000、AA0000001 开始下一次搜索.....就像这样......@Pavel
  • @arun 是的,1 seq 是可能的。您必须计算范围开始,然后取相应的范围,减去开始并转换值。例如。 r0~a00000000=0, r1~aa0000000=2600000000, r2~aaa000000=2600000000+26*26*10^7, r(i)=r(i-1)+26^i*10^(9-i)
【解决方案2】:

您可以创建一个数字序列,但可以将前两个字符即时转换为十六进制值。如果您将序列创建为:

create sequence s42 start with 1000000000 maxvalue 1599999999;

...然后有一个功能来简化,虽然你并不严格需要它:

create function alpha_seq return varchar2 as
begin
  return to_char(trunc(s42.nextval / 100000000), 'FMXX')
    || substr(to_char(s42.currval, 'FM0000000000'), 3);
end;
/

序列值始终为 10 位。前两个被拉出并转换为等效的十六进制,然后附加其余的。

作为演示:

select alpha_seq from dual
connect by level < 5;

ALPHA_SEQ
----------
A00000000 
A00000001 
A00000002 
A00000003 

-- skip a load of numbers
alter sequence s42 increment by 99999994;
select alpha_seq from dual;

ALPHA_SEQ
----------
A99999997 

alter sequence s42 increment by 1;

select alpha_seq from dual
connect by level < 5;

ALPHA_SEQ
----------
A99999998 
A99999999 
B00000000 
B00000001 

-- skip a load of numbers
alter sequence s42 increment by 99999996;
select alpha_seq from dual;

ALPHA_SEQ
----------
B99999997 

alter sequence s42 increment by 1;

select alpha_seq from dual
connect by level < 5;

ALPHA_SEQ
----------
B99999998 
B99999999 
C00000000 
C00000001 

序列上的最大值意味着它将上升到 F99999999,如果再次调用 nextval,则会出错。我假设第一个数字应该是十六进制;如果你想要 A-Z,那么你可以让序列以 6500000000 开头,并将前两位数字转换为带有 chr() 的字符,而不是将 65 转换为 A 等。

【讨论】:

  • 不管怎样,一旦到达Z99999999,我需要从AA0000000开始下一次搜索,AA0000001.....像这样......
  • @Arun - 仅用于前两位数,或者然后是 AAA... 等,一旦用完?将每个数字的行为从 0-9 更改为 0-Z 并不容易。去 19, 1A, ... 1F, 20, ... 29, 2A, ... 即在 36 为底会更容易。
  • 这是否可以通过使用现有序列本身来完成?
【解决方案3】:
function generate_universal_id(pid){
    let BASE_VALUE = 100000000;
    let prefix = ['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'];
    let prefix_index = pid/100000;
    let intvalue = Math.floor( prefix_index );
    prefix = prefix[intvalue];
    BASE_VALUE = BASE_VALUE + pid;
    BASE_VALUE = BASE_VALUE.toString().slice(-5);

    if(pid == 100000 || pid == 200000 || pid == 300000 || pid == 400000 || pid == 500000 || pid == 600000 || pid == 700000 || pid == 800000 || pid == 900000 ){
        BASE_VALUE = BASE_VALUE + 1;
    }
    BASE_VALUE = BASE_VALUE.toString().slice(-5)
    let universal_id = `${prefix}${BASE_VALUE}`
    console.log(universal_id);
}

generate_universal_id(100000)

【讨论】:

  • 您好,欢迎来到 stackoverflow。到目前为止,您的问题还很不清楚,因为它实际上并未包含任何关于您要达到的目标、您遇到并试图解决的问题的描述。如果您有问题需要帮助,最好的办法是创建一个Minimal, Complete and Verifiable Example。如果您认为代码正在执行您想要的操作,但您希望听到人们对其发表评论并可能进行改进,您可以考虑将其发布到 codereview.stackexchange.com
  • 您的函数是用哪种语言编写的?它当然看起来不像 sql-ish。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-01-12
  • 1970-01-01
  • 1970-01-01
  • 2023-02-17
  • 1970-01-01
  • 2015-07-01
  • 2021-02-08
相关资源
最近更新 更多