Как сделать триггер для приращения последовательности уровня оператора в Oracle? - PullRequest
1 голос
/ 26 июня 2019

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

Я сделал простую числовую последовательность с INCREMENT_BY = 1. Я попытался решить мою задачу с помощью одного триггера, который увеличит мою последовательность версий и применяет ее к столбцу версий. Но, согласно документации Oracle, каждый триггер должен работать либо на уровне строк, либо на уровне операторов. Поэтому я пришел к выводу, что мне нужно как минимум 2 триггера: один для увеличения последовательности версий, а другой для применения ее к вставляемым строкам.

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

create or replace TRIGGER my_trigger
AFTER INSERT ON my_table
BEGIN
    my_sequence.NEXTVAL;
END;

Этот код стреляет PLS-00313: "NEXTVAL" not declared in this scope. Я также пытался использовать выражение " NEXTVAL " внутри " SELECT ", но оно также оказалось бесплодным. Чего мне не хватает?

Ответы [ 2 ]

2 голосов
/ 26 июня 2019

Чтобы все записи имели одинаковое значение из последовательности, один раз на INSERT, вы можете использовать глобальную переменную в составном триггере.

Создать тестовую таблицу и последовательность:

create table my_table(
  my_column number,
  other_column number
)
/
create sequence my_seq
/

Создать триггер:

CREATE OR REPLACE TRIGGER my_trigger
   FOR INSERT
   ON my_table
   COMPOUND TRIGGER
   g_value NUMBER;

   BEFORE STATEMENT
   IS
   BEGIN
      g_value := my_seq.NEXTVAL;
   END BEFORE STATEMENT;

   BEFORE EACH ROW
   IS
   BEGIN
      :new.my_column := g_value;
   END BEFORE EACH ROW;
END;
/

Теперь продемонстрируйте

insert into my_table values(null, 10)
/
insert into my_table values(null, 20)
/
insert into my_table 
select cast(null as number) my_column, level other_column from dual connect by level < 10
/
insert into my_table values(null, 40)
/

Результаты:

select * from my_table
/

MY_COLUMN OTHER_COLUMN
--------- ------------
        1           10
        2           20
        3            1
        3            2
        3            3
        3            4
        3            5
        3            6
        3            7
        3            8
        3            9
        4           40

Обратите внимание, что все средние строки имеют значение 3 в качестве значения MY_COLUMN.

Часть BEFORE STATEMENT получает одно значение из последовательности. Часть BEFORE EACH ROW присваивает одно и то же значение каждой строке, на которую воздействует инструкция.

Проблема с попыткой сделать это с помощью триггера уровня оператора в Oracle состоит в том, что у вас нет доступа к списку затронутых записей, поэтому вы не можете сказать «установить номер группы для записей 5,6,7». , 8,9 и 10 "

1 голос
/ 26 июня 2019

Вам просто нужно

:new.col1 := my_sequence.NEXTVAL;

назначение.

Если вы используете DB 12c, тогда измените таблицу как

ALTER TABLE mytable MODIFY col1 INTEGER DEFAULT my_sequence.NEXTVAL; или

если вы еще не добавили столбец идентификаторов или вам нужен новый столбец идентификаторов, используйте

ALTER TABLE mytable ADD id INTEGER GENERATED ALWAYS AS IDENTITY;

без использования триггера базы данных.

...