Как мне сбросить последовательность в Oracle? - PullRequest
152 голосов
/ 09 сентября 2008

В PostgreSQL , я могу сделать что-то вроде этого:

ALTER SEQUENCE serial RESTART WITH 0;

Есть ли эквивалент Oracle?

Ответы [ 17 ]

136 голосов
/ 18 сентября 2008

Вот хорошая процедура для сброса любой последовательности в 0 от гуру Oracle Tom Kyte Отличная дискуссия о плюсах и минусах в ссылках ниже тоже.

tkyte@TKYTE901.US.ORACLE.COM> 
create or replace
procedure reset_seq( p_seq_name in varchar2 )
is
    l_val number;
begin
    execute immediate
    'select ' || p_seq_name || '.nextval from dual' INTO l_val;

    execute immediate
    'alter sequence ' || p_seq_name || ' increment by -' || l_val || 
                                                          ' minvalue 0';

    execute immediate
    'select ' || p_seq_name || '.nextval from dual' INTO l_val;

    execute immediate
    'alter sequence ' || p_seq_name || ' increment by 1 minvalue 0';
end;
/

На этой странице: Динамический SQL для сброса значения последовательности
Другое хорошее обсуждение также здесь: Как сбросить последовательности?

82 голосов
/ 09 сентября 2008

Истинный перезапуск невозможен AFAIK . (Пожалуйста, поправьте меня, если я ошибаюсь!).

Однако, если вы хотите установить его на 0, вы можете просто удалить и воссоздать его.

Если вы хотите установить конкретное значение, вы можете установить INCREMENT в отрицательное значение и получить следующее значение.

То есть, если ваша последовательность равна 500, вы можете установить ее на 100 с помощью

ALTER SEQUENCE serial INCREMENT BY -400;
SELECT serial.NEXTVAL FROM dual;
ALTER SEQUENCE serial INCREMENT BY 1;
44 голосов
/ 19 мая 2010

Это мой подход:

  1. сбросить последовательность
  2. воссоздать его

Пример:

--Drop sequence

DROP SEQUENCE MY_SEQ;

-- Create sequence 

create sequence MY_SEQ
minvalue 1
maxvalue 999999999999999999999
start with 1
increment by 1
cache 20;
33 голосов
/ 19 мая 2011

Мой подход - небольшое расширение Пример Дугмана .

Расширения ...

Передать начальное значение в качестве параметра. Зачем? Мне нравится называть эту вещь сбросом последовательности обратно к максимальному идентификатору, используемому в некоторой таблице . В итоге я вызываю этот процесс из другого скрипта, который выполняет несколько вызовов для целой группы последовательностей, сбрасывая nextval обратно до некоторого уровня, который достаточно высок, чтобы не вызывать нарушений первичного ключа, когда я использую значение последовательности для уникального идентификатора.

Это также чтит предыдущее минимальное значение . Фактически может выдвинуть следующее значение еще выше , если желаемое p_val или существующее минимальное значение выше текущего или рассчитанного следующего значения.

Лучше всего, его можно вызвать, чтобы сбросить до указанного значения, и просто подождать, пока в конце не появится процедура «исправить все мои последовательности».

create or replace
procedure Reset_Sequence( p_seq_name in varchar2, p_val in number default 0)
is
  l_current number := 0;
  l_difference number := 0;
  l_minvalue user_sequences.min_value%type := 0;

begin

  select min_value
  into l_minvalue
  from user_sequences
  where sequence_name = p_seq_name;

  execute immediate
  'select ' || p_seq_name || '.nextval from dual' INTO l_current;

  if p_Val < l_minvalue then
    l_difference := l_minvalue - l_current;
  else
    l_difference := p_Val - l_current;
  end if;

  if l_difference = 0 then
    return;
  end if;

  execute immediate
    'alter sequence ' || p_seq_name || ' increment by ' || l_difference || 
       ' minvalue ' || l_minvalue;

  execute immediate
    'select ' || p_seq_name || '.nextval from dual' INTO l_difference;

  execute immediate
    'alter sequence ' || p_seq_name || ' increment by 1 minvalue ' || l_minvalue;
end Reset_Sequence;

Эта процедура полезна сама по себе, но теперь давайте добавим еще одну, которая вызывает ее и задает все программно с соглашением об именах последовательностей и ищет максимальное значение, используемое в существующей таблице / поле ...

create or replace
procedure Reset_Sequence_to_Data(
  p_TableName varchar2,
  p_FieldName varchar2
)
is
  l_MaxUsed NUMBER;
BEGIN

  execute immediate
    'select coalesce(max(' || p_FieldName || '),0) from '|| p_TableName into l_MaxUsed;

  Reset_Sequence( p_TableName || '_' || p_Fieldname || '_SEQ', l_MaxUsed );

END Reset_Sequence_to_Data;

Теперь мы готовим на газе!

Приведенная выше процедура проверит максимальное значение поля в таблице, построит имя последовательности из пары таблица / поле и вызовет "Reset_Sequence" с этим измеренным максимальным значением.

Последняя часть этой головоломки и глазурь на пироге идут дальше ...

create or replace
procedure Reset_All_Sequences
is
BEGIN

  Reset_Sequence_to_Data( 'ACTIVITYLOG', 'LOGID' );
  Reset_Sequence_to_Data( 'JOBSTATE', 'JOBID' );
  Reset_Sequence_to_Data( 'BATCH', 'BATCHID' );

END Reset_All_Sequences;

В моей фактической базе данных есть около сотни других последовательностей, сбрасываемых с помощью этого механизма, поэтому в этой процедуре выше 97 вызовов Reset_Sequence_to_Data .

