我正在尝试创建一个触发器,当学生在没有先决条件的情况下注册课程时,会在ALARMS表中插入值student_id
和course_id
,但是我失败了。
这是我的触发器:
CREATE OR REPLACE TRIGGER ALARM_TRIGGER
BEFORE INSERT OR UPDATE OF student_id, course_id ON students_courses
FOR EACH ROW
BEGIN
insert into alarms(student_id, course_id) values(:NEW.student_id, :NEW.course_id);
END;
表格:
1-COURSES:有course_id(PK)和course_name。
2-STUDENTS:有student_id(PK)和student_name。
3-STUDENTS_COURSES:每个学生都有自己的课程。
4-PREREQUISITE_COURSES:每个课程都有先决条件。
5-ALARMS:当任何学生在没有先决条件的情况下注册课程时,触发存储student_id,course_id。
这是课程先决条件表的示例:
COURSE_NUMBER COURSE_PREREQUISITE 1 null 2 1 3 null 4 3
答案 0 :(得分:1)
如果学生在没有先决条件的情况下注册课程,则查询先决条件的结果将为NULL。因此,如果课程有先决条件且学生已采取先决条件,则您希望结果相同。这使后续逻辑更容易。因此,如果课程具有学生未的先决条件,则结果将是先决条件的课程ID(您可以使用它来显示有意义的错误消息)。
如果课程没有先决条件,返回NULL的查询很简单:
select P.COURSE_PREREQUISITE Result
into RequiredReq
from Prerequisites P
where P.COURSE_NUMBER = :new.course_id;
当然,如果有先决条件,它会返回先决条件的课程ID,但我们稍后会处理这个问题。现在我们想加入STUDENTS_COURSES表:
join STUDENTS_COURSES SC
on SC.COURSE_NUMBER = P.COURSE_PREREQUISITE
and SC.Student_ID = :new.Student_ID
然而,这并不能为我们提供所需的一切。首先,如果学生没有采取先决条件,查询将不返回任何内容,因此我们将收到NO_DATA_FOUND错误。其次,如果学生已采取先决条件,它将返回课程ID,但在这种情况下,我们希望它返回NULL。
如果我们将内部联接转换为左外部联接,让我们看看我们得到了什么:
select P.COURSE_PREREQUISITE Result
into RequiredReq
from Prerequisites P
left join STUDENTS_COURSES SC
on SC.COURSE_NUMBER = P.COURSE_PREREQUISITE
and SC.Student_ID = :new.Student_ID
where P.COURSE_NUMBER = :new.course_id;
这给了我们想要的一切,但不是很正确。如果先决条件已满足 ,则获取NULL;如果具有,则获取先决条件值。所以为了改变它,我们在查询中只需要一点逻辑:
select case when P.Prerequisite is null then null --> No prerequisite
when SC.StudentID is not null then null --> Prerequisite met
else P.Prerequisite end Result --> Prerequisite not met
into RequiredReq
from Prerequisites P
left join STUDENTS_COURSES SC
on SC.COURSE_NUMBER = P.COURSE_PREREQUISITE
and SC.Student_ID = :new.Student_ID
where P.COURSE_NUMBER = :new.course_id;
现在,NULL表示课程没有先决条件或学生已达到先决条件。只有当课程具有学生未满足的先决条件和时,才会返回一个值,这是未满足先决条件的课程编号。
注意:只有在您的示例数据中暗示每个课程只有一个先决条件时,此方法才有效。如果可以有一个或多个先决条件,您可能希望更改为数字返回值,0表示没有或满足所有先决条件,非零表示未满足先决条件的数量。