oracle触发错误ORA-01427&错误ORA-04091

时间:2012-05-08 14:31:39

标签: sql oracle triggers oracle10g

我有以下表格:

FACULTY表

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

课程表

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
   )

所以现在我想实现两件事

(1)在教师桌上更新faculty_id时。触发器将触发并使用新的faculty_id更新课程表中的相应行。它还将存储旧的faculty_id值,课程名称以及在course_log表中执行操作的日期。

以下是我的内容

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;

但是我收到以下错误。

  

错误ORA-01427:单行子查询返回多行ORA-06512:在“SYSTEM.UPDATE_FACULTY”,第2行ORA-04088:执行触发器'SYSTEM.UPDATE_FACULTY'时出错

关于如何解决它的任何想法?

(2)编写一个触发器,当尝试更改课程表中的course_id属性时触发,该触发器将检查课程表中是否已存在该值,并且如果它是新值则将成功更新。如果该值已存在于任何行中,则触发器将抛出一个应用程序错误,指出“该course_id已存在!更新未成功。”

下面是我的查询

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;

但是我收到了这个错误

  

错误ORA-04091:表SYSTEM.COURSE正在变异,触发器/函数可能看不到它ORA-06512:在“SYSTEM.UPDATE_COURSE_ID”,第5行ORA-04088:执行触发器'SYSTEM.UPDATE_COURSE_ID'时出错< / p>

1 个答案:

答案 0 :(得分:0)

对于第一个问题,既然您可能希望在course_log表中插入多行,则需要执行类似

的操作
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;

对于第二个问题,使用触发器没有意义。你想要使用约束。并且course_id course已经存在主键约束,这已经阻止了重复的course_id值。

用触发器执行此类操作是一个非常糟糕的主意。由于course上的行级触发器无法查询course表(如果您的insert语句始终为单行形式INSERT ... VALUES或触发器,则行级插入触发器除外使用自治交易,这两者都不合适。因此,如果您真的想用触发器执行此操作,则需要创建一个包含course_id值集合的包,一个初始化集合的before语句触发器,一个添加{{{ 1}}到集合,以及一个after语句触发器,它迭代集合并查找重复的:new.course_id值。这是很多对象要做的事情,首先不应该使用触发器,而且已经由约束完成了。如果你刚刚学习了触发器,我猜你还没有被教过关于包或集合的知识,这使得解决方案更不合适。