ORACLE变异触发错误

时间:2012-08-23 10:36:21

标签: oracle triggers

  

可能重复:
  ORACLE After update trigger: solving ORA-04091 mutating table error

所以我有一个触发器来检查一个管理员是否已被锁定登录(如果他们是1将设置为temp_pw。然后它会向管理员发送一个四位数的密码以解锁他们的帐户。问题是我更新了failed_logins字段,在调用触发器之前,每次失败的登录都将其递增1。

触发器的其余部分会在向管理员发送带有密码的电子邮件之前检查是否有管理员拥有锁定帐户。

如果我拿出更新Pi_admin_table设置blah blah ,它会发送电子邮件,但如果我将其包含在表格中插入新密码,则会出错:

 Message: 60 ORA-00060: deadlock detected while waiting for resource
 ORA-06512: at "PI_USER_ADMIN.TR_ADMIN_LOCKOUT", line 17
 ORA-04088: error during execution of trigger
 'PI_USER_ADMIN.TR_ADMIN_LOCKOUT' UPDATE *pi_admin_table SET
 failed_logins = failed_logins + 1 where
 EMAIL='nathan@perceptive.co.uk' returning failed_logins into :bind_var

这是我的触发器:

create or replace
TRIGGER "TR_ADMIN_LOCKOUT" 
AFTER UPDATE ON PI_ADMIN_TABLE
for each row
declare
-- pragma autonomous_transaction seems to fix trigger mutation errors. 
-- Look at rewriting trigger later.
--pragma autonomous_transaction;
tempEmail varchar2(80 BYTE);
tempID varchar2(80 BYTE);
mail_host varchar2(255);
mail_port varchar2(255);
mail_from varchar2(255);
tempPW int;
begin
  SELECT EMAIL, ADMINID
    into tempEmail, tempID
    from pi_admin_table
    where TEMP_PW = :NEW.TEMP_PW;

  SELECT MAIL_HOST, MAIL_PORT, MAIL_FROM
    into mail_host, mail_port, mail_from
    from pi_settings_table;

  select dbms_random.value(1,10000)
    into tempPW
    from dual;

  if tempEmail IS NOT NULL then
    UPDATE PI_ADMIN_TABLE SET RESET_PW=round(tempPW) where adminid=tempID;
    send_mail(tempEmail,
              mail_host,
              mail_port,
              mail_from,
              'Locked Out Event',
              'Your administrator account was locked out. '|| chr(10) || chr(10) ||
              'Please use this four digit pass code next time try to log in' ||
              chr(10) || chr(10) ||  
              'Temp pass code: '|| round(tempPW) );
  end if;
END;

2 个答案:

答案 0 :(得分:2)

Oracle不允许ROW触发器中的代码针对定义了触发器的表发出SELECT,INSERT,UPDATE或DELETE。您的选择是使用自主交易(但请参阅the post referenced in @Ben's comment above处的警告)或使用复合触发器。

分享并享受。

答案 1 :(得分:2)

我建议您不要使用触发器执行该任务。封装您在存储过程中尝试实现的逻辑。