web-dev-qa-db-ja.com

テーブルから最大値で始まるOracleシーケンスを作成する方法は?

特定のテーブルの最大値で始まるシーケンスをOracleで作成しようとしています。なぜこれが機能しないのですか?

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

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はシーケンスを使用しません。

18
Neil Kodner

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;

考慮すべきもう1つの点:CACHEパラメーターを20に設定すると、データベースがダウンした場合にシーケンスで最大19個の値が失われるリスクがあります。 CACHEd値は、データベースの再起動時に失われます。シーケンスを頻繁にヒットしない限り、またはギャップをそれほど気にしない限り、1に設定します。

最後に、CACHEおよびINCREMENT BYに指定した値がデフォルトです。それらをオフにして、同じ結果を得ることができます。

36
DCookie

ここで私はうまく動作する私の例を持っています:

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;
30

CREATE SEQUENCEステートメント内で副選択を使用することはできません。事前に値を選択する必要があります。

16
Chad Birch

半ばで、MAX値はcommitted値の最大値になります。 1234が返される場合があり、誰かが既に1235を挿入したがコミットしていないことを考慮する必要がある場合があります。

12
Gary Myers

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;
4
dmonti
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;
0
evandertino