46

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

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

8 回答 8

37

如果您可以使用 PL/SQL,请尝试(编辑:合并 Neil 的 xlnt 建议以从下一个更高的值开始):

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 个值。缓存的值在数据库重新启动时丢失。除非你经常打这个序列,或者你不太在意间隔,我会把它设置为 1。

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

于 2009-04-28T16:38:51.530 回答
31

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

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;
于 2013-05-29T09:30:21.130 回答
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

当您创建一个带有数字的序列时,您必须记住,当您第一次选择该序列时,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.

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

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

于 2009-04-28T17:04:00.490 回答
19

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

于 2009-04-28T16:26:01.437 回答
12

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

于 2009-04-28T23:14:21.190 回答
7

基于 Ivan Laharnar,代码更少,更简单:

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;
于 2017-07-13T19:20:37.430 回答
2
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;
于 2017-11-17T07:38:52.923 回答
0

使用动态 sql

BEGIN
            DECLARE
            maxId NUMBER;
              BEGIN
              SELECT MAX(id)+1
              INTO maxId
              FROM table_name;          
              execute immediate('CREATE SEQUENCE sequane_name MINVALUE '||maxId||' START WITH '||maxId||' INCREMENT BY 1 NOCACHE NOCYCLE');
              END;
END;
于 2019-09-19T11:37:16.837 回答