sql >> Databáze >  >> RDS >> Oracle

Potřeba resetovat hodnotu sekvence v Oracle

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:

  1. Nejprve zjistěte, jaká je maximální hodnota id (sekvence) ve vaší tabulce.
  2. 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:

  1. Zjištění rozdílu mezi maximálním id ve vaší tabulce a aktuální hodnotu sekvence.
  2. Změna sekvence na zvýšení o toto záporné číslo
  3. 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>


  1. Návrh databáze pro uživatelská nastavení

  2. Jak zakázat všechna omezení cizího klíče v databázi SQL Server - SQL Server / TSQL výukový program, část 77

  3. RDLC LocalReport Export do Excelu je opravdu pomalý

  4. Jak uvolnit možné zámky řádků Postgres?