如何从表中创build一个以最大值开始的Oracle序列?

尝试在Oracle中创build一个以特定表的最大值开始的序列。 为什么这不起作用?

CREATE SEQUENCE transaction_sequence MINVALUE 0 START WITH (SELECT MAX(trans_seq_no) FROM TRANSACTION_LOG) INCREMENT BY 1 CACHE 20; 

你可能想用max(trans_seq_no) + 1.

看:

 SQL> create table my_numbers(my_number number not null primary key); Table created. SQL> insert into my_numbers(select rownum from user_objects); 260 rows created. SQL> select max(my_number) from my_numbers; MAX(MY_NUMBER) -------------- 260 SQL> create sequence my_number_sn start with 260; Sequence created. SQL> insert into my_numbers(my_number) values (my_number_sn.NEXTVAL); insert into my_numbers(my_number) values (my_number_sn.NEXTVAL) * ERROR at line 1: ORA-00001: unique constraint (NEIL.SYS_C00102439) violated 

当你用一个数字创build一个序列时,你必须记住,当你第一次select这个序列时,Oracle会返回你赋给它的初始值。

 SQL> drop sequence my_number_sn; Sequence dropped. SQL> create sequence my_number_sn start with 261; Sequence created. SQL> insert into my_numbers(my_number) values (my_number_sn.NEXTVAL); 1 row created. 

如果你想做“无缝隙”的事情,我强烈build议你

1不这样做,#2不使用序列。

如果你可以使用PL / SQL,试试(编辑:纳入Neil的xlntbuild议,从下一个更高的值开始):

 SELECT 'CREATE SEQUENCE transaction_sequence MINVALUE 0 START WITH '||MAX(trans_seq_no)+1||' INCREMENT BY 1 CACHE 20' INTO v_sql FROM transaction_log; EXECUTE IMMEDIATE v_sql; 

还有一点需要考虑:通过将CACHE参数设置为20,如果数据库出现故障,可能会产生序列中丢失多达19个值的风险。 数据库重新启动时,CACHEd值将丢失。 除非你经常碰到这个序列,或者你不关心那些差距,我会把它设置为1。

最后一个nit:您为CACHE和INCREMENT BY指定的值是默认值。 您可以将它们closures并获得相同的结果。

在这里,我有我的例子,它工作得很好:

 declare ex number; begin select MAX(MAX_FK_ID) + 1 into ex from TABLE; If ex > 0 then begin execute immediate 'DROP SEQUENCE SQ_NAME'; exception when others then null; end; execute immediate 'CREATE SEQUENCE SQ_NAME INCREMENT BY 1 START WITH ' || ex || ' NOCYCLE CACHE 20 NOORDER'; end if; end; 

您不能在CREATE SEQUENCE语句中使用子select。 您必须事先select值。

在中期,MAX值只会是承诺值的最大值。 它可能会返回1234,您可能需要考虑有人已经插入1235但未提交。

基于Ivan Laharnar,代码less且简单:

 declare lastSeq number; begin SELECT MAX(ID) + 1 INTO lastSeq FROM <TABLE_NAME>; if lastSeq IS NULL then lastSeq := 1; end if; execute immediate 'CREATE SEQUENCE <SEQUENCE_NAME> INCREMENT BY 1 START WITH ' || lastSeq || ' MAXVALUE 999999999 MINVALUE 1 NOCACHE'; end; 
 DECLARE v_max NUMBER; BEGIN SELECT (NVL (MAX (<COLUMN_NAME>), 0) + 1) INTO v_max FROM <TABLE_NAME>; EXECUTE IMMEDIATE 'CREATE SEQUENCE <SEQUENCE_NAME> INCREMENT BY 1 START WITH ' || v_max || ' NOCYCLE CACHE 20 NOORDER'; END;