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.
我一如既往地感谢任何帮助引导我朝着正确的方向前进。
答案 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;