Oracle
 sql >> база данни >  >> RDS >> Oracle

Трябва да нулирате стойността на последователността в Oracle

Причини, поради които не трябва да нулирате стойността, ако се използва:

Какво се случва, ако имате 20 записа и изтриете записи 5-10? Имате празнина в средата, която повторното задаване на последователността няма да реши. Последователностите никога генерира последователност от числа без празнини, перфектна 1, 2 .. n .

Ако извикате .nextval и не използвайте стойността изчезна . Ще пуснете ли и ще създадете отново последователността? Ако стартирате вмъкване и го отмените и Oracle върне обратно това, което сте направили, тези стойности изчезнат . Ако зададете nocache тогава ще имате по-малко пропуски, но с цената на удар в производителността; струва ли си?

Вашият кеш трябва да бъде настроен на броя вмъквания, които очаквате да направите по всяко време във всички сесии за да избегнете проблеми с производителността. Последователностите са предназначени да осигурят много бърз, мащабируем начин за създаване на сурогатен ключ без никакви ключалки и т.н. не за повторно генериране на набора от положителни числа.

В края на деня това не трябва да има никакво значение. Ако разчитате на непрекъсната последователност като ключ на вашата таблица, тогава имате проблем с данните си, а не с последователности.

Отговор на въпроса:

За да отговорите действително на въпроса си, ще трябва да:

  1. Първо, разберете каква е максималната стойност на идентификатор (последователност) във вашата таблица.
  2. След това пуснете и създайте отново последователността.

Намирането на максималната стойност означава, че ще трябва да пресъздадете последователността динамично с цената на още един удар за производителност.

Ако се опитате да вмъкнете нещо в таблицата си, докато това се случва, то ще се провали и може да обезсили всички задействания или други обекти, които използват последователността:

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

Както казах, това не се препоръчва и трябва просто да игнорирате всички пропуски.

Актуализация – известен още като по-добър отговор благодарение на Джефри Кемп:

Противно на препоръката на документацията, както Джефри Кемп предложи в коментарите, има начин да направите това без отпадане и повторно създаване на последователността.

А именно от:

  1. Изработване на разликата между максималния id във вашата таблица и текущата стойност на последователността.
  2. Промяна на последователността за увеличаване с това отрицателно число
  3. Промяна на последователността за увеличаване с 1 отново.

Ползите от това са, че обектът все още съществува, така че тригерите, грантовете и т.н. все още се поддържат. Недостатъкът, както го виждам, е, че ако друга сесия се увеличи с това отрицателно число в същото време като вашата, можете да се върнете твърде далеч.

Ето демонстрация:

Настройте теста:

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.

Върнете последователността

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. Разбиране на псевдонима на Oracle – защо псевдонимът не се разпознава в заявка, освен ако не е обвит във втора заявка?

  2. 2 начина за изтриване на дублиращи се редове в Oracle

  3. Как да вмъкнете данни директно от Excel в базата данни на Oracle

  4. Извикване на запаметена процедура на Oracle с изходен параметър от SQL Server

  5. SQL мониторинг в SQL Developer