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
值。有很多对象要做一些本来不应该用触发器做的事情,而约束已经在做这些事情了。如果你只是在学习触发器,我猜你还没有学过关于包或集合的知识,这使得解决方案更不合适。这是我练习触发器的一些练习。你能帮忙吗?