如何通过自动开始日期和持续时间列创建一些东西来更新结束日期SQL

时间:2018-06-25 10:56:53

标签: sql oracle plsql

我想创建一些东西来自动更新表中的数据,但是我不知道该怎么用。

我有nr1个表

create table NR1
(
  id         INTEGER not null,
  price      INTEGER,
  price2     INTEGER,
  start_date DATE,
  end_date   DATE,
  duration   NUMBER
)

并且我尝试创建触发器,该触发器将在插入或更新表end_date之后始终更新,所以我尝试了以下操作:

create or replace trigger update_nr1_date
after update or insert on nr1
for each row
 when (new.id>0)
declare
begin
  UPDATE nr1
  set nr1.end_date =add_months(nr1.start_date, nr1.duration);
end;

但是它有突变问题,我对此有所了解,并且我理解了这一概念。我想要这样的触发器(不是sheduler,因为我想在插入或更新某些行后自动获取它)。在将数据插入表本身时是否可以补充丢失的列?

1 个答案:

答案 0 :(得分:4)

您的触发器需要在更新之前 才能更改触发器再次触发的行中的值;并且它需要通过赋值语句来修改the current row's (new) pseudorecord-您不应在触发器内发布单独的更新语句。首先,它将级联,在您的示例中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或更高,则可以use a virtual column instead,完全不需要触发器:

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

结束日期总是反映其他两列的值。