2011-11-23 69 views
2

我遇到觸發器問題。創建觸發器後,它給我的消息PL/SQL觸發器無法正常工作

BD1.UTILIZADOR是突變,觸發不能讀取或執行

我有這個表

create table UTILIZADOR 
    (
     U_ID     NUMBER(6)   not null, 
     U_NOME    VARCHAR2(60)   not null, 
     U_SEXO    VARCHAR2(10)   not null, 
     U_IDADE    NUMBER(3)   not null, 
     U_ALTURA    NUMBER(3)   not null, 
     U_PESO    NUMBER(6)   not null, 
     U_IMC    NUMBER(2,2), 
     U_PRIVILEGIOS  NUMBER(1)   not null, 
     U_PASSWORD   VARCHAR2(10)   not null, 
     constraint PK_UTILIZADOR primary key (U_ID) 
    ); 

,如果我這樣做:

INSERT INTO UTILIZADOR (U_ID,U_NOME,U_SEXO,U_IDADE,U_ALTURA,U_PESO,U_PRIVILEGIOS,U_PASSWORD) VALUES (1,'my name','Male',32,174,74000,0,'password'); 

然後

SELECT * FROM UTILIZADOR; 

我可以看到一切都如預期。

我想要做什麼,插入或更新U_ALTURA或U_PESO時,字段U_IMC會自動更新/插入。

這裏是如果做了什麼:

CREATE OR REPLACE TRIGGER CALCULA_IMC 
AFTER INSERT OR UPDATE OF U_ALTURA, U_PESO ON UTILIZADOR 
FOR EACH ROW 
BEGIN 
    UPDATE UTILIZADOR 
     SET U_IMC = (U_PESO/1000)/(POWER(U_ALTURA/100,2)); 
END; 
/

有人能告訴我什麼,我做錯了什麼?

回答

3

我假設你要更新的記錄的字段被更新,而不是對整個表:

CREATE OR REPLACE TRIGGER CALCULA_IMC 
AFTER INSERT OR UPDATE OF U_ALTURA, U_PESO ON UTILIZADOR 
FOR EACH ROW 
BEGIN 
    :NEW.U_IMC = (:NEW.U_PESO/1000)/(POWER(:NEW.U_ALTURA/100,2)); 
END; 
/
1

你的觸發器試圖更新一個已經更新的行,考慮一下,在你試圖進行另一次更新的後期更新觸發器中,它將再次觸發觸發器,導致另一個更新,然後觸發觸發器再次......

Oracle不喜歡試圖改變或檢查已經被改變的東西。

嘗試直接在插入/更新語句中設置u_imc。

5

您的觸發器代碼正在更新UTILIZADOR表中的每條記錄,這將包括您的INSERT語句剛剛插入的記錄,我假設您不希望每當您插入新記錄時更新表中的每條記錄。

當你在插入或更新後觸發火災時,它實際上會遞歸地調用它自己,並且你真的不想這樣做。

你需要更多地瞭解觸發器,然後纔能有效地做你想做的事情。

http://docs.oracle.com/cd/B19306_01/appdev.102/b14251/adfns_triggers.htm

http://www.techonthenet.com/oracle/triggers/

這裏是關於變異表一個偉大的文章,並提出一些建議觸發器變圓了這個問題:

http://www.oracle-base.com/articles/9i/MutatingTableExceptions.php

有可能是一個更好的辦法實現您的目標,例如您可以使用BEFORE INSERT OR UPDATE觸發器並將更新分配給:NEW值而不是在您的觸發器主體中發佈新的UPDATE等。

行級別的觸發器無法讀取或寫入從其觸發的表。但是,語句級觸發器可以。

希望它可以幫助...