2011-06-10 158 views
0

我想插入触发之前禁用在插入表时INSERT触发器

create or replace trigger CHECK_FOR_MAX_ENTRANTS 
before insert on application 
declare 
    entrants_count number; 
    max_entrants number; 
begin 
    select count(*) into entrants_count from application 
    where id_speciality = :new.id_speciality; 

    select max_students_number into max_entrants from speciality s 
    where s.id_speciality = :new.id_speciality; 

    IF entrants_count >= max_entrants THEN 
     **disable this insert** 
end; 

我怎样才能做到这一些条件为真之前?

+2

这种方法的另一个问题是,两个并发事务可以插入“最后”一个允许的记录,因为他们看不到其他的记录呢。 – 2011-06-10 19:27:54

+0

此方法的其他一些问题包括: – 2011-06-13 13:17:10

+0

PS。我很快就点击了“添加评论”。我想说...这种方法的其他一些问题包括:a)如果max_entrants.max_students_number更新为更小的数字会怎样?如果超过max_students_number,应用程序中的相关行会发生什么? b)如果application.speciality更新会怎么样?这可能会导致计数超过相关的max_entrants.max_students_number。 – 2011-06-13 13:39:28

回答

3

假设你正在谈论甲骨文,那么,在地方禁用此插入你可以:

IF entrants_count >= max_entrants THEN 
    raise_application_error(-21010, 'Max number of Entrants Reached'); 
END IF; 

参见:http://download.oracle.com/docs/cd/B19306_01/appdev.102/b14261/errors.htm#sthref2006

编辑:它通常是一个坏主意,有插入失败默默(你要求)。如果您尝试在后插入触发器中删除记录,也可能会遇到变异表错误。

相反,只是不要插入记录开始。 一个你也许可以做到这一点的方法是这样的添加到您的插入语句的末尾:

WHERE EXISTS SELECT null FROM 
(SELECT COUNT(*) entrants_count FROM application 
WHERE id_speciality = :new.id_speciality) a, 
(SELECT max_students_number max_entrants 
FROM speciality WHERE id_speciality = :new.id_speciality) s 
WHERE a.entrants_count < s.max_entrants 

时entrants_count < max_entrants(你想要的)这应该只执行INSERT语句。

+0

+1打我4分钟;) – tbone 2011-06-10 18:00:06

+0

我知道我可以抛出一个错误,但我不想抛出它,只需禁用插入操作,也许最好在插入触发器后使用,其中只需删除新插入的行如果条件成立? – maks 2011-06-10 18:05:31

2

尝试提高一个错误:

IF entrants_count >= max_entrants THEN 
    raise_application_error(-20001, 'Cannot perform this insert!'); 
END IF;