Oracle
 sql >> Baza danych >  >> RDS >> Oracle

Trzeba zresetować wartość sekwencji w Oracle

Powody, dla których nie należy resetować wartości, jeśli jest używana:

Co się stanie, jeśli masz 20 rekordów i usuniesz rekordy 5-10? Masz lukę pośrodku, której ponowne ustawienie sekwencji nie rozwiąże. Sekwencje nigdy wygeneruj ciąg liczb bez przerw, doskonały 1, 2 .. n .

Jeśli zadzwonisz .nextval i nie używaj wartości, która zniknęła . Czy zamierzasz porzucić i odtworzyć sekwencję? Jeśli rozpoczniesz wstawianie i anulujesz je, a Oracle cofnie to, co zrobiłeś, te wartości znikną . Jeśli ustawisz nocache wtedy będziesz miał mniej luk, ale kosztem uderzenia w wydajność; czy warto?

Twoja pamięć podręczna powinna być ustawiona na liczbę wstawek, jaką spodziewasz się wykonać w dowolnym momencie we wszystkich sesjach aby uniknąć problemów z wydajnością. Sekwencje są zaprojektowane tak, aby zapewnić bardzo szybki, skalowalny sposób tworzenia klucza zastępczego bez żadnych blokad itp. nie aby ponownie wygenerować zbiór dodatnich liczb całkowitych.

W ostatecznym rozrachunku nie powinno to mieć najmniejszego znaczenia. Jeśli polegasz na nieprzerwanej sekwencji jako kluczu w swojej tabeli, masz problem z danymi, a nie z sekwencjami.

Odpowiedź na pytanie:

Aby faktycznie odpowiedzieć na swoje pytanie, musisz:

  1. Najpierw dowiedz się, jaka jest maksymalna wartość identyfikatora (sekwencji) w Twojej tabeli.
  2. Następnie upuść i ponownie utwórz sekwencję.

Znalezienie maksymalnej wartości oznacza, że ​​trzeba będzie odtwarzać sekwencję dynamicznie kosztem kolejnego uderzenia w wydajność.

Jeśli spróbujesz wstawić coś do swojej tabeli, podczas gdy to się dzieje, zakończy się to niepowodzeniem i może unieważnić wszystkie wyzwalacze lub inne obiekty, które używają sekwencji:

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 mówię, nie jest to zalecane i należy po prostu zignorować wszelkie luki.

Aktualizacja – czyli lepsza odpowiedź dzięki Jeffreyowi Kempowi:

Wbrew zaleceniom dokumentacji istnieje, jak zasugerował Jeffrey Kemp w komentarzach, sposób na zrobienie tego bez upuszczanie i ponowne tworzenie sekwencji.

Mianowicie przez:

  1. Opracowanie różnicy między maksymalnym id w Twojej tabeli i aktualną wartość sekwencji.
  2. Zmienianie sekwencji w celu zwiększenia o tę liczbę ujemną
  3. Ponowna zmiana sekwencji w celu zwiększenia o 1.

Zaletą tego jest to, że obiekt nadal istnieje, a wyzwalacze, granty itp. są nadal utrzymywane. Minusem, jak widzę, jest to, że jeśli kolejna sesja wzrośnie o tę ujemną liczbę w tym samym czasie, co twoja, możesz się cofnąć za daleko.

Oto demonstracja:

Skonfiguruj 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.

Odwróć sekwencję

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. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Dowiedz się, do którego kwartału należy data w Oracle

  2. Błąd 404 nie został znaleziony w EM 12c

  3. Wstaw wiele rekordów w Oracle

  4. Oracle — jakiego pliku nazw TNS używam?

  5. Oracle ORA-00979 — nie jest wyrażeniem GROUP BY