oracle 多用户无冲突号码顺序插入及IP地址分配

8ulbf1ek  于 2023-10-16  发布在  Oracle
关注(0)|答案(1)|浏览(114)

我有一个问题,当多个用户/IP地址同时提交条目时,顺序插入数据而不冲突数字。我的数据库表中有两列:“ID”和“NO”。“ID”作为唯一标识符,而“NO”表示订单号,该订单号对用户插入的编号进行排序。
例如,如果用户A和用户B同时提交,则“否”数据可能是重复的,因为它是同时命中的。
我创建了一个函数,它将生成“NO”格式,但“NO”中仍然存在重复。
下面是我的函数:

FUNCTION get_next_no
(
 P_TYPE        IN VARCHAR2
)
RETURN VARCHAR2 IS PRAGMA autonomous_transaction;

v_last_sequence     INT;
v_no                VARCHAR2(24 Byte);

BEGIN        
    SELECT  MAX(SUBSTR(no,17,8))
    INTO    v_last_sequence
    FROM    P_MAIN
    WHERE   TO_CHAR(p_date, 'YYYYMM')  = TO_CHAR(SYSDATE, 'YYYYMM')
    AND     TYPE = P_TYPE
    ;

    IF v_last_sequence IS NULL THEN
        v_last_sequence := 0;
    END IF;
    
    IF P_TYPE = 'CONV' THEN
        v_no := 'CERC-00-' || TO_CHAR(SYSDATE, 'YYYY') || '-' || TO_CHAR(SYSDATE, 'MM') || '-' || LPAD(v_last_sequence + 1, 8, '0');
    ELSE 
        v_no := 'CERS-00-' || TO_CHAR(SYSDATE, 'YYYY') || '-' || TO_CHAR(SYSDATE, 'MM') || '-' || LPAD(v_last_sequence + 1, 8, '0');
    END IF;
    

    RETURN v_no;
END get_next_no;

任何指导或建议将不胜感激。感谢您!
我正在寻求一种解决方案或方法来有效地处理这种情况,保证分配的“NO”值是连续的和唯一的,即使多个用户或IP地址并发提交。

kpbwa7wx

kpbwa7wx1#

最简单的方法就是使用一个标准的序列对象,不要再担心“NO”中的空白。这样,没有重复,没有锁定,没有烦恼。
如果你真的想走上无间隙的道路,你需要一个单独的表加上一些锁逻辑来序列化访问。对于一个合理的可扩展解决方案,下面有一些代码,我在这里介绍一下
https://youtu.be/B5JltFoe5Ho

create table seqs
  ( name   varchar2(100),
    constraint seqs_pk primary key ( name )
  )
organization index ;

insert into seqs
select 'SEQ'||rownum
from dual
connect by level <= 5;

select * from seqs;

create table seqs_numbers
  ( name   varchar2(100),
    num    number(10),
    state  varchar2(10),
    constraint seqs_numbers_pk primary key ( name,num ),
    constraint seqs_numbers_fk foreign key ( name) references seqs ( name ) on delete cascade,
    constraint seqs_numbers_ck check ( state in ('free','used'))
  )
organization index ;

insert into seqs_numbers
select s.name, num, 'free'
from   seqs s,
       ( select level num from dual 
         connect by level <= 1000 );
commit;

select * from seqs_numbers
where  name = 'SEQ1'
and    rownum <= 12;

create or replace
function get_seq(p_name varchar2) return number is
  l_seq number;
  cursor next_seq is
    select num
    from   seqs_numbers
    where  name = p_name
    and    state='free'
    order by num
    for update skip locked;
begin
  open next_seq;
  fetch next_seq into l_seq;
  close next_seq;
  update seqs_numbers
  set    state = 'used'
  where  name = p_name
  and    num = l_seq;
  
  return l_seq;
end;
/

不过说真的按顺序进行

相关问题