Как создать последовательность Oracle, начиная с максимального значения из таблицы?
пытаюсь создать последовательность в Oracle, которая начинается с максимального значения из определенной таблицы. Почему это не работает?
CREATE SEQUENCE transaction_sequence
MINVALUE 0
START WITH (SELECT MAX(trans_seq_no)
FROM TRANSACTION_LOG)
INCREMENT BY 1
CACHE 20;
7 ответов
вы можете начать с 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.
Если вы пытаетесь сделать "gapless" вещь, я настоятельно рекомендую вам
1 не делать этого, и #2 не использовать последовательность для него.
Если вы можете использовать PL / SQL, попробуйте (EDIT: включает предложение 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;
еще один момент для рассмотрения: установив для параметра кэша значение 20, вы рискуете потерять до 19 значений в последовательности, если база данных пойдет вниз. Кэшированные значения теряются при перезапуске базы данных. Если вы не нажимаете последовательность очень часто, или, вы не заботитесь о пробелах, я бы установил ее на 1.
один последний nit: указанные вами значения для CACHE и INCREMENT BY являются значениями по умолчанию. Вы можете оставить их и получить тот же результат.
вот у меня есть пример, который работает:
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
заявление. Вы должны будете выбрать значение заранее.
медведь в середине, максимальное значение будет только максимум совершено значения. Он может вернуть 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;