触发器

时间:2018-04-16 23:53:10

标签: sql if-statement plsql triggers oracle10g

所以我应该使用一个叫做课堂的桌子,包括学生,性别(M / F),座位#和座位(A / B)。我正在尝试创建一个触发器,阻止用户将学生插入已经存在的座位#和seatsection。此外,每个座位号的部分必须由同性别的学生占用。如果insert语句违反了这些规则,则应生成相应的错误消息。

这是我提出的草稿:

create or replace trigger trigstudent
before insert on classroom for each row
BEGIN
   if :new.seat# = :old.seat# then
      if :new.seatsection = :old.seatsection then
      -- raise an error message saying students can't take someone else's seat
      else
         if :new.gender = :old.gender then
            -- raise error message saying that only students of the same gender can sit together
         end if;
       end if;
    end if;

我显然后来意识到你不能使用" new"和#34;老"对于插入语句。所以我一直坚持这一点,不知道该怎么做。任何帮助将不胜感激。

1 个答案:

答案 0 :(得分:0)

使用触发器实现该逻辑实际上非常困难 - 它实际上是一个建模问题,即对表进行建模以允许标准数据库约束来控制数据验证。

特别是,没有数据库限制,面临的挑战是确保人X不添加/更新行,而Y人正在做同样的事情,并使用未提交的更改创建违规(您的会话无法看到。)

所以这里有一个如何实现它的例子,但这是一种强力方法,即在允许插入后我们触发一个触发器

  1. 锁定表格,因此我们可以独占访问它
  2. 查找数据违规,不仅针对此事务中修改的行,还针对所有
  3. 但我强调,这通常不是现实世界中的可持续解决方案'

    create or replace trigger trigstudent
    after insert or update on classroom 
    DECLARE
      x int;
    BEGIN
      lock table classroom in exclusive mode nowait;
    
      select count(*) into x from dual
      where exists ( 
        select count(*) from classroom group by seat# having count(*) > 1 
        );
    
      if x > 0 then
        raise_application_error(-20000,'There are some seat duplicates');
      end if;
    
      select count(*) into x from dual
      where exists ( 
        select count(distinct gender) from classroom group by section# having count(distinct gender) > 1
        );
    
      if x > 0 then
        raise_application_error(-20000,'There are some clashing genders per section');
      end if;
    end;
    /