Důvody, proč byste neměli resetovat hodnotu, pokud se používá:
Co se stane, když máte 20 záznamů a smažete záznamy 5-10? Uprostřed máte mezeru, kterou přenastavení sekvence nevyřeší. Sekvence nebudou nikdy vygenerujte posloupnost čísel bez mezer, dokonalé 1, 2 .. n .
Pokud zavoláte .nextval
a nepoužívejte hodnotu, která je pryč . Chystáte se vypustit a znovu vytvořit sekvenci? Pokud spustíte vložení a zrušíte jej a Oracle vrátí zpět to, co jste udělali, tyto hodnoty jsou pryč . Pokud nastavíte nocache
pak budete mít méně mezer, ale za cenu zásahu do výkonu; Stojí to za to?
Vaše mezipaměť by měla být nastavena na počet vložení, který očekáváte, že provedete najednou ve všech relacích abyste se vyhnuli problémům s výkonem. Sekvence jsou navrženy tak, aby poskytovaly velmi rychlý a škálovatelný způsob vytvoření náhradního klíče bez jakýchkoli zámků atd. ne znovu vygenerovat sadu kladných celých čísel.
Na konci dne by to nemělo být ani v nejmenším důležité. Pokud se spoléháte na nepřerušenou sekvenci jako klíč vaší tabulky, máte problém spíše s daty než se sekvencemi.
Odpověď na otázku:
Chcete-li skutečně odpovědět na vaši otázku, budete potřebovat:
- Nejprve zjistěte, jaká je maximální hodnota id (sekvence) ve vaší tabulce.
- Potom pusťte a znovu vytvořte sekvenci.
Nalezení maximální hodnoty znamená, že budete muset sekvenci znovu vytvořit dynamicky za cenu dalšího zásahu do výkonu.
Pokud se pokusíte něco vložit do tabulky, zatímco se to děje, selže to a může zneplatnit všechny spouštěče nebo jiné objekty, které používají sekvenci:
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 říkám, toto se nedoporučuje a měli byste všechny mezery ignorovat.
Aktualizace – aka Lepší odpověď Díky Jeffrey Kempovi:
Na rozdíl od doporučení dokumentace existuje, jak navrhl Jeffrey Kemp v komentářích, způsob, jak to udělat bez vypuštění a opětovné vytvoření sekvence.
Konkrétně od:
- Zjištění rozdílu mezi maximálním
id
ve vaší tabulce a aktuální hodnotu sekvence. - Změna sekvence na zvýšení o toto záporné číslo
- Opětovná změna sekvence na zvýšení o 1.
Výhodou toho je, že objekt stále existuje a spouštěče, granty atd. jsou stále zachovány. Nevýhoda, jak to vidím, je, že pokud se další relace zvýší o toto záporné číslo ve stejnou dobu jako vaše, můžete se vrátit příliš daleko.
Zde je ukázka:
Nastavte 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.
Vrátit sekvenci
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>