简体   繁体   中英

oracle triggers error ORA-01427 & error ORA-04091

I have the following tables:

FACULTY table

CREATE TABLE  "FACULTY" 
   (    "FACULTY_ID" NUMBER(3,0), 
    "FACULTY_NAME" VARCHAR2(30), 
    "FACULTY_DEAN" VARCHAR2(30), 
     CONSTRAINT "FACULTY_PK" PRIMARY KEY ("FACULTY_ID") ENABLE
   )

COURSE table

CREATE TABLE  "COURSE" 
   (    "COURSE_ID" NUMBER(5,0), 
    "COURSE_NAME" VARCHAR2(50), 
    "COURSE_LEVEL" NUMBER, 
    "FACULTY" NUMBER, 
     CONSTRAINT "COURSE_PK" PRIMARY KEY ("COURSE_ID") ENABLE
   )

so now i want to achieve two things

(1) when a faculty_id is updated on the faculty table. a trigger will fire and update the corresponding rows in the course table with new faculty_id. it will also store the old faculty_id value, name of course, and the date in which the operation is performed in a course_log table.

Below is what I got

create or replace trigger update_faculty
after update on faculty
for each row
begin
   insert into course_log 
     values (:old.faculty_id, 
             (select course_name 
                from course 
               where faculty=:old.faculty_id),
             sysdate);
   update course 
      set faculty=:new.faculty_id 
    where faculty=:old.faculty_id;
end;

But I get the following error.

error ORA-01427: single-row subquery returns more than one row ORA-06512: at "SYSTEM.UPDATE_FACULTY", line 2 ORA-04088: error during execution of trigger 'SYSTEM.UPDATE_FACULTY'

any ideas on how to solve it?

(2) Write a trigger that fires when try change the course_id attribute in the course table, which will check whether the value already exists in the course table and will update successfully if it is a new value. If the value already exists in any row, the trigger will throw an application error saying "The course_id already exists! Update not successful."

below is my query

CREATE OR REPLACE TRIGGER  "UPDATE_COURSE_ID" 
after update on course
for each row
declare 
    error number;
begin
    select count(*) 
      into error 
    from course
    where course_id=:new.course_id;

    if error > 0 then
        raise_application_error (-20000,'The course_id already found! Update not success'); 
    end if;
    if error = 0 then
        update course set course_id=:new.course_id where course_id=:old.course_id;
    end if;
end;

But I got this error

error ORA-04091: table SYSTEM.COURSE is mutating, trigger/function may not see it ORA-06512: at "SYSTEM.UPDATE_COURSE_ID", line 5 ORA-04088: error during execution of trigger 'SYSTEM.UPDATE_COURSE_ID'

For the first question, since you may want to insert multiple rows into the course_log table, you'd need to do something like

create or replace trigger update_faculty
  after update on faculty
  for each row
begin
   -- I'm guessing about the definition of the course_log table
   insert into course_log( faculty_id, course_name, log_date ) 
     select :old.faculty_id, course_name, sysdate
       from course 
      where faculty=:old.faculty_id;

   update course 
      set faculty=:new.faculty_id 
    where faculty=:old.faculty_id;
end;

For the second question, it doesn't make sense to use a trigger. You'd want to use a constraint. And you already have a primary key constraint on course_id in course which is already preventing duplicate course_id values.

Enforcing this sort of thing with triggers is a really poor idea. Since a row level trigger on course cannot query the course table (with the exception of a row-level insert trigger if your insert statements are always of the single-row form INSERT ... VALUES or triggers that use autonomous transactions, neither of which is appropriate here). So if you really wanted to do this with triggers, you'd need to create a package that contained a collection of course_id values, a before statement trigger that initializes the collection, a row-level trigger that adds the :new.course_id to the collection, and an after statement trigger that iterates over the collection and looks for duplicate course_id values. That's a lot of objects to do something that shouldn't be done with triggers in the first place and that is already being done by your constraint. If you're just learning about triggers, I'm guessing that you haven't been taught about packages or collections yet which makes the solution even less appropriate.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM