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

Sql oracle触发错误ORA-01427&;错误ORA-04091,sql,oracle,triggers,oracle10g,Sql,Oracle,Triggers,Oracle10g,我有以下表格: 教员表 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_I

我有以下表格:

教员表

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
   )
课程表

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) 在教员表上更新教员id时。触发器将使用新的教员id触发并更新课程表中的相应行。它还将在课程日志表中存储旧教员id值、课程名称和执行操作的日期

下面是我得到的

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) 编写一个触发器,在尝试更改课程表中的课程id属性时触发,该触发器将检查该值是否已存在于课程表中,如果该值是新值,则将成功更新。如果该值已存在于任何行中,触发器将抛出一个应用程序错误,说明“课程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”时出错


对于第一个问题,由于您可能希望在
课程日志
表中插入多行,因此需要执行以下操作

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
中,您已经在
course\u id
上设置了一个主键约束,它已经防止了重复的
course\u id


用触发器强制执行这类操作是一个非常糟糕的主意。由于
课程
上的行级触发器无法查询
课程
表(如果insert语句始终是单行形式的
insert…VALUES
或使用自主事务的触发器,则行级insert触发器除外,这两种情况在此处都不适用)。因此,如果您真的想使用触发器执行此操作,您需要创建一个包含
课程id
值集合的包,一个初始化集合的before语句触发器,一个将
:new.course\u id
添加到集合的行级触发器,以及一个after语句触发器,它在集合上迭代并查找重复的
course\u id
值。有很多对象要做一些本来不应该用触发器做的事情,而约束已经在做这些事情了。如果你只是在学习触发器,我猜你还没有学过关于包或集合的知识,这使得解决方案更不合适。

这是我练习触发器的一些练习。你能帮忙吗?