Как я автоматически сбрасываю значение последовательности к 0 каждый год в Oracle 10 г?

:%s/^.\{0,5\}//g для глобального, так как мы хотим удалить первые 5 столбцов каждой строки для каждой строки.

6
задан tth 3 June 2009 в 02:44
поделиться

5 ответов

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

ЕСЛИ этот тип операций будет запущен в производство, его необходимо тщательно протестировать. (Что вызывает наибольшее беспокойство, так это возможность того, что процедура сброса будет случайно выполнена в неподходящее время, например, в середине года.

Отбрасывание и воссоздание последовательности - один из подходов. Как операция, это довольно просто что касается ПОСЛЕДОВАТЕЛЬНОСТИ:

    DROP SEQUENCE MY_SEQ;
    CREATE SEQUENCE MY_SEQ START WITH 1 INCREMENT BY 1 MINVALUE 0;

[EDIT] Как правильно указывает Мэтью Уотсон, каждый оператор DDL (например, DROP, CREATE, ALTER) вызывает неявную фиксацию. [/ EDIT]

Но любые привилегии, предоставленные SEQUENCE, будут отброшены, поэтому их нужно будет предоставить повторно. Любые объекты, ссылающиеся на последовательность, будут признаны недействительными. Чтобы сделать это более обобщенным, вам нужно будет сохранить привилегии (перед отбрасыванием последовательности), а затем повторно предоставить их.

Второй подход - ИЗМЕНИТЬ существующую ПОСЛЕДОВАТЕЛЬНОСТЬ, не отбрасывая и не воссоздавая ее. Сброс последовательности можно выполнить, изменив значение INCREMENT на отрицательное значение (разница между текущим значением и 0), а затем сделав ровно один .NEXTVAL, чтобы установить текущее значение на 0, а затем снова изменить INCREMENT на 1. Я использовал тот же подход раньше (вручную, в тестовой среде), чтобы установить последовательность на большее значение.

Конечно, для того, чтобы это работало правильно, вам нужно убедиться, что никакие другие сеансы не ссылаются на последовательность, пока эта операция выполняется. Дополнительный .NEXTVAL в неподходящий момент может испортить сброс. (ПРИМЕЧАНИЕ: добиться этого на стороне базы данных будет сложно, если приложение подключается как владелец последовательности, а не как отдельный пользователь.)

Чтобы это происходило каждый год, вам необходимо запланировать работу. Сброс последовательности должен быть согласован со сбросом части YYYY вашего идентификатора.

Вот пример:

http://www.jaredstill.com/content/reset-sequence.html

вам необходимо убедиться, что никакие другие сеансы не ссылаются на последовательность, пока выполняется эта операция. Дополнительный .NEXTVAL в неподходящий момент может испортить сброс. (ПРИМЕЧАНИЕ: добиться этого на стороне базы данных будет сложно, если приложение подключается как владелец последовательности, а не как отдельный пользователь.)

Чтобы это происходило каждый год, вам необходимо запланировать работу. Сброс последовательности должен быть согласован со сбросом части YYYY вашего идентификатора.

Вот пример:

http://www.jaredstill.com/content/reset-sequence.html

вам необходимо убедиться, что никакие другие сеансы не ссылаются на последовательность, пока выполняется эта операция. Дополнительный .NEXTVAL в неподходящий момент может испортить сброс. (ПРИМЕЧАНИЕ: добиться этого на стороне базы данных будет сложно, если приложение подключается как владелец последовательности, а не как отдельный пользователь.)

Чтобы это происходило каждый год, вам необходимо запланировать работу. Сброс последовательности должен быть согласован со сбросом части YYYY вашего идентификатора.

Вот пример:

http://www.jaredstill.com/content/reset-sequence.html

если приложение подключается как владелец последовательности, а не как отдельный пользователь.)

Чтобы это происходило каждый год, вам нужно запланировать задание. Сброс последовательности должен быть согласован со сбросом части YYYY вашего идентификатора.

Вот пример:

http://www.jaredstill.com/content/reset-sequence.html

если приложение подключается как владелец последовательности, а не как отдельный пользователь.)

Чтобы это происходило каждый год, вам нужно запланировать задание. Сброс последовательности должен быть согласован со сбросом части YYYY вашего идентификатора.

Вот пример:

http://www.jaredstill.com/content/reset-sequence.html

[EDIT]

UNTESTED заполнитель для одной из возможных схем блока PL / SQL для сброса последовательности

    declare
      pragma autonomous_transaction;
      ln_increment       number;
      ln_curr_val        number;
      ln_reset_increment number;
      ln_reset_val       number;
    begin

      -- save the current INCREMENT value for the sequence
      select increment_by
        into ln_increment
        from user_sequences
       where sequence_name = 'MY_SEQ';

      -- determine the increment value required to reset the sequence
      -- from the next fetched value to 0
      select -1 - MY_SEQ.nextval into ln_reset_increment from dual;

      -- fetch the next value (to make it the current value)
      select MY_SEQ.nextval into ln_curr from dual;

      -- change the increment value of the sequence to 
      EXECUTE IMMEDIATE 'alter sequence MY_SEQ increment by '
        || ln_reset_increment ||' minvalue 0';

      -- advance the sequence to set it to 0
      select MY_SEQ.nextval into ln_reset_val from dual;

      -- set increment back to the previous(ly saved) value
      EXECUTE IMMEDIATE 'alter sequence MY_SEQ increment by '
        || ln_increment ;
    end;
    /

