同一个表上的触发器不会在插入之前更新列值

时间:2018-02-27 08:58:08

标签: sql oracle database-trigger

以下是通过将EMP_ID与某些文字合并来生成EMP_KEY的值所使用的触发器,假设为EMP_KEY =2000TYPE_ID=1,具体取决于条件,EMP_ID的值应为CON2000,依此类推。 但是,当插入记录时,EMP_ID的值仅生成' CON' 当记录更新时,它的工作正常,即EMP_ID=CON2000

在这种情况下,EMP_KEY是自动生成的字段及其NOT NULL

我犯了什么错误?有人可以帮忙吗? 我使用AFTER并使用引用OLD作为旧的和NEW作为新的,但没有运气。

CREATE OR REPLACE TRIGGER EMP_ID_TRIGG BEFORE
INSERT OR UPDATE ON EMP 
FOR EACH ROW 
BEGIN 
IF :NEW.TYPE_ID = 1 THEN :NEW.EMP_ID := CONCAT('CON', :NEW.EMP_KEY);
ELSIF :NEW.TYPE_ID = 2 THEN :NEW.EMP_ID := CONCAT('SUBCON', 
:NEW.EMP_KEY);
ELSIF :NEW.TYPE_ID = 3 THEN :NEW.EMP_ID := CONCAT('JV', :NEW.EMP_KEY);
ELSE :NEW.EMP_ID := :NEW.EMP_KEY;
END IF;
END;

1 个答案:

答案 0 :(得分:3)

听起来你在桌面上有两个触发器,一个用于生成密钥(可能来自一个序列),然后是你已经显示使用该密钥值生成ID的一个触发器。简单的演示:

create table emp (emp_key number primary key,
  type_id number,
  emp_id varchar2(20),
  emp_name varchar2(20)
);

create sequence emp_key_seq;

create or replace trigger emp_key_trigg
before insert on emp
for each row 
begin 
  :new.emp_key := emp_key_seq.nextval;
end;
/

create or replace trigger emp_id_trigg
before insert or update on emp 
for each row 
begin 
  if :new.type_id = 1 then
    :new.emp_id := concat('CON', :new.emp_key);
  elsif :new.type_id = 2 then
    :new.emp_id := concat('SUBCON', :new.emp_key);
  elsif :new.type_id = 3 then
    :new.emp_id := concat('JV', :new.emp_key);
  else
    :new.emp_id := :new.emp_key;
  end if;
end;
/

然后插入和更新你所描述的内容:

insert into emp (type_id, emp_name) values (1, 'Jane');
insert into emp (type_id, emp_name) values (2, 'Joe');

select * from emp;

   EMP_KEY    TYPE_ID EMP_ID               EMP_NAME            
---------- ---------- -------------------- --------------------
         1          1 CON                  Jane                
         2          2 SUBCON               Joe                 

update emp set emp_name = 'Jen' where emp_name = 'Jane';

select * from emp;

   EMP_KEY    TYPE_ID EMP_ID               EMP_NAME            
---------- ---------- -------------------- --------------------
         1          1 CON1                 Jen                 
         2          2 SUBCON               Joe                 

From 11g您可以使用相同的时间点触发with the FOLLOWS clause来控制触发的顺序,因此在这种情况下,广告follow emp_key_trigg(当然还有您实际触发器的名称):

create or replace trigger emp_id_trigg
before insert or update on emp 
for each row
follows emp_key_trigg
begin 
  if :new.type_id = 1 then
    :new.emp_id := concat('CON', :new.emp_key);
  elsif :new.type_id = 2 then
    :new.emp_id := concat('SUBCON', :new.emp_key);
  elsif :new.type_id = 3 then
    :new.emp_id := concat('JV', :new.emp_key);
  else
    :new.emp_id := :new.emp_key;
  end if;
end;
/

insert into emp (type_id, emp_name) values (1, 'Jane');
insert into emp (type_id, emp_name) values (2, 'Joe');

select * from emp;

   EMP_KEY    TYPE_ID EMP_ID               EMP_NAME            
---------- ---------- -------------------- --------------------
         3          1 CON3                 Jane                
         4          2 SUBCON4              Joe                 

您还可以将两个触发器合并为一个(无论如何,您必须在早期版本中进行操作,如triggers of the same type for the same statement are not guaranteed to fire in any specific order):

-- don't do this unless you're sure it's what you have to do!
drop trigger emp_key_trigg;

create or replace trigger emp_id_trigg
before insert or update on emp 
for each row 
begin 
  if inserting then
    :new.emp_key := emp_key_seq.nextval;
  end if;

  if :new.type_id = 1 then
    :new.emp_id := concat('CON', :new.emp_key);
  elsif :new.type_id = 2 then
    :new.emp_id := concat('SUBCON', :new.emp_key);
  elsif :new.type_id = 3 then
    :new.emp_id := concat('JV', :new.emp_key);
  else
    :new.emp_id := :new.emp_key;
  end if;
end;
/

insert into emp (type_id, emp_name) values (1, 'Jane');
insert into emp (type_id, emp_name) values (2, 'Joe');

select * from emp;

   EMP_KEY    TYPE_ID EMP_ID               EMP_NAME            
---------- ---------- -------------------- --------------------
         5          1 CON5                 Jane                
         6          2 SUBCON6              Joe