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 :
- Tout d'abord, découvrez quelle est la valeur maximale de l'ID (séquence) dans votre tableau.
- 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 :
- Travailler sur la différence entre l'
id
maximum dans votre table et la valeur actuelle de la séquence. - Modification de la séquence pour incrémenter de ce nombre négatif
- 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>