Essayer de créer une séquence dans Oracle qui commence par la valeur maximale d'une table spécifique. Pourquoi ça ne marche pas?
CREATE SEQUENCE transaction_sequence
MINVALUE 0
START WITH (SELECT MAX(trans_seq_no)
FROM TRANSACTION_LOG)
INCREMENT BY 1
CACHE 20;
vous voudrez peut-être commencer par max(trans_seq_no) + 1.
regarder:
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
Lorsque vous créez une séquence avec un nombre, vous devez vous rappeler que la première fois que vous sélectionnez cette séquence, Oracle renverra la valeur initiale que vous lui avez attribuée.
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.
Si vous essayez de faire le «sans fils», je vous conseille fortement de
Si vous pouvez utiliser PL/SQL, essayez (EDIT: incorpore la suggestion xlnt de Neil de commencer à la valeur immédiatement supérieure):
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;
Autre point à prendre en compte: en définissant le paramètre CACHE sur 20, vous courez le risque de perdre jusqu'à 19 valeurs dans votre séquence si la base de données tombe en panne. Les valeurs CACHEd sont perdues au redémarrage de la base de données. À moins que vous ne touchiez très souvent la séquence, ou que vous vous fassiez un peu des trous, je le mettrais à 1.
Un dernier point: les valeurs que vous avez spécifiées pour CACHE et INCREMENT BY sont les valeurs par défaut. Vous pouvez les laisser et obtenir le même résultat.
Ici, j'ai mon exemple qui fonctionne très bien:
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;
Vous ne pouvez pas utiliser de sous-sélection dans une instruction CREATE SEQUENCE
. Vous devrez sélectionner la valeur à l'avance.
Garder au milieu, la valeur MAX ne sera que le maximum de engagé valeurs. Il pourrait retourner 1234, et vous devrez peut-être considérer que quelqu'un a déjà inséré 1235 mais n'a pas été commis.
Basé sur Ivan Laharnar avec moins de code et plus simple:
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;