ORACLE сохранить столбцы идентификаторов всегда как один (1) - PullRequest
0 голосов
/ 30 апреля 2020

Я нашел несколько вопросов, похожих на мои, но не смог найти точное решение. В нашем хранилище данных мы иногда «удаляем» или «усекаем» таблицу, когда исправляем что-то или что-то подобное. Однако в Oracle столбец идентификаторов всегда начинается со следующей строки. Как сделать так, чтобы строка всегда начиналась с 1? Это может нарушить другие измерения и факты.

Возможно ли поместить эту конфигурацию навсегда или хотя бы в процедуру вставки?

Я всегда сбрасываю столбец идентификаторов вручную с помощью SQL Developer, поскольку я не знаю, как это сделать с помощью PL / SQL, как показано ниже (программное обеспечение на португальском языке, извините).

Пример созданного столбца идентификаторов:

CREATE TABLE "DW_FUNCESP"."D_DEPARTAMENTO"
(
    "ID_DEPARTAMENT" NUMBER(10,0) GENERATED BY DEFAULT ON NULL AS IDENTITY MINVALUE 1 MAXVALUE 9999999999999999999999999999 INCREMENT BY 1
    START WITH 1 CACHE 20 NOORDER NOCYCLE NOKEEP NOSCALE NOT NULL ENABLE
)

enter image description here

Спасибо!

Ответы [ 2 ]

2 голосов
/ 04 мая 2020

ПРИМЕЧАНИЕ:

подготовлен полный пример в качестве отдельного ответа , я только немного скорректировал решение для использования предложений ALTER TABLE (по согласованию ) полные кредиты @Bob Jarvis


Как уже упоминалось в комментариях, столбцы Oracle IDENTITY поддерживаются системой SEQUENCE, созданной системой. Некоторые подробности можно найти, например, здесь (с соответствующими ссылками на официальные документы Oracle).

Oracle не имеет простого способа сброса значения последовательности, однако вот подробное обсуждение того, как сделать это, используя довольно простые шаги

К сожалению (хотя это может быть к счастью) созданные системой последовательности не могут быть изменены таким образом, однако атрибуты последовательности могут можно изменить, введя команды ALTER TABLE MODIFY . Вы можете увидеть выдержку здесь

BEGIN
  -- Get the next value from the sequence
  EXECUTE IMMEDIATE 'SELECT ' || v_sequence || '.NEXTVAL ' ||
                    '  FROM DUAL'
    INTO v_num;

  -- Change the sequence so it decrements or increments to the desired
  -- start value the next time NEXTVAL is invoked.

  v_sql := 'ALTER TABLE ' || p_table_name || ' MODIFY ('
  || p_column_name || ' GENERATED BY DEFAULT ON NULL AS IDENTITY (INCREMENT BY '
  || (-v_num)  || ' MINVALUE 0))' ;
  EXECUTE IMMEDIATE v_sql;

  -- Decrement/increment the sequence to the desired start value
  EXECUTE IMMEDIATE 'SELECT ' || v_sequence || '.NEXTVAL FROM DUAL'
    INTO v_num;

  -- Reset the sequence so it uses the desired "increment by"
  v_sql := 'ALTER TABLE ' || p_table_name || ' MODIFY ('
  || p_column_name || ' GENERATED BY DEFAULT ON NULL AS IDENTITY (INCREMENT BY 1))' ;
  EXECUTE IMMEDIATE v_sql;
END;
/

И полный пример на dbfiddle

2 голосов
/ 01 мая 2020

РЕДАКТИРОВАТЬ: Учитывая то, что я знал в то время, я был прав, но, как оказалось, я не прав. В комментарии и соответствующей скрипте @ mickle sh показано, как это можно сделать с помощью ALTER TABLE MODIFY.... Я попросил его опубликовать ответ, чтобы его можно было принять - пока я оставляю этот ответ здесь, чтобы другие могли по крайней мере перейти по ссылке на его dbfiddle . Но на самом деле - это неверно.


Извините, но вы не можете этого сделать.

У меня был действительно хороший ответ, подготовленный о том, как получить имя последовательности, для которой система создает столбец GENERATED ALWAYS AS IDENTITY, и как преобразовать это значение LONG в строку символов, и как сбросить начальное значение последовательности - все это хорошо, и он сделал действительно хороший db <> fiddle - и затем, когда я все это завернул, я сделал последний проход - и получил

ORA-32793: cannot alter a system-generated sequence

Так что - Oracle не позволит вам изменить последовательность, которую он генерирует для столбца GENERATED ALWAYS AS IDENTITY. Я думаю, это означает, что вы застряли и вам придется смириться с тем фактом, что эти цифры не могут быть сброшены, чтобы начать с одного. Другие ваши варианты:

  1. Удалить и заново создать таблицу, что также потребует от вас воссоздания любых связанных триггеров и перекомпиляции любых процедур / функций / пакетов, которые используют эту таблицу, и, возможно, другие вещи, о которых я не думал; или

  2. Не используйте GENERATE ALWAYS AS IDENTITY, создайте свою собственную последовательность, используйте триггер, чтобы установить столбец идентификаторов из своей последовательности, и затем вы сможете использовать следующую процедуру для сброса вашей последовательности:

CREATE OR REPLACE FUNCTION RESET_SEQUENCE(pinSequence    IN VARCHAR2,
                                          pinStart_value IN NUMBER DEFAULT 1,
                                          pinIncrement   IN NUMBER DEFAULT 1)
  RETURN NUMBER
AS
  nVal  NUMBER;
BEGIN
  -- Get the next value from the sequence

  EXECUTE IMMEDIATE 'SELECT ' || pinSequence || '.NEXTVAL ' ||
                    '  FROM DUAL'
    INTO nVal;

  -- Change the sequence so it decrements or increments to the desired
  -- start value the next time NEXTVAL is invoked.

  EXECUTE IMMEDIATE 'ALTER SEQUENCE ' || pinSequence ||
                    '  INCREMENT BY ' || (nVal - (pinStart_value - pinIncrement)) * -1 ||
                    '  MINVALUE 0';

  -- Decrement/increment the sequence to the desired start value

  EXECUTE IMMEDIATE 'SELECT ' || pinSequence || '.NEXTVAL ' ||
                    '  FROM DUAL'
    INTO nVal;

  -- Reset the sequence so it uses the desired "increment-by"

  EXECUTE IMMEDIATE 'ALTER SEQUENCE ' || pinSequence ||
                    '  INCREMENT BY ' || pinIncrement ||
                    '  MINVALUE 0';

  RETURN 1;
EXCEPTION
  WHEN OTHERS THEN
    DBMS_OUTPUT.PUT_LINE('RESET_SEQUENCE : ' || SQLCODE || ' ' || SQLERRM);
    RETURN 0;
END RESET_SEQUENCE;
/

А вот db <> скрипка , показывающая общий тест функции RESET_SEQUENCE.

чел.

...