【问题标题】:SQL - Trigger to check insert of date on each studentSQL - 触发器检查每个学生的日期插入
【发布时间】:2020-08-31 13:32:56
【问题描述】:

我正在尝试创建一个触发器,用于检查我插入的日期是否大于表中每个学生的日期。控件只需要在 ID 和 DATE 上。

STUDENT_EXAMS

id_student subject    mark        date_exam
1          Chemistry  6          'May-05-2020'
2          Maths      7          'May-01-2020'

合法插入

insert into STUDENT_EXAMS (id_student, subject, mark, date_exam)
values (1, 'History', 8, 'May-06-2020');

insert into STUDENT_EXAMS (id_student, subject, mark, date_exam)
values (2, 'Biology', 8, 'May-05-2020');

非法插入

insert into STUDENT_EXAMS (id_student, subject, mark, date_exam)
values (1, 'History', 8, 'May-04-2020');

insert into STUDENT_EXAMS (id_student, subject, mark, date_exam)
values (2, 'Biology', 10, 'Apr-30-2020');

这是我尝试创建的触发器,但它不起作用,我不知道如何在每个 ID_STUDENT 上也插入一个控件。

create or replace trigger check_date
before insert on STUDENT_EXAM
for each row
begin
    if (:new.date_exam > :old.date_exam) then
        insert into STUDENT_EXAM (id_student, subject, mark, date_exam)
        values (:new.id_student, :new.subject, :new.mark, :new.date_exam); 
end if;
end;

【问题讨论】:

    标签: sql oracle plsql triggers database-trigger


    【解决方案1】:

    也许这是您感兴趣的。当插入行的 date_Exam 小于 id 的 date_Exam 最大值时,它会阻止插入 STUDENT_EXAM 表。

      create or replace trigger check_date
        before insert on STUDENT_EXAM
        for each row
        DECLARE 
    
        lv_date_exam DATE;
        begin
    
             select max(date_exam) into lv_date_exam 
             from student_exam where id = :new.id;
    
            if (:new.date_exam < lv_date_exam) then
               raise_application_error(-20000
                , 'Cannot insert record as date_exam '||:new.date_exam||' is less than max date_exam '||lv_date_exam);
        end if;
        end;
    

    [由 Littlefoot 编辑,说明为什么它会因 mutating table 错误而失败]

    您建议的表格和触发器:

    SQL> create table student_exam (id number, date_exam date);
    
    Table created.
    
    SQL> create or replace trigger check_date
      2      before insert on STUDENT_EXAM
      3      for each row
      4      DECLARE
      5
      6      lv_date_exam DATE;
      7      begin
      8
      9           select max(date_exam) into lv_date_exam
     10           from student_exam where id = :new.id;
     11
     12          if (:new.date_exam < lv_date_exam) then
     13             raise_application_error(-20000
     14              , 'Cannot insert record as date_exam '||:new.date_exam||' is less than max date_exam '||lv_date_exam);
     15      end if;
     16      end;
     17  /
    
    Trigger created.
    

    测试:

    这行得通:

    SQL> insert into student_exam (id, date_exam) values (1, sysdate);
    
    1 row created.
    

    但这不是:

    SQL> insert into student_exam (id, date_exam)
      2    select 1, sysdate - 10 from dual union all
      3    select 1, sysdate + 20 from dual;
    insert into student_exam (id, date_exam)
                *
    ERROR at line 1:
    ORA-04091: table SCOTT.STUDENT_EXAM is mutating, trigger/function may not see
    it
    ORA-06512: at "SCOTT.CHECK_DATE", line 6
    ORA-04088: error during execution of trigger 'SCOTT.CHECK_DATE'
    
    
    SQL>
    

    【讨论】:

    • 不幸的是,它因 mutating table 错误而惨遭失败。
    • @Littlefoot,你能解释一下为什么它不起作用吗?因为我正在测试它,现在看来可行,感谢您的帮助!
    • @Gwynbleidd,我通过添加显示为什么的示例来编辑作者的消息。 VN'sCorner,随时回滚该编辑。我没有发布答案,只是试图解释它的问题所在。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-28
    • 2013-10-06
    • 2011-03-06
    • 1970-01-01
    相关资源
    最近更新 更多