使用多个表数据触发

时间:2013-03-28 00:20:50

标签: oracle plsql triggers

create or replace 
trigger audit_att_eval
    AFTER INSERT OR UPDATE OF evaluation ON attendance
    FOR EACH ROW
DECLARE
  fname VARCHAR2(22);
  sname VARCHAR2(22);
  ctitle VARCHAR(30);
  ostartdate DATE;
  oinstructor VARCHAR2(12);
BEGIN
  SELECT student.first_name, student.surname, course.title, offering.start_date, offering.instructor
  INTO fname, sname, ctitle, ostartdate, oinstructor
  FROM student, course, offering, attendance
  WHERE student.student_id = attendance.student_id
  AND attendance.offering_id = offering.offering_id
  AND offering.course_id = course.course_id;
IF (:NEW.evaluation = 0)
    THEN
      INSERT INTO eval_audit
      VALUES (fname, sname, ctitle, ostartdate, oinstructor, :NEW.evaluation);   
  END IF;
END;

这会编译,但是当我通过尝试更新现有的出勤率来测试时,我得到以下错误:

Error report:
SQL Error: ORA-04091: table.ATTENDANCE is mutating, trigger/function may not see it
ORA-04088: error during execution of trigger 'OPS$1022005.AUDIT_ATT_EVAL'
04091. 00000 -  "table %s.%s is mutating, trigger/function may not see it"
*Cause:    A trigger (or a user defined plsql function that is referenced in
           this statement) attempted to look at (or modify) a table that was
           in the middle of being modified by the statement which fired it.
*Action:   Rewrite the trigger (or function) so it does not read that table.

我一如既往地感谢任何帮助引导我朝着正确的方向前进。

1 个答案:

答案 0 :(得分:1)

当我们执行一些DML操作(在你的情况下是INSERT / UPDATE)并且我们试图从同一个触发器中选择受影响的记录(你是从关注表中获取)时,通常会发生变异错误。所以基本上我们试图从拥有触发器的表中选择触发器中的记录。这会造成不一致,Oracle会抛出一个变异错误

create or replace 
trigger audit_att_eval
   AFTER INSERT OR UPDATE OF evaluation ON attendance
   FOR EACH ROW
DECLARE
  --fname VARCHAR2(22);
  --sname VARCHAR2(22);
  --ctitle VARCHAR(30);
  --ostartdate DATE;
  --oinstructor VARCHAR2(12);

CURSOR fetch_audit_details
   IS 
    SELECT student.first_name, student.surname, course.title, offering.start_date, offering.instructor
  --INTO fname, sname, ctitle, ostartdate, oinstructor
  FROM student
      , course
      , offering
   -- ,attendence   i have removed this because this is not allowed in this trigger
  WHERE student.student_id = :NEW.student_id    --use the new student id
  AND :NEW.offering_id = offering.offering_id   ----use the new offering_id
  AND offering.course_id = course.course_id;     

fetch_audit_row fetch_audit_details%ROWTYPE;

BEGIN

IF (:NEW.evaluation = 0)
  THEN
  --You need details only when evaluation value is 0 ,thats why i put this inside 
  --condition
   OPEN fetch_audit_details;
   FETCH fetch_audit_details INTO fetch_audit_row;
   CLOSE fetch_audit_details;

  --check whether this cursor returns null ,do what you need to do in this situation??

 INSERT INTO eval_audit
     VALUES (fetch_audit_row.first_name, fetch_audit_row.surname, fetch_audit_row.title, fetch_audit_row.start_date, fetch_audit_row.instructor, 0);   
   END IF;
  END;