Причини, поради които не трябва да нулирате стойността, ако се използва:
Какво се случва, ако имате 20 записа и изтриете записи 5-10? Имате празнина в средата, която повторното задаване на последователността няма да реши. Последователностите никога генерира последователност от числа без празнини, перфектна 1, 2 .. n .
Ако извикате .nextval
и не използвайте стойността изчезна . Ще пуснете ли и ще създадете отново последователността? Ако стартирате вмъкване и го отмените и Oracle върне обратно това, което сте направили, тези стойности изчезнат . Ако зададете nocache
тогава ще имате по-малко пропуски, но с цената на удар в производителността; струва ли си?
Вашият кеш трябва да бъде настроен на броя вмъквания, които очаквате да направите по всяко време във всички сесии за да избегнете проблеми с производителността. Последователностите са предназначени да осигурят много бърз, мащабируем начин за създаване на сурогатен ключ без никакви ключалки и т.н. не за повторно генериране на набора от положителни числа.
В края на деня това не трябва да има никакво значение. Ако разчитате на непрекъсната последователност като ключ на вашата таблица, тогава имате проблем с данните си, а не с последователности.
Отговор на въпроса:
За да отговорите действително на въпроса си, ще трябва да:
- Първо, разберете каква е максималната стойност на идентификатор (последователност) във вашата таблица.
- След това пуснете и създайте отново последователността.
Намирането на максималната стойност означава, че ще трябва да пресъздадете последователността динамично с цената на още един удар за производителност.
Ако се опитате да вмъкнете нещо в таблицата си, докато това се случва, то ще се провали и може да обезсили всички задействания или други обекти, които използват последователността:
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;
/
Както казах, това не се препоръчва и трябва просто да игнорирате всички пропуски.
Актуализация – известен още като по-добър отговор благодарение на Джефри Кемп:
Противно на препоръката на документацията, както Джефри Кемп предложи в коментарите, има начин да направите това без отпадане и повторно създаване на последователността.
А именно от:
- Изработване на разликата между максималния
id
във вашата таблица и текущата стойност на последователността. - Промяна на последователността за увеличаване с това отрицателно число
- Промяна на последователността за увеличаване с 1 отново.
Ползите от това са, че обектът все още съществува, така че тригерите, грантовете и т.н. все още се поддържат. Недостатъкът, както го виждам, е, че ако друга сесия се увеличи с това отрицателно число в същото време като вашата, можете да се върнете твърде далеч.
Ето демонстрация:
Настройте теста:
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.
Върнете последователността
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>