0

我有以下表格:

教员表

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 表上更新时。触发器将触发并使用新的faculty_id 更新课程表中的相应行。它还将在 course_log 表中存储旧的 Faculty_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) 编写一个触发器,当尝试更改课程表中的 course_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' 期间出错

4

1 回答 1

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_idcourse其中已经防止重复course_id值。

用触发器强制执行这种事情是一个非常糟糕的主意。由于行级触发器course无法查询course表(如果您的插入语句始终为单行形式INSERT ... VALUES或使用自治事务的触发器,则行级插入触发器除外,这两种情况都不适用)。因此,如果您真的想使用触发器执行此操作,您需要创建一个包含course_id值集合的包、一个用于初始化集合的 before 语句触发器、一个:new.course_id将遍历集合并查找重复的语句触发器course_id价值观。这是很多对象要做的事情,这些事情一开始就不应该用触发器来做,而且你的约束已经在做这些事情了。如果您只是在学习触发器,我猜您还没有学习过包或集合,这使得解决方案更加不合适。

于 2012-05-08T14:57:14.560 回答