2015-06-04 56 views
0

我想寫一個觸發器,它可以阻止從表中刪除記錄並阻止更新時的工資降低。它作爲兩個單獨的觸發器運行良好,但我想合併成一個。04098.「trigger'%s。%s'無效且重新驗證失敗」

這是合併後,我的觸發:

CREATE OR REPLACE TRIGGER test 
    BEFORE DELETE OR UPDATE 
    ON emp 
    FOR EACH ROW 
    BEGIN 
     IF UPDATING THEN 
     IF :NEW.sal < :OLD.sal THEN 
      raise_application_error(-20500, 'You cannot decrease emp salary'); 
     END IF; 
     ELSE DELETING THEN 
     raise_application_error(-20500, 'You cannot delete records from emp'); 
     END IF; 
    END; 

問題是,當我嘗試更新或刪除記錄,我得到一個錯誤:

04098. 00000 - "trigger '%s.%s' is invalid and failed re-validation" 
*Cause: A trigger was attempted to be retrieved for execution and was 
      found to be invalid. This also means that compilation/authorization 
      failed for the trigger 

我認爲有一個問題解決此行 - BEFORE DELETE OR UPDATE,因爲如我所知如果我FOR EACH ROW的說法,我應該寫爲BEFORE UPDATE on sal,但後來我不知道如何加入BEFORE DELETE陳述到此。

編輯:
問題是在ELSE附近的陳述。它應該更改爲ELSIF

+1

請嘗試用'elsif'替換'else'(或刪除'刪除然後')。 –

+0

你是100%正確的,我完全錯過了它。 – Gregy

+2

我會盡一切努力使您的觸發器工作,因爲它禁止薪水減少。 ;-) –

回答

2

您的IF語句語法不正確。它應該是:

CREATE OR REPLACE TRIGGER test 
    BEFORE DELETE OR UPDATE 
    ON emp 
    FOR EACH ROW 
BEGIN 
    IF UPDATING AND :NEW.sal < :OLD.sal THEN 
    raise_application_error(-20500, 'You cannot decrease emp salary'); 
    ELSIF DELETING THEN 
    raise_application_error(-20500, 'You cannot delete records from emp'); 
    END IF; 
END test; 

我還將UPDATING案例中使用的兩個IF語句合併爲一個,以使它更簡單。

編輯

的情況下,你不希望允許薪金降低另一種可能的解決辦法是悄悄更改薪水恢復到原來的值,如:

CREATE OR REPLACE TRIGGER test 
    BEFORE DELETE OR UPDATE 
    ON emp 
    FOR EACH ROW 
BEGIN 
    IF UPDATING AND :NEW.sal < :OLD.sal THEN 
    :NEW.sal := :OLD.sal; -- restore original salary 
    ELSIF DELETING THEN 
    raise_application_error(-20500, 'You cannot delete records from emp'); 
    END IF; 
END test; 
+0

你是對的,但我已經發現,在更新多個記錄的情況下,觸發器將不起作用。例如,如果我想要改變所有約翰遜姓氏的人 - WHERE emp_name ='約翰遜',如果新薪水會降低其中一個觸發器會阻止整個更新。我該如何保護? – Gregy

+0

看我的編輯.... –