Powody, dla których nie należy resetować wartości, jeśli jest używana:
Co się stanie, jeśli masz 20 rekordów i usuniesz rekordy 5-10? Masz lukę pośrodku, której ponowne ustawienie sekwencji nie rozwiąże. Sekwencje nigdy wygeneruj ciąg liczb bez przerw, doskonały 1, 2 .. n .
Jeśli zadzwonisz .nextval
i nie używaj wartości, która zniknęła . Czy zamierzasz porzucić i odtworzyć sekwencję? Jeśli rozpoczniesz wstawianie i anulujesz je, a Oracle cofnie to, co zrobiłeś, te wartości znikną . Jeśli ustawisz nocache
wtedy będziesz miał mniej luk, ale kosztem uderzenia w wydajność; czy warto?
Twoja pamięć podręczna powinna być ustawiona na liczbę wstawek, jaką spodziewasz się wykonać w dowolnym momencie we wszystkich sesjach aby uniknąć problemów z wydajnością. Sekwencje są zaprojektowane tak, aby zapewnić bardzo szybki, skalowalny sposób tworzenia klucza zastępczego bez żadnych blokad itp. nie aby ponownie wygenerować zbiór dodatnich liczb całkowitych.
W ostatecznym rozrachunku nie powinno to mieć najmniejszego znaczenia. Jeśli polegasz na nieprzerwanej sekwencji jako kluczu w swojej tabeli, masz problem z danymi, a nie z sekwencjami.
Odpowiedź na pytanie:
Aby faktycznie odpowiedzieć na swoje pytanie, musisz:
- Najpierw dowiedz się, jaka jest maksymalna wartość identyfikatora (sekwencji) w Twojej tabeli.
- Następnie upuść i ponownie utwórz sekwencję.
Znalezienie maksymalnej wartości oznacza, że trzeba będzie odtwarzać sekwencję dynamicznie kosztem kolejnego uderzenia w wydajność.
Jeśli spróbujesz wstawić coś do swojej tabeli, podczas gdy to się dzieje, zakończy się to niepowodzeniem i może unieważnić wszystkie wyzwalacze lub inne obiekty, które używają sekwencji:
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;
/
Jak mówię, nie jest to zalecane i należy po prostu zignorować wszelkie luki.
Aktualizacja – czyli lepsza odpowiedź dzięki Jeffreyowi Kempowi:
Wbrew zaleceniom dokumentacji istnieje, jak zasugerował Jeffrey Kemp w komentarzach, sposób na zrobienie tego bez upuszczanie i ponowne tworzenie sekwencji.
Mianowicie przez:
- Opracowanie różnicy między maksymalnym
id
w Twojej tabeli i aktualną wartość sekwencji. - Zmienianie sekwencji w celu zwiększenia o tę liczbę ujemną
- Ponowna zmiana sekwencji w celu zwiększenia o 1.
Zaletą tego jest to, że obiekt nadal istnieje, a wyzwalacze, granty itp. są nadal utrzymywane. Minusem, jak widzę, jest to, że jeśli kolejna sesja wzrośnie o tę ujemną liczbę w tym samym czasie, co twoja, możesz się cofnąć za daleko.
Oto demonstracja:
Skonfiguruj 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.
Odwróć sekwencję
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>