2016-06-23 28 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'块中。 –