ПРИМЕЧАНИЯ:

  • как наилучшим образом защитить последовательность от доступа во время ее сброса, ПЕРЕИМЕНОВАТЬ ее ?
  • Здесь нужно проработать несколько тестовых примеров.
  • Первый проход, проверка нормативных случаев положительной, возрастающей, приращения 1.
  • Было бы лучше создать новую ПОСЛЕДОВАТЕЛЬНОСТЬ, добавить разрешения, переименовать существующие и новые последовательности, а затем повторно компилировать зависимости?
6
ответ дан 8 December 2019 в 14:46
поделиться

Просто предложите это как идею:

Если вам нужно решение, которое не требует постоянного DDL (т.е. не требует удаления, создания или сброса последовательностей) или даже каких-либо заданий, вы можете подумать о чем-то вроде этого (в принципе это только, я не тестировал этот подход, но уверен, что он сработает):

  1. Создайте единую последовательность.

  2. Создайте справочную таблицу с одной строкой для каждого года, например,

    YEARS (год НОМЕР (4,0) ПЕРВИЧНЫЙ КЛЮЧ, start_value NUMBER)

  3. Когда вы получаете NEXTVAL из последовательности, вам нужно вычесть start_value при запросе из таблицы YEARS за текущий год. Если год не найден, должна быть вставлена ​​новая строка (т. Е. При первом запуске процесса в любом данном году будет вставлено новое значение).

например, функция, например get_year_starting_value (pn_year IN NUMBER) RETURN NUMBER может запросить эту таблицу и вернуть начальное_значение для данного года; если он получит NO_DATA_FOUND , он может вызвать процедуру для его вставки, используя NEXTVAL из последовательности (зафиксированной в автономной транзакции, так что новое значение будет немедленно доступно для других сеансов, и так что функция не

5
ответ дан 8 December 2019 в 14:46
поделиться

Используйте задание, чтобы добиться цели. Сначала создайте хранимую процедуру для сброса вашей последовательности (я обычно использую решение DROP / CREATE, но вы можете использовать трюк spencer7593 ):

CREATE OR REPLACE PROCEDURE my_seq_reset AS
BEGIN
    EXECUTE IMMEDIATE 'DROP SEQUENCE my_seq';
    EXECUTE IMMEDIATE
      'CREATE SEQUENCE my_seq' ||
      '  MINVALUE 1 ' ||
      '  MAXVALUE 999999 ' ||
      '  START WITH 1 ' ||
      '  INCREMENT BY 1 ' ||
      '  NOCACHE';
END;

Затем создайте задание ( см. Здесь для справки):

BEGIN
  dbms_scheduler.create_job(
    job_name        => 'job$my_seq_reset',
    job_type        => 'STORED_PROCEDURE',
    job_action      => 'my_seq_reset',
    start_date      => TO_DATE('01-01-09', 'DD-MM-RR'),
    repeat_interval => 'FREQ=YEARLY;BYDATE=0101',
    enabled         => TRUE,
    auto_drop       => FALSE,
    comments        => 'My sequence yearly reset job.'
  );
END;

Готово.

4
ответ дан 8 December 2019 в 14:46
поделиться

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

На ум приходят 2 мысли.

  1. В 12 часов утра переустановите последовательность, это сложно, потому что вам нужно убедиться, что вы взяли любой код.
  2. Создайте последовательность для каждого года, возможно, даже включите ее в свой код, чтобы иметь возможность создавать последовательность, а затем динамически вызывать правильную последовательность для года.

Я бы предпочел вариант 2, поскольку он не пытаясь сделать что-нибудь необычное и всегда будет работать без сбоев, любые варианты, пытающиеся изменить саму последовательность, обязательно вас укусят.

1
ответ дан 8 December 2019 в 14:46
поделиться

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

http://www.psoug.org/reference/OLD/sequences.html?PHPSESSID=5949da378678fa6d24b6fcc6eaae9888

Мой подход будет заключаться в следующем:

  1. создать таблицу с годом и начальной последовательностью для этого года (вызовем эту таблицу year_seed)

  2. создайте процедуру, которая получает год, проверяет таблицу year_seed и, если это первая проверка за год, генерирует регистр с начальной последовательностью. Эта процедура также должна возвращать последовательность минус начальная последовательность для года.

Может быть, это не так просто, но я думаю, что это лучшее решение. Удачи

0
ответ дан 8 December 2019 в 14:46
поделиться
Другие вопросы по тегам:

Похожие вопросы: