Here\'s the problem:
Create a trigger that prevents any change to the taking relation that would drop the overall average grade in any particular class below 2.5. No
use this statement inside DECLARE
, it will work.
pragma autonomous_transaction;
First you need to read about triggers, mutating table error and compound triggers: http://docs.oracle.com/cd/E11882_01/appdev.112/e25519/triggers.htm#LNPLS2005
Your trigger is AFTER UPDATE OR INSERT OR DELETE. Means if you run UPDATE OR INSERT OR DELETE statements on this table, the trigger will fire. But you are trying to update the same table again inside your trigger, which is compl. wrong. This this is why you are getting the error. You cannot modify the same table the trigger is firing on. The purpose of trigger is to fire automatically when table is updated, inserted or deleted in your case. What you need is some procedure, not trigger.
If you want retrieve other data by join other table(TABLE_ADDRESS). Here is my solution.
CREATE OR REPLACE TRIGGER TRIGGER_TABLE_ACTIVITIES AFTER INSERT ON TABLE_NAME
FOR EACH ROW
DECLARE
V_ADDRESS VARCHAR2(100);
BEGIN
SELECT A.ADDRESS INTO V_ADDRESS
FROM TABLE_ADDRESS A
WHERE A.ADDRESSID = :NEW.ADDRESSID
;
INSERT INTO TABLE_ACTIVITIES(
NAME, ADDRESS)
VALUES(:NEW.NAME, V_ADDRESS);
END;
/
Even we have ended up with same issue in our project. But after searching in few oracle forums, we have found the below solution.
1)Save the Old/New Column data in a temporary table as pat of row level trigger. 2) Write a statement level trigger and use the data saved in step 1.
This would solve the issue I think.
I think you can fix this by rewriting this as a before trigger, rather than an after trigger. However, this might be a little complicated for inserts and deletes. The idea is:
CREATE OR REPLACE TRIGGER stopChange
BEFORE UPDATE OR INSERT OR DELETE ON taking
REFERENCING OLD AS old
NEW AS new
FOR EACH ROW
DECLARE
grd_avg taking.grade%TYPE;
BEGIN
SELECT (SUM(grade) - oldgrade + new.grade) / count(*)
INTO grd_avg
FROM taking
WHERE studentnum = :new.studentnum
AND schedulenum = :new.schedulenum
AND semester = :new.semester;
IF grd_avg < 2.5 THEN
new.grade = old.grade
END IF;
END;
I had the same issue and I noticed that if you do a select on the same table you put the trigger on you may/will get this problem. You can remove FOR EACH ROW or use the data in :New to do the calculation (if possible) and then make the update.
In your case it will make more sense to use separate table to have the avg_grade per semester.