使用条件创建触发器

时间:2015-01-03 01:00:00

标签: oracle plsql triggers

我正在尝试创建一个触发器,当学生在没有先决条件的情况下注册课程时,会在ALARMS表中插入值student_idcourse_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

1 个答案:

答案 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表示没有或满足所有先决条件,非零表示未满足先决条件的数量。