特定のテーブルの最大値で始まるシーケンスをOracleで作成しようとしています。なぜこれが機能しないのですか?
CREATE SEQUENCE transaction_sequence
MINVALUE 0
START WITH (SELECT MAX(trans_seq_no)
FROM TRANSACTION_LOG)
INCREMENT BY 1
CACHE 20;
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とINCREMENTBYに指定した値がデフォルトです。それらを省略して、同じ結果を得ることができます。
ここに、うまく機能する私の例があります。
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;
あなたはから始めたいかもしれません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.
あなたが「ギャップのない」ことをしようとしているなら、私はあなたに強くお勧めします
CREATE SEQUENCE
ステートメント内で副選択を使用することはできません。事前に値を選択する必要があります。
途中で、MAX値はコミットされた値の最大値になります。1234が返される可能性があり、誰かがすでに1235を挿入しているが、コミットされていないことを考慮する必要がある場合があります。
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;
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;
動的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;