解决Oracle序列重复问题(oracle序列重复)

在开发中,使用Oracle的Sequence经常会用到,用于生成自增的主键字段,意在保证创建的数据每行主键是独一无二的。 但是,由于各种原因,经常会出现Sequence重复,从而引发数据库异常。

要解决这一Oracle序列重复问题,我们可以在并发环境中加入一定的逻辑:

1、使用存储过程来实现:可以在存储过程里,先获取一个Sequence值,然后依次判断数据库中是否存在相同值,如果不存在则插入;如果存在,则重取一个Sequence值,重复执行这个逻辑,直到插入成功;

“`sql

CREATE OR REPLACE PROCEDURE get_nextval_by_seq

(v_seq_name IN VARCHAR2,

v_nextval OUT NUMBER)

IS

v_currval NUMBER;

v_try_times NUMBER;

BEGIN

v_try_times := 0;

LOOP

— 获取 Sequence 值

SELECT seq_name.nextval

INTO v_currval

FROM dual;

— 判断是否存在重复的值

BEGIN

INSERT INTO tab_ (col1)

VALUES (v_currval);

v_nextval := v_currval;

EXIT;

EXCEPTION

WHEN DUP_VAL_ON_INDEX

THEN — 如果重复,则重新 get 一个值

v_try_times := v_try_times + 1;

CONTINUE;

END;

END LOOP;

END get_nextval_by_seq;

2、使用AQ (Advance Queue):AQ本身就是一种先进的队列,可以用来实现高并发环境下的序列号生成,例如:
```sql
-- 创建队列
BEGIN
SYS.DBMS_AQADM.CREATE_QUEUE(
queue_name => 'seq_aq',
queue_table => 'seq_table',
multiple_consumers => FALSE
);
END;
/
-- 创建生产者
BEGIN
SYS.DBMS_AQADM.CREATE_QUEUE_PRODUCER(
producer_name => 'seq_producer',
queue_name => 'seq_aq'
);
END;
/
-- 启动队列
BEGIN
SYS.DBMS_AQADM.START_QUEUE(queue_name => 'seq_aq');
END;
/

-- 创建序列
CREATE SEQUENCE seq_aq
INCREMENT BY 1
START WITH 1
MAXVALUE 999999999999999999
MINVALUE 1
NOCYCLE
NOCACHE;
-- 构造函数
CREATE OR REPLACE FUNCTION get_nextval_by_aq
RETURN INTEGER
IS
enq_opt DBMS_AQ.ENQUEUE_OPTIONS_T;
mes_prop DBMS_AQ.MESSAGE_PROPERTIES_T;
message_handle RAW(16);
nextval INTEGER;
BEGIN
MES_PROP.Correlation := SYS.DBMS_AQ.NEW_CORRELATION;
ENQ_OPT.RetentionTime := 0;

SYS.DBMS_AQ.ENQUEUE( queue_name => 'SEQ_AQ',
enqueue_opt => ENQ_OPT,
message_prop => MES_PROP,
payload =>
SYS.DBMS_AQ.new_message(
nextval => seq_aq.nextval),
msgid => message_handle
);
nextval := MES_PROP.message_data.nextval;
SYS.dbms_aq.dequeue(
queue_name => 'SEQ_AQ',
dequeue_options => NULL,
message_properties => MES_PROP,
payload => nextval,
msgid => message_handle
);
return nextval;
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('Error') ;
END;

以上方法可以有效解决Oracle序列重复问题,当前可用方案应该根据实际情况选择,AQ一般用于并发环境比较严格的情景,普通情景可以使用存储过程就可以达到同样的效果。


数据运维技术 » 解决Oracle序列重复问题(oracle序列重复)