2011-06-10 204 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;