PL / SQL触发器不会更改表属性的值

时间:2018-03-06 21:03:03

标签: plsql triggers aggregate-functions

这是我上一篇文章中的后续问题: PL/SQL Triggers with aggregate function

我有一个名为updategpa的触发器,只要在student表中更改成绩,就会更新course表中的gpa。

此触发器由于“更新了”而被调用'当course表收到新数据时,触发器更新assignments表。

问题:在调用触发器之前和之后gpa是0

有谁可以说我的触发器出了什么问题?

drop table courses;
drop table student;
drop table assignments;

create table student (sid integer, sname char(10), saddress char(10), gpa integer);
create table courses (sid integer, cid integer, cgrade integer);
create table assignments ( sid integer, cid integer, aid integer, agrade integer);

insert into student (sid, sname, saddress, gpa) values (1, 'Mike', 'Brighton', 0);
insert into courses (sid, cid, cgrade) values(1, 2000, 0);

insert into assignments values(1, 2000, 1, 70);
insert into assignments values(1, 2000, 2, 80);

create or replace trigger updateGrades before insert or update or delete of agrade on assignments for each row
    begin
      if inserting then
          update courses set cgrade = :new.agrade where cid = :new.cid and sid = :new.sid;
      elsif updating then
          update courses set cgrade = :old.agrade + (:new.agrade - :old.agrade)
            where cid = :new.cid and sid = :new.sid;
      elsif deleting then
          delete from courses where cid = :new.cid and sid = :new.sid;
      end if;
    end;
/
show errors;

create or replace trigger updategpa after insert or update or delete of cgrade on courses for each row
    begin
        if inserting then
            update student set gpa =
              (select avg(cgrade) from courses inner join student on courses.sid = student.sid
              )
              where sid = 1;
        elsif inserting then
            update student set gpa =
              (select avg(cgrade) from courses inner join student on courses.sid = student.sid
              )
              where sid = 1;
        elsif deleting then
            delete from student where sid = :new.sid;
        end if;
    end;
/
show errors;

select * from courses;
select * from student;
select * from assignments;

update assignments set agrade = agrade + 5;

select * from courses;
select * from student;
select * from assignments;

控制台输出:

SQL> select * from student;

       SID SNAME      SADDRESS          GPA
---------- ---------- ---------- ----------
         1 Mike       Brighton            0

SQL> select * from assignments;

       SID        CID        AID     AGRADE
---------- ---------- ---------- ----------
         1       2000          1         70
         1       2000          2         80

SQL>
SQL> update assignments set agrade = agrade + 5;

2 rows updated.

SQL>
SQL> select * from courses;

       SID        CID     CGRADE
---------- ---------- ----------
         1       2000         85

SQL> select * from student;

       SID SNAME      SADDRESS          GPA
---------- ---------- ---------- ----------
         1 Mike       Brighton            0

SQL> select * from assignments;

       SID        CID        AID     AGRADE
---------- ---------- ---------- ----------
         1       2000          1         75
         1       2000          2         85

1 个答案:

答案 0 :(得分:0)

问题的根源是您的updategpa触发器需要跟踪行级别对COURSES的每次更改,然后汇总这些更改以维护每个学生的运行总计。这是复合触发器的一个很好的用例。 Find out more

create or replace trigger updategpa  
for update or update or insert on courses compound trigger   

  type cid_nt is table of courses%rowtype;  
  upd_recs cid_nt;  

  before statement is   
  begin  
    upd_recs := cid_nt();  
  end before statement;  

  before each row is   
  begin  
    upd_recs.extend();  
    if inserting or updating then   
        upd_recs(upd_recs.count()).sid := :new.sid;  
    else  
        upd_recs(upd_recs.count()).sid := :old.sid;  
    end if;  
  end before each row;  

  after each row is   
  begin  
    null;  
  end after each row;  

  after statement is   
  begin  
    for idx in 1 .. upd_recs.count() loop  
      update student   
      set gpa = (select avg(cgrade)  
                 from courses   
                 where courses.sid = student.sid )  
         where sid = upd_recs(idx).sid;  
    end loop;    
  end after statement;  

end;  

以下是a LiveSQL demo(需要免费的OTN帐户)。