sql >> Database teknologi >  >> RDS >> Oracle

Skal nulstille værdien af ​​sekvens i Oracle

Grunde til, hvorfor du ikke bør nulstille værdien, hvis den bliver brugt:

Hvad sker der, hvis du har 20 poster og sletter post 5-10? Du har et hul i midten, som ikke løses ved at genindstille sekvensen. Sekvenser vil aldrig generere en mellemrumsfri række af tal, en perfekt 1, 2 .. n .

Hvis du ringer til .nextval og brug ikke den værdi, det er bort . Vil du slippe og genskabe sekvensen? Hvis du starter en indsættelse og annullerer den, og Oracle ruller tilbage, hvad du har gjort, er disse værdier forsvundet . Hvis du indstiller nocache så vil du have færre huller, men til en pris af et hit til ydeevnen; er det det værd?

Din cache skal indstilles til det antal inserts, du forventer at gøre på ethvert tidspunkt i alle sessioner for at undgå problemer med ydeevnen. Sekvenser er designet til at give en meget hurtig, skalerbar måde at skabe en surrogatnøgle uden nogen låse osv. ikke at genskabe sættet af positive heltal.

I slutningen af ​​dagen burde det ikke betyde det mindste. Hvis du stoler på en ubrudt sekvens som nøglen til din tabel, har du et problem med dine data snarere end sekvenser.

Besvarelse af spørgsmålet:

For rent faktisk at besvare dit spørgsmål skal du:

  1. Først skal du finde ud af, hvad den maksimale id-værdi (sekvens) i din tabel er.
  2. Slip derefter og genskab sekvensen.

At finde den maksimale værdi betyder, at du bliver nødt til at genskabe sekvensen dynamisk på bekostning af endnu et hit til ydeevnen.

Hvis du forsøger at indsætte noget i din tabel, mens dette sker, vil det mislykkes og kan ugyldiggøre eventuelle triggere eller andre objekter, der bruger sekvensen:

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

Som jeg siger, anbefales dette ikke, og du bør bare ignorere eventuelle huller.

Opdatering - aka et bedre svar takket være Jeffrey Kemp:

I modsætning til dokumentationens anbefaling er der, som Jeffrey Kemp foreslog i kommentarerne, en måde at gøre dette uden på slippe og genskabe sekvensen.

Nemlig af:

  1. Udregning af forskellen mellem det maksimale id i din tabel og den aktuelle værdi af sekvensen.
  2. Ændring af rækkefølgen til at stige med dette negative tal
  3. Ændring af rækkefølgen til at øges med 1 igen.

Fordelene ved dette er, at objektet stadig eksisterer så og triggere, bevillinger osv. stadig opretholdes. Ulempen, som jeg ser det, er, at hvis en anden session stiger med dette negative tal på samme tid som din, kan du gå for langt tilbage.

Her er en demonstration:

Konfigurer testen:

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.

Tilbagestil rækkefølgen

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. Hvordan opstår databasekorruption?

  2. Hvad er den bedste måde at gemme koordinater (længde/breddegrad, fra Google Maps) i SQL Server?

  3. java.lang.NoSuchFieldError:NONE i dvale med Spring 3, maven, JPA, c3p0

  4. Sådan aktiveres alle CHECK &fremmednøglebegrænsninger for en tabel i SQL Server (T-SQL-eksempler)