web-dev-qa-db-fra.com

Comment créer une séquence Oracle commençant par max value à partir d'une table?

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;
42
Amar Patel

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 

1 pas le faire, et # 2 ne pas utiliser une séquence pour cela.

19
Neil Kodner

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.

36
DCookie

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

Vous ne pouvez pas utiliser de sous-sélection dans une instruction CREATE SEQUENCE. Vous devrez sélectionner la valeur à l'avance.

16
Chad Birch

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.

12
Gary Myers

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