oracle 在执行触发器时出错的装置,EMPLOYEE_AUDIT_TRIGGER,完整性约束

idv4meu8  于 2023-05-16  发布在  Oracle
关注(0)|答案(2)|浏览(155)

我正在尝试运行这个触发器,它应该在每次修改Employee表时记录一个事务。
这是扳机

CREATE OR REPLACE TRIGGER EMPLOYEE_AUDIT_TRIGGER
BEFORE INSERT OR DELETE OR UPDATE ON EMPLOYEE
FOR EACH ROW
BEGIN
  INSERT INTO TRANSACTIONS (TRANSACTION_TIMESTAMP, USERNAME, EMP_ID, POSITION_TYPE)
  VALUES (SYSTIMESTAMP, GET_USERNAME(), :NEW.EMP_ID, 'HR');
END;

get_username函数只是我定义的一个普通函数,它返回当前用户的用户名。没有触发器,我可以在Employee表中输入employee而不会出现任何错误,所以这绝对不是一个错误,只是触发器出了问题
触发器应该记录一个事务
然而,我一直在犯这个错误:

ORA-02291: integrity constraint (xxxx.SYS_xxxxx) violated - parent key
not found
ORA-06512: at "xxxxx.EMPLOYEE_AUDIT_TRIGGER", line 2
ORA-04088: error during execution of trigger 'xxxxx.EMPLOYEE_AUDIT_TRIGGER'
jchrr9hc

jchrr9hc1#

Oracle说你正在尝试插入一个在父表中不存在的值。
parent 表通过外键约束从transactions表引用。

  • transaction_timestamp可以
  • username:为什么不使用内置的user函数?
  • emp_id:似乎可以; pseudorecord是这么说的。注意 oldnew 值(当您删除行时,new不存在,因此可能需要使用coalesce(:new.emp_id, :old.emp_id)
  • position_type:什么是HR?那列上有外键吗?是否存在于父表中?
czq61nw1

czq61nw12#

您有transactions表,其中包含DDL:

EMP_ID NUMBER(3) REFERENCES EMPLOYEE(EMP_ID)

你的触发点是

CREATE OR REPLACE TRIGGER EMPLOYEE_AUDIT_TRIGGER
BEFORE INSERT OR DELETE OR UPDATE ON EMPLOYEE
FOR EACH ROW
BEGIN
  INSERT INTO TRANSACTIONS (TRANSACTION_TIMESTAMP, USERNAME, EMP_ID, POSITION_TYPE)
  VALUES (SYSTIMESTAMP, GET_USERNAME(), :NEW.EMP_ID, 'HR');
END;

有三个问题:
1.它是一个BEFORE INSERT触发器,因此您试图在EMP_ID存在于employee表中之前将其插入transactions表中,并且将没有行供引用约束引用(尚未)。您可以通过将触发器更改为AFTER INSERT或推迟约束的计算来解决这个问题,但这不会解决下一个问题。
1.它将在DELETE上触发,在这种情况下,包含EMP_ID的行将从employee表中删除,这将失败,因为transactions表中有一个引用约束,要求父键存在。
1.从employee表中删除行时,:NEW.EMP_ID将是NULL
要修复它,您需要:

  • 删除transactions.emp_id上的FOREIGN KEY约束,因为您仍然希望事务在删除员工后仍然存在,并且约束是不必要的(并且是导致错误的原因)。
  • 在触发器的INSERT中将:NEW.EMP_ID更改为COALESCE(:NEW.EMP_ID, :OLD.EMP_ID)
  • 注意:如果可以从LOGINPOSITIONS表中删除行,那么您可能希望从transactions表中删除所有外键,因为这些列可能会出现类似的问题。

相关问题