Нравится это? Ненавидеть это? Безразлично

27 голосов
/ 30 октября 2013
alter sequence serial restart start with 0;

Эта функция является новой в Oracle 12c. Он не включен в официальную документацию . Я нашел это в скриптах, сгенерированных пакетом Oracle DBMS_METADATA_DIFF .

ПРЕДУПРЕЖДЕНИЕ: Я несколько раз использовал эту функцию в производственных системах, и, на мой взгляд, можно использовать эту команду в специальных скриптах. Но вы можете не захотеть включать его в процедуру как часть приложения. Я создал запрос на обслуживание Oracle с запросом об этой функции; это не просто ошибка документации, это неподдерживаемая функция. Возможно, команда когда-нибудь исчезнет, ​​как WM_CONCAT. (Хотя я думаю, что это маловероятно - синтаксис Oracle редко исчезает, и это простая функция, используемая как минимум в двух местах.)

9 голосов
/ 04 ноября 2010

Следующий скрипт устанавливает последовательность в желаемое значение:

Учитывая только что созданную последовательность с именем PCS_PROJ_KEY_SEQ и таблицу PCS_PROJ:

BEGIN
   DECLARE
      PROJ_KEY_MAX       NUMBER := 0;
      PROJ_KEY_CURRVAL   NUMBER := 0;
   BEGIN

    SELECT MAX (PROJ_KEY) INTO PROJ_KEY_MAX FROM PCS_PROJ;
    EXECUTE IMMEDIATE 'ALTER SEQUENCE PCS_PROJ_KEY_SEQ INCREMENT BY ' || PROJ_KEY_MAX;
    SELECT PCS_PROJ_KEY_SEQ.NEXTVAL INTO PROJ_KEY_CURRVAL FROM DUAL;
    EXECUTE IMMEDIATE 'ALTER SEQUENCE PCS_PROJ_KEY_SEQ INCREMENT BY 1';

END;
END;
/
5 голосов
/ 29 июля 2009

Эта хранимая процедура перезапускает мою последовательность:

Create or Replace Procedure Reset_Sequence  
  is
  SeqNbr Number;
begin
   /*  Reset Sequence 'seqXRef_RowID' to 0    */
   Execute Immediate 'Select seqXRef.nextval from dual ' Into SeqNbr;
   Execute Immediate 'Alter sequence  seqXRef increment by - ' || TO_CHAR(SeqNbr) ;
   Execute Immediate 'Select seqXRef.nextval from dual ' Into SeqNbr;
   Execute Immediate 'Alter sequence  seqXRef increment by 1';
END;

/

4 голосов
/ 10 февраля 2013

Существует другой способ сброса последовательности в Oracle: установите свойства maxvalue и cycle. Когда nextval последовательности достигает значения maxvalue, если установлено свойство cycle, оно снова начинается с minvalue последовательности.

Преимущество этого метода по сравнению с установкой отрицательного значения increment by состоит в том, что последовательность может продолжать использоваться во время выполнения процесса сброса, что снижает вероятность того, что для сброса потребуется некоторая форма сбоя.

Значение для maxvalue должно быть больше, чем текущее значение nextval, поэтому приведенная ниже процедура включает в себя необязательный параметр, разрешающий буфер в случае повторного доступа к последовательности между выбором nextval в процедуре и настройкой cycle свойство.

create sequence s start with 1 increment by 1;

select s.nextval from dual
connect by level <= 20;

   NEXTVAL
----------
         1 
...
        20

create or replace procedure reset_sequence ( i_buffer in pls_integer default 0)
as
  maxval pls_integer;
begin

  maxval := s.nextval + greatest(i_buffer, 0); --ensure we don't go backwards!
  execute immediate 'alter sequence s cycle minvalue 0 maxvalue ' || maxval;
  maxval := s.nextval;
  execute immediate 'alter sequence s nocycle maxvalue 99999999999999';

end;
/
show errors

exec reset_sequence;

select s.nextval from dual;

   NEXTVAL
----------
         1 

Процедура в состоянии покоя дает возможность того, что другой сеанс получит значение 0, что может быть или не быть проблемой для вас. Если это так, вы всегда можете:

  • Установить minvalue 1 на первом изменении
  • Исключить второе nextval извлечение
  • Переместите оператор для установки свойства nocycle в другую процедуру, которая будет запущена позднее (при условии, что вы хотите это сделать).
3 голосов
/ 25 апреля 2017

Jezus, все это программирование только для перезапуска индекса ... Возможно, я идиот, но для pre-oracle 12 (который имеет функцию перезапуска), что не так с simpel:

drop sequence blah;
create sequence blah 

2 голосов
/ 29 сентября 2015

В моем проекте, как только случилось, что кто-то вручную ввел записи без использования последовательности, следовательно, я должен сбросить значение последовательности вручную, для чего я написал ниже фрагмент кода SQL:

declare
max_db_value number(10,0);
cur_seq_value number(10,0);
counter number(10,0);
difference number(10,0);
dummy_number number(10);

begin

-- enter table name here
select max(id) into max_db_value from persons;
-- enter sequence name here
select last_number into cur_seq_value from user_sequences where  sequence_name = 'SEQ_PERSONS';

difference  := max_db_value - cur_seq_value;

 for counter in 1..difference
 loop
    -- change sequence name here as well
    select SEQ_PERSONS.nextval into dummy_number from dual;
 end loop;
end;

Обратите внимание, приведенный выше код будет работать, если последовательность запаздывает.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...