sql >> Database >  >> RDS >> Oracle

Moet de waarde van de reeks in Oracle opnieuw instellen

Redenen waarom u de waarde niet opnieuw moet instellen als deze wordt gebruikt:

Wat gebeurt er als u 20 records heeft en records 5-10 verwijdert? Je hebt een gat in het midden dat het opnieuw instellen van de reeks niet zal oplossen. Sequenties zullen nooit genereer een reeks vrije getallen, een perfecte 1, 2 .. n .

Als je .nextval . belt en gebruik niet de waarde die is op . Ga je de reeks laten vallen en opnieuw maken? Als u een invoegtoepassing start en deze annuleert en Oracle rolt terug wat u hebt gedaan, zijn die waarden verdwenen . Als u nocache . instelt dan heb je minder hiaten, maar ten koste van een prestatietreffer; is het het waard?

Uw cache moet zijn ingesteld op het aantal invoegingen dat u op een bepaald moment verwacht in alle sessies om prestatieproblemen te voorkomen. Sequenties zijn ontworpen om een ​​zeer snelle, schaalbare manier te bieden om een ​​surrogaatsleutel te maken zonder sloten enz. niet om de reeks positieve gehele getallen opnieuw te genereren.

Aan het eind van de dag zou het niets uit moeten maken. Als u vertrouwt op een ononderbroken reeks als sleutel van uw tabel, heeft u een probleem met uw gegevens in plaats van reeksen.

De vraag beantwoorden:

Om uw vraag daadwerkelijk te beantwoorden, moet u:

  1. Ontdek eerst wat de maximale id (reeks) waarde in uw tabel is.
  2. Laat de reeks vallen en maak deze opnieuw.

Het vinden van de maximale waarde betekent dat u de reeks dynamisch opnieuw moet maken ten koste van nog een hit voor de uitvoering.

Als u iets in uw tabel probeert in te voegen terwijl dit gebeurt, zal dit mislukken en kunnen eventuele triggers of andere objecten die de reeks gebruiken ongeldig maken:

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;
/

Zoals ik al zei, wordt dit niet aanbevolen en moet je eventuele hiaten negeren.

Update - ook bekend als een beter antwoord dankzij Jeffrey Kemp:

In tegenstelling tot de aanbeveling in de documentatie is er, zoals Jeffrey Kemp in de opmerkingen suggereerde, een manier om dit zonder te doen de reeks te laten vallen en opnieuw te maken.

Namelijk door:

  1. Het verschil uitwerken tussen de maximale id in uw tabel en de huidige waarde van de reeks.
  2. De reeks wijzigen om te verhogen met dit negatieve getal
  3. De volgorde wijzigen om opnieuw met 1 te verhogen.

De voordelen hiervan zijn dat het object dus nog steeds bestaat en dat triggers, subsidies etc nog steeds behouden blijven. Het nadeel, zoals ik het zie, is dat als een andere sessie tegelijkertijd met de jouwe met dit negatieve getal wordt verhoogd, je te ver terug kunt gaan.

Hier is een demonstratie:

Stel de test in:

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.

Keer de volgorde terug

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. Externe verbinding met PostgreSQL instellen

  2. Hoe een groot aantal tekenreeksen te laden die overeenkomen met de Oracle-database?

  3. Hoe willekeurige parameters naar Oracle-trigger te sturen?

  4. Jenkins gebruiken met Kubernetes AWS, deel 1