2017-06-15 78 views
1

我正在爲公司數據庫編寫觸發器,並且此觸發器旨在更新員工的名稱(例如更改名稱的罕見情況)與前一個不同,或NOT NULL。觸發器中的更新名稱(與以前不同)SQL

這是我寫的代碼。它編譯,但它給我錯誤的更新(ORA-04091:表COMPANY.EMPLOYEE變異,觸發器/函數可能看不到 它)。我注意到這是由FOR EACH ROW引起的,但我無法刪除,因爲否則:new:old引用將不起作用。

CREATE OR REPLACE TRIGGER NO_INVALID_NAME 
AFTER UPDATE OF EMPLOYEE_NAME ON EMPLYEE 
FOR EACH ROW 
DECLARE 
    INVALID_NAME EXCEPTION; 
    CORRECT_NAME EXCEPTION; 

BEGIN 
    UPDATE EMPLOYEE 
    SET EMPLOYEE_NAME =:NEW.EMPLOYEE_NAME 
    WHERE EMPLOYEE_NAME =:OLD.EMPLOYEE_NAME; 

    IF :NEW.EMPLOYEE_NAME <> :OLD.EMPLOYEE_NAME AND IS NOT NULL THEN 
    RAISE INVALID_NAME; 
    ELSE 
    RAISE CORRECT_NAME; 
    END IF; 

EXCEPTION 
    WHEN NOME_NON_CORRETTO 
    THEN RAISE_APPLICATION_ERROR(-20009,'Name cannot be updated.'); 
    WHEN CORRECT_NAME 
    THEN DBMS_OUTPUT.PUT_LINE('Updated.'); 
END; 

我想我搞亂了:NEW和:OLD聲明,但我看不到在哪裏。

+0

你檢查過嗎? [Oracle文檔](http://docs.oracle.com/cd/E11882_01/appdev.112/e25519/triggers.htm#LNPLS2005) – SlimsGhost

+0

我已經諮詢了很多文檔,但也許你可以建議我一些頁面應該爲我的代碼做訣竅? – smartsoap

+0

我不明白這裏的商業規則。爲什麼更新觸發器試圖更新自己的表?爲什麼'employee_name'允許爲空?如果要防止更改名稱,那麼只需引發一個異常'if:new.employee_name <>:old.employee_name'。如果名稱允許更改,那麼觸發器是什麼? –

回答

0

第2行表格名稱中存在拼寫錯誤,所以我們將其更改爲EMPLOYEE。

AFTER UPDATE OF EMPLOYEE_NAME ON EMPLOYEE

我會嘗試添加:NEW.EMPLOYEE_NAME之前NOT NULL子句,但我相信,如果它解決所有的問題。

IF(:NEW.EMPLOYEE_NAME <> :OLD.EMPLOYEE_NAME AND :NEW.EMPLOYEE_NAME IS NOT NULL) 
+0

是的,對不起,EMPLYEE是一個錯誤。 另請參見:NEW.EMPLOYEE_NAME IS NOT NULL不工作壽,仍然給我(ORA-04091:表COMPANY.EMPLOYEE變異,觸發器/函數可能看不到它)的錯誤。 – smartsoap

+0

也許這只是不正常的操作順序? – smartsoap

+0

在UPDATE之前放置IF塊是個好主意。這樣無效的名字就不會被分配給員工。而不是'名稱不能更新'。該例外可能會拋出'無效的名稱。沒有更新員工'。 –

0

在觸發器中,您可以像更新一樣執行相同的操作。 因此 - 「應用程序」進行更新(無需提交),然後觸發器進行相同的更新,然後驗證:new.nameold.name

試試這個:

CREATE OR REPLACE TRIGGER NO_INVALID_NAME 
BEFORE UPDATE ON EMPLOYEE 
FOR EACH ROW 
DECLARE 
    INVALID_NAME EXCEPTION; 
    CORRECT_NAME EXCEPTION; 
BEGIN 
    IF :NEW.EMPLOYEE_NAME <> :OLD.EMPLOYEE_NAME AND :NEW.EMPLOYEE_NAME IS NOT NULL THEN 
     RAISE INVALID_NAME; 
    ELSE 
     RAISE CORRECT_NAME; 
    END IF; 
EXCEPTION 
    WHEN NOME_NON_CORRETTO 
     THEN RAISE_APPLICATION_ERROR(-20009,'Name cannot be updated.'); 
    WHEN CORRECT_NAME 
     THEN DBMS_OUTPUT.PUT_LINE('Updated.'); 
END;