Oracle
 sql >> Base de données >  >> RDS >> Oracle

Besoin de réinitialiser la valeur de la séquence dans Oracle

Raisons pour lesquelles vous ne devriez pas réinitialiser la valeur si elle est utilisée :

Que se passe-t-il si vous avez 20 enregistrements et supprimez les enregistrements 5 à 10 ? Vous avez un espace au milieu que la réinitialisation de la séquence ne résoudra pas. Les séquences ne seront jamais générer une séquence de nombres sans espace, un parfait 1, 2 .. n .

Si vous appelez .nextval et n'utilisez pas la valeur c'est parti . Allez-vous supprimer et recréer la séquence ? Si vous démarrez une insertion et que vous l'annulez et qu'Oracle annule ce que vous avez fait, ces valeurs sont disparues . Si vous définissez nocache alors vous aurez moins d'écarts mais au prix d'une baisse de performance; Est-ce que ça vaut le coup?

Votre cache doit être défini sur le nombre d'insertions que vous prévoyez d'effectuer à tout moment dans toutes les sessions pour éviter tout problème de performances. Les séquences sont conçues pour fournir un moyen très rapide et évolutif de créer une clé de substitution sans aucun verrou, etc non pour re-générer l'ensemble des entiers positifs.

En fin de compte, cela ne devrait pas avoir d'importance. Si vous comptez sur une séquence ininterrompue comme clé de votre table, vous avez un problème avec vos données plutôt qu'avec les séquences.

Répondre à la question :

Pour répondre réellement à votre question, vous devez :

  1. Tout d'abord, découvrez quelle est la valeur maximale de l'ID (séquence) dans votre tableau.
  2. Ensuite, déposez et recréez la séquence.

Trouver la valeur maximale signifie que vous devrez recréer la séquence dynamiquement au prix d'un autre impact sur les performances.

Si vous essayez d'insérer quelque chose dans votre table pendant que cela se produit, cela échouera et peut invalider tous les déclencheurs ou autres objets qui utilisent la séquence :

declare

   l_max_value number;

begin

   select max(id)
     into l_max_value
     from my_table;

   execute immediate 'drop sequence my_sequence_name';

   -- nocache is not recommended if you are inserting more than
   -- one row at a time, or inserting with any speed at all.
   execute immediate 'create sequence my_sequence_name
                           start with ' || l_max_value
                      || ' increment by 1
                           nomaxvalue
                           nocycle
                           nocache';

end;
/

Comme je l'ai dit, ce n'est pas recommandé et vous devez simplement ignorer les lacunes.

Mise à jour - alias Une meilleure réponse grâce à Jeffrey Kemp :

Contrairement à la recommandation de la documentation, il existe, comme Jeffrey Kemp l'a suggéré dans les commentaires, un moyen de le faire sans déposer et recréer la séquence.

A savoir, par :

  1. Travailler sur la différence entre l'id maximum dans votre table et la valeur actuelle de la séquence.
  2. Modification de la séquence pour incrémenter de ce nombre négatif
  3. Modification de la séquence pour incrémenter de 1 à nouveau.

Les avantages de ceci sont que l'objet existe toujours et que les déclencheurs, les subventions, etc. sont toujours maintenus. L'inconvénient, selon moi, est que si une autre session augmente de ce nombre négatif en même temps que la vôtre, vous pouvez remonter trop loin.

Voici une démonstration :

Configurez le test :

SQL> create sequence test_seq
  2   start with 1
  3   increment by 1
  4   nomaxvalue
  5   nocycle
  6   nocache;

Sequence created.

SQL>
SQL> create table tmp_test ( id number(16) );

Table created.

SQL>
SQL> declare
  2     l_nextval number;
  3  begin
  4
  5    for i in 1 .. 20 loop
  6       insert into tmp_test values ( test_seq.nextval );
  7    end loop;
  8
  9  end;
 10  /

PL/SQL procedure successfully completed.

SQL>
SQL> select test_seq.currval from dual;

   CURRVAL
----------
        20

SQL>
SQL> delete from tmp_test where id > 15;

5 rows deleted.

SQL> commit;

Commit complete.

Inverser la séquence

SQL>
SQL> declare
  2
  3     l_max_id number;
  4     l_max_seq number;
  5
  6  begin
  7
  8     -- Get the maximum ID
  9     select max(id) into l_max_id
 10       from tmp_test;
 11
 12     -- Get the current sequence value;
 13     select test_seq.currval into l_max_seq
 14       from dual;
 15
 16     -- Alter the sequence to increment by the difference ( -5 in this case )
.
 17     execute immediate 'alter sequence test_seq
 18                          increment by ' || ( l_max_id - l_max_seq );
 19
 20     -- 'increment' by -5
 21     select test_seq.nextval into l_max_seq
 22       from dual;
 23
 24     -- Change the sequence back to normal
 25     execute immediate 'alter sequence test_seq
 26                          increment by 1';
 27
 28  end;
 29  /

PL/SQL procedure successfully completed.

SQL>
SQL> select test_seq.currval from dual;

   CURRVAL
----------
        15

SQL>