2016-06-23 27 views
0

我創建了以下觸發,但我在做新的插入/更新後所提到的表是不是被解僱:如何創建在表中完成任何插入或更新時觸發的觸發器?

CREATE OR REPLACE TRIGGER ref_upd_user_phi_details 
AFTER 
INSERT OR UPDATE --of emp_email_address, ssn_nb 
ON ref_adp_employees 
REFERENCING OLD AS OLD NEW AS NEW 
FOR EACH ROW 
BEGIN 
     UPDATE ref_adp_employees 
     SET emp_email_address = 'QA_' ||emp_email_address, 
      ssn_nb = nvl2(ssn_nb, NULL, '123-45-6789') 
     WHERE upper(emp_email_address) NOT LIKE 'QA_%' 
     AND upper(emp_email_address) LIKE '%@KEENAN.COM'; 
exception 
     WHEN others 
      THEN 
       NULL; 
END; 

可有人請建議我我缺少什麼?

+1

你爲什麼捕捉到WHEN OTHERS異常,並且對此無能爲力。暫時刪除您的異常部分,並重新編譯觸發器。做一個插入/更新,看看它是否拋出任何錯誤。 –

+0

此外,您的更新語句似乎是一個靜態更新。您沒有在觸發器中新創建或更新的記錄中使用任何值。你試圖通過這個觸發器達到什麼目的? –

+0

@phonetic_man:在刪除異常部分後,讓我檢查您要求我做的第一個條件。我想在插入任何新記錄或任何現有記錄更新時觸發此觸發器。 –

回答

0

您是否聽說過Google?有很多答案和例子可以觸發,但是我現在看到的一些事情:

1)將觸發器更改爲BEFORE插入或更新。在更改另一個表格時使用AFTER,或者在表格上運行一些後續處理。

2)取出註釋到被更改或添加的單個字段。這是很好的AFAIK。

3)在觸發器的使用中,使用何時插入以及何時更新。或者,如果您只更新表格,則僅將DDL更改爲BEFORE UPDATE。

4)在更新中,引用set:new.emp_email_address ='QA_'|| :old.emp_email_address ...等等等等。這就是新舊一樣重要的地方。

+0

將與第4點 –

+0

我試圖嘗試:創建或替換TRIGGER ref_upd_user_phi_details BEFORE 插入或更新--oF emp_email_address,ssn_nb ON ref_adp_employees REFERENCING舊如舊新AS新 FOR EACH ROW BEGIN UPDATE HR。 ref_adp_employees SET:new.emp_email_address ='QA_'||:old.emp_email_address, :new.ssn_nb = nvl2(:old.ssn_nb,NULL,'123-45-6789') WHERE upper(:old.emp_email_address) NOT LIKE'QA_%' AND upper(:old.emp_email_address)LIKE'%@KEENAN.COM'; --exception - WHEN others - THEN - NULL; END; –

0

更新

CREATE OR REPLACE TRIGGER ref_upd_user_phi_details 
Before 
INSERT OR UPDATE 
+0

感謝您分享查詢。此外,如果你可以建議我缺少創建上述觸發器。 –

1

前請檢查是否觸發是否有效通過焙燒下面的查詢..

SELECT * 
FROM ALL_OBJECTS 
WHERE OBJECT_NAME = trigger_name 
AND OBJECT_TYPE = 'TRIGGER' 
AND STATUS <> 'VALID' 

的觸發更新後燒製.. 嘗試作爲@phonetic_man指出出門,你隱藏任何錯誤,你抓住when others並採取任何行動。沒有異常塊,你會看到你正在引起一個變異表錯誤(ORA-04091),因爲你指的是觸發器所針對的同一個表。

如果您拿出for each row部分將其轉換爲語句級觸發器,那麼您將避免該問題,但現在您將有一個無限循環(ORA-00036) - 當您嘗試從內部更新表觸發器,更新本身會導致同一觸發器再次觸發;它試圖再次更新同一個表,這會導致觸發器再次觸發;等到Oracle發現並殺死進程。

使用before-insert行級別觸發器來確保行的新值與您嘗試強制執行的任何模式相匹配會更有意義。也許是這樣的:

CREATE OR REPLACE TRIGGER ref_upd_user_phi_details 
BEFORE INSERT OR UPDATE --of emp_email_address, ssn_nb 
ON ref_adp_employees 
REFERENCING OLD AS OLD NEW AS NEW 
FOR EACH ROW 
BEGIN 
    IF upper(:NEW.emp_email_address) NOT LIKE 'QA_%' 
     AND upper(:NEW.emp_email_address) LIKE '%@KEENAN.COM' 
    THEN 
     :NEW.emp_email_address := 'QA_' || :NEW.emp_email_address; 
     :NEW.ssn_nb := CASE WHEN :NEW.ssn_nb IS NULL THEN '123-45-6789' END; 
    END IF; 
END; 
/

而要看看它做什麼:

insert into ref_adp_employees (emp_id, emp_email_address, ssn_nb) values (1, 'TEST_1', '123-45-6789'); 
insert into ref_adp_employees (emp_id, emp_email_address, ssn_nb) values (2, '[email protected]', '123-45-9876'); 
insert into ref_adp_employees (emp_id, emp_email_address, ssn_nb) values (3, 'QA_TEST_1', null); 

select emp_id, emp_email_address, ssn_nb from ref_adp_employees; 

    EMP_ID EMP_EMAIL_ADDRESS    SSN_NB  
---------- ------------------------------ ----------- 
     1 TEST_1       123-45-6789 
     2 [email protected]      
     3 QA_TEST_1         

不知道,如果你真的打算用NULL替換集核潛艇,並把空到固定值;我懷疑你是真的想取代固定字符串設定值,獨自離開零點,在這種情況下,這將是:

 :NEW.ssn_nb := CASE WHEN :NEW.ssn_nb IS NOT NULL THEN '123-45-6789' END; 

您可能還需要動議IF外塊,所以不管它的完成電子郵件地址;我已經複製了你原來的代碼試圖做的事情,但這可能是不對的。

如果您想要修改現有數據以匹配這些更改,請對整個表執行一次性更新 - 請勿嘗試在觸發器內執行此操作。

+0

這是工作的罰款現在:CREATE OR REPLACE TRIGGER ref_upd_user_phi_details BEFORE INSERT或emp_email_address的UPDATE,ssn_nb ON ref_adp_employees REFERENCING舊如舊新AS NEW FOR EACH ROW BEGIN IF上(:NEW.emp_email_address)NOT LIKE 'QA_%' AND upper(:NEW.emp_email_address)LIKE'%@KEENAN.COM' THEN :NEW.emp_email_address:='QA_'|| :NEW.emp_email_address; :NEW.ssn_nb:= CASE WHEN:NEW.ssn_nb IS NOT NULL THEN'123-45-6789'END; END IF; :NEW.ssn_nb:= CASE WHEN:NEW.ssn_nb IS NOT NULL THEN'123-45-6789'END; END; –

+0

@Oracle_UNIX_aspirant - 這對其他人來說並不會有幫助,而且很難將代碼讀取(或查看其相關性)作爲評論。您似乎已將'ssn_nb'更改再次應用於所有更新/插入;你也不需要它在'IF'塊中。 –