Motivos pelos quais você não deve redefinir o valor se estiver sendo usado:
O que acontece se você tiver 20 registros e excluir os registros de 5 a 10? Você tem uma lacuna no meio que redefinir a sequência não resolverá. As sequências nunca gerar uma sequência de números sem lacunas, um perfeito 1, 2 .. n .
Se você chamar
.nextval
e não use o valor que se foi . Você vai largar e recriar a sequência? Se você iniciar uma inserção e cancelá-la e o Oracle reverter o que você fez, esses valores sumiram . Se você definir nocache
então você terá menos lacunas, mas ao custo de um impacto no desempenho; Vale a pena? Seu cache deve ser definido para o número de inserções que você espera fazer a qualquer momento em todas as sessões para evitar quaisquer problemas de desempenho. As sequências são projetadas para fornecer uma maneira muito rápida e escalável de criar uma chave substituta sem travas etc. não para gerar novamente o conjunto de inteiros positivos.
No final do dia, não deveria importar nem um pouco. Se você está contando com uma sequência ininterrupta como a chave da sua tabela, então você tem um problema com seus dados em vez de sequências.
Respondendo à pergunta:
Para realmente responder sua pergunta, você precisaria:
- Primeiro, descubra qual é o valor máximo de id (sequência) em sua tabela.
- Em seguida, solte e recrie a sequência.
Encontrar o valor máximo significa que você precisa recriar a sequência dinamicamente ao custo de outro impacto no desempenho.
Se você tentar inserir algo em sua tabela enquanto isso está acontecendo, ele falhará e poderá invalidar quaisquer gatilhos ou outros objetos que usem a sequência:
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;
/
Como eu disse, isso não é recomendado e você deve simplesmente ignorar quaisquer lacunas.
Atualização - também conhecida como Uma resposta melhor, graças a Jeffrey Kemp:
Ao contrário da recomendação da documentação, há, como Jeffrey Kemp sugeriu nos comentários, uma maneira de fazer isso sem descartando e recriando a sequência.
A saber, por:
- Como calcular a diferença entre o
id
máximo na sua tabela e o valor atual da sequência. - Alterando a sequência para incrementar por este número negativo
- Alterando a sequência para incrementar em 1 novamente.
Os benefícios disso são que o objeto ainda existe e gatilhos, concessões etc. ainda são mantidos. A desvantagem, a meu ver, é que, se outra sessão aumentar esse número negativo ao mesmo tempo que a sua, você pode voltar muito longe.
Aqui está uma demonstração:
Configure o teste:
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.
Reverta a sequência
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>