Ваш триггер должен перед обновлением , чтобы изменить значение в строке, по которой триггер срабатывает снова; и он должен изменить псевдокорд текущей строки * (новый) с помощью оператора присваивания - вам не следует выдавать отдельный оператор обновления внутри триггера. Для начала он будет каскадным, и в вашем примере woudl попытается обновить каждую строку в таблице. Но это также вызывает ошибку изменяющейся таблицы - вы пытаетесь обновить строки в таблице, против которой выступает триггер. Есть обходные пути, когда это действительно необходимо, но это не так, этого обновления просто не должно быть.
Так вы бы сделали:
create or replace trigger update_nr1_date
before update or insert on nr1
for each row
when (new.id>0)
begin
:new.end_date := add_months(:new.start_date, :new.duration);
end;
/
Но если вы на 11g или выше, вы можете использовать виртуальный столбец вместо , без использования триггера вообще:
create table NR1
(
id INTEGER not null,
price INTEGER,
price2 INTEGER,
start_date DATE,
end_date DATE generated always as (add_months(start_date, duration)) virtual,
duration NUMBER
)
Затем при вставке пропустите этот столбец в выражении:
insert into nr1 (id, price, price2, start_date, duration)
values (1, 2, 3, date '2018-06-01', 3);
1 row inserted.
select * from nr1 where id = 1;
ID PRICE PRICE2 START_DATE END_DATE DURATION
---------- ---------- ---------- ---------- ---------- ----------
1 2 3 2018-06-01 2018-09-01 3
Дата окончания всегда отражает значения двух других столбцов.