要在更新属性上执行的TRIGGER?

时间:2011-11-28 20:20:56

标签: sql oracle triggers sqlplus

我遇到触发器问题,但我找不到原因。

这些是表格:

create table Properties(  
    idProperties number(10) NOT NULL , 
    Type varchar2(45) NOT NULL,
    ConstructionDate date NOT NULL,
    FloorLocation varchar(20),
    Balkony varchar2(10),
    Price number(10) NOT NULL,
    DateOfInsert date NOT NULL,
    DateOfExiration date NOT NULL,
    Address_FK number(20),
    PropertyType_FK number(20) NOT NULL,
    Service_FK number(20),
    Ownership_FK number(20),
    PropertyService_FK number(20))

create table Services(
    idServices number(10) NOT NULL,
    servicetype varchar2(20))

我正在尝试在状态字段从“NEW”更改为“APROVED”时编写一个触发器,以便在更新PROPERTY时执行,然后使用今天的日期(Sysdate)+ 90天更新到期日期。

我正在尝试这个,但它不起作用:

CREATE OR REPLACE TRIGGER T22
AFTER UPDATE ON Properties
FOR EACH ROW

Begin
  if :new.servicetype = 'APROVED' then
 :new.Servicetype := SYSDATE + 90;

end if;
End;

我是否需要使用属性表中的外键调用servicetype?或者这是对的,但我错过了什么?

2 个答案:

答案 0 :(得分:2)

您无法更改AFTER触发器中的值。您需要使用BEFORE触发器。

如果您使用的是Oracle 11.2,如果您尝试定义更改值的AFTER触发器,则应该出现“ORA-04084:无法更改此触发类型的新值”错误

SQL> create table t (
  2    col1 number,
  3    col2 date
  4  );

Table created.

SQL> create trigger trg_t
  2    after update on t
  3    for each row
  4  begin
  5    :new.col2 := sysdate + 90;
  6  end;
  7  /
create trigger trg_t
               *
ERROR at line 1:
ORA-04084: cannot change NEW values for this trigger type

另一方面,如果您将触发器创建为BEFORE UPDATE触发器,则它应该可以正常工作

SQL> ed
Wrote file afiedt.buf

  1  create or replace trigger trg_t
  2    before update on t
  3    for each row
  4  begin
  5    :new.col2 := sysdate + 90;
  6* end;
SQL> /

Trigger created.

答案 1 :(得分:0)

您必须从服务类型表中进行选择才能看到实际的服务描述,以便您可以比较之前和之后的描述。

此外,在更改即将插入的值时,您必须将此更改为更新前的触发器。

SQL> select * from properties;

        ID  SERVICEID EXPIRATIO
---------- ---------- ---------
       100          1 26-FEB-12
       200          2 28-NOV-11

SQL> select * from services;

 SERVICEID SERVICETYPE
---------- --------------------
         1 APPROVED
         2 NEW

触发器定义:

create or replace trigger trg1
  before update on properties
  for each row
declare
  l_old_servicetype services.servicetype%type;
  l_new_servicetype services.servicetype%type;
begin
  dbms_output.put_line('changing from ');

  select servicetype
    into l_old_servicetype
    from services
    where ServiceId = :old.serviceId;

  select servicetype
    into l_new_servicetype
    from services
    where ServiceId = :new.serviceId;

  dbms_output.put_line('old value : ' || l_old_servicetype );
  dbms_output.put_line('nwe value : ' || l_new_servicetype );


   if( l_old_servicetype = 'NEW' and l_new_servicetype='APPROVED') then
      :new.expirationDate := SYSDATE + 90;
   end if; 

end;
/

测试:

SQL> select * from properties;

        ID  SERVICEID EXPIRATIO
---------- ---------- ---------
       100          2 28-NOV-11
       200          2 28-NOV-11

SQL> update properties set serviceId = 1 where id = 100;
changing from
old value : NEW
nwe value : APPROVED

1 row updated.

SQL> select * from properties;

        ID  SERVICEID EXPIRATIO
---------- ---------- ---------
       100          1 26-FEB-12
       200          2 28-NOV-11