Oracle 插入触发器前

Oracle 插入触发器前,oracle,plsql,triggers,Oracle,Plsql,Triggers,当某些条件为真时,我想在插入触发器插入表之前禁用in 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_special

当某些条件为真时,我想在插入触发器插入表之前禁用in

 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;

我如何才能做到这一点?

假设您谈论的是Oracle,那么,您可以:

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

编辑:一般来说,让插入悄悄地失败是个坏主意。如果尝试在插入后触发器中删除记录,也可能会遇到变异表错误

相反,只是不插入记录开始。 可能实现这一点的一种方法是在insert语句末尾添加如下内容:

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

这应该只在进入者计数时执行insert语句。假设您谈论的是Oracle,那么,您可以:

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

编辑:一般来说,让插入悄悄地失败是个坏主意。如果尝试在插入后触发器中删除记录,也可能会遇到变异表错误

相反,只是不插入记录开始。 可能实现这一点的一种方法是在insert语句末尾添加如下内容:

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
仅当进入者计数尝试引发错误时,才应执行insert语句:

IF entrants_count >= max_entrants THEN
  raise_application_error(-20001, 'Cannot perform this insert!');
END IF;
尝试引发错误:

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

我知道我可以抛出一个错误,但我不想抛出它,只是禁用一个插入操作,如果条件为真,也许最好使用插入后触发器,在那里简单地删除新插入的行?我知道我可以抛出一个错误,但我不想抛出它,只是禁用一个插入操作,如果条件为真,则最好使用插入后触发器,其中只删除新插入的行。这种方法的另一个问题是,两个并发事务可能会插入最后一条允许的记录,因为它们还看不到另一条记录。这种方法的一些其他问题包括:PS。我过早地点击了添加注释。我想说。。。此方法的其他一些问题包括:如果max_Entrators.max_students_编号更新为较小的编号,该怎么办?如果应用程序中的相关行超过最大学生数,会发生什么情况?b如果application.speciality更新了怎么办?这可能会导致计数超过相关的Max ExtRunt.Max SuxStudio编号。为了避免基于触发器的方法出现这些问题,可以考虑使用物化视图来实现此约束。您可以在和中找到一些示例。此方法的另一个问题是,两个并发事务可能会插入最后一条允许的记录,因为它们还看不到另一条记录。此方法的其他一些问题包括:PS。我过早地点击了Add Comment。我想说。。。此方法的其他一些问题包括:如果max_Entrators.max_students_编号更新为较小的编号,该怎么办?如果应用程序中的相关行超过最大学生数,会发生什么情况?b如果application.speciality更新了怎么办?这可能会导致计数超过相关的Max ExtRunt.Max SuxStudio编号。为了避免基于触发器的方法出现这些问题,可以考虑使用物化视图来实现此约束。您可以在和找到一些示例。