Oracle
 sql >> Datenbank >  >> RDS >> Oracle

Sie müssen den Wert der Sequenz in Oracle zurücksetzen

Gründe, warum Sie den Wert nicht zurücksetzen sollten, wenn er verwendet wird:

Was passiert, wenn Sie 20 Datensätze haben und die Datensätze 5-10 löschen? Sie haben eine Lücke in der Mitte, die durch das Zurücksetzen der Sequenz nicht behoben wird. Sequenzen werden nie eine lückenlose Zahlenfolge erzeugen, eine perfekte 1, 2 .. n .

Wenn Sie .nextval aufrufen und verwenden Sie nicht den Wert, der weg ist . Wirst du die Sequenz löschen und neu erstellen? Wenn Sie eine Einfügung starten und diese abbrechen und Oracle Ihre Aktion rückgängig macht, sind diese Werte weg . Wenn Sie nocache setzen dann haben Sie weniger Lücken, aber auf Kosten der Leistung; lohnt es sich?

Ihr Cache sollte auf die Anzahl der Einfügungen eingestellt sein, die Sie gleichzeitig über alle Sitzungen hinweg erwarten um Leistungsprobleme zu vermeiden. Sequenzen sind so konzipiert, dass sie eine sehr schnelle, skalierbare Möglichkeit zum Erstellen eines Ersatzschlüssels ohne Sperren usw. nicht bieten um den Satz positiver Ganzzahlen neu zu generieren.

Am Ende des Tages sollte es nicht das Geringste ausmachen. Wenn Sie sich auf eine ununterbrochene Sequenz als Schlüssel Ihrer Tabelle verlassen, haben Sie eher ein Problem mit Ihren Daten als mit Sequenzen.

Beantwortung der Frage:

Um Ihre Frage tatsächlich zu beantworten, müssten Sie:

  1. Finden Sie zuerst heraus, was der maximale ID-Wert (Sequenz) in Ihrer Tabelle ist.
  2. Dann die Sequenz löschen und neu erstellen.

Das Finden des Maximalwerts bedeutet, dass Sie die Sequenz auf Kosten einer weiteren Leistungseinbuße dynamisch neu erstellen müssten.

Wenn Sie versuchen, etwas in Ihre Tabelle einzufügen, während dies geschieht, schlägt dies fehl und kann alle Trigger oder andere Objekte ungültig machen, die die Sequenz verwenden:

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

Wie ich schon sagte, wird dies nicht empfohlen und Sie sollten alle Lücken einfach ignorieren.

Update – auch bekannt als A Better Answer Thanks to Jeffrey Kemp:

Entgegen der Empfehlung der Dokumentation gibt es, wie Jeffrey Kemp in den Kommentaren vorgeschlagen hat, eine Möglichkeit, dies ohne zu tun Löschen und erneutes Erstellen der Sequenz.

Nämlich durch:

  1. Ausrechnen der Differenz zwischen der maximalen id in Ihrer Tabelle und den aktuellen Wert der Sequenz.
  2. Ändern der Sequenz zum Erhöhen um diese negative Zahl
  3. Verändern der Sequenz, um wieder um 1 zu inkrementieren.

Die Vorteile davon sind, dass das Objekt immer noch existiert und Auslöser, Zuschüsse usw. weiterhin beibehalten werden. Der Nachteil, wie ich es sehe, ist, dass Sie zu weit zurückgehen können, wenn eine andere Sitzung um diese negative Zahl zur gleichen Zeit wie Ihre erhöht wird.

Hier ist eine Demonstration:

Test einrichten:

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.

Reihenfolge umkehren

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>