【问题标题】:pl sql error when working with trigger使用触发器时出现pl sql错误
【发布时间】:2016-04-22 16:05:00
【问题描述】:

使用以下触发器时出现错误:

create or replace trigger t1
  after insert or update  
     on student_tbl 
  declare
   pragma autonomous_transaction;
    begin
   if inserting then

 insert into stud_fees_details(stud_id,fees_balance,total_fees) 
       select stud_id,course_fees,course_fees from student_tbl s,courses_tbl c where s.stud_standard_id=c.course_id;

 elsif updating('stud_standard_id') then

insert into stud_fees_details(stud_id,fees_balance,total_fees) 
select stud_id,course_fees,course_fees from student_tbl s,courses_tbl c where s.stud_standard_id=c.course_id;

 end if;
end;

错误是

ORA-06519: 检测到活动的自主事务并回滚 ORA-06512:在“SYSTEM.T1”,第 15 行 ORA-04088: 执行触发器 'SYSTEM.T1' 期间出错

【问题讨论】:

  • 删除了 Sql server 和 Mysql 标签,因为错误消息明确指出它是 ORACLE
  • 您是否尝试在搜索引擎上搜索错误消息“检测到并回滚活动的自主事务”?我的第一击似乎以非常详细的方式解释了它。
  • 有 oracle Database Error Messages 手册解释了为什么会出现这个错误以及如何避免它。
  • 首先在触发器中使用自治事务听起来是个坏主意。您试图解决的真正问题是什么?
  • 这似乎是所谓的XY-problem:您引入了自治事务,因为您遇到了另一个问题。现在您询问的是自主事务错误而不是您原来的问题。除此之外,在 SYSTEM 模式中创建对象是一个坏主意。您应该为此创建一个用户/模式。

标签: oracle plsql oracle11g database-trigger


【解决方案1】:

如果触发器不使用:new 或:old,则它是可疑的。您的触发器正在使用查询中正在修改的同一个表。

你可能打算:

create or replace trigger t1 after insert or update on student_tbl 
declare
   pragma autonomous_transaction;
begin
    if inserting then
        insert into stud_fees_details(stud_id, fees_balance, total_fees) 
            select stud_id, course_fees, course_fees
            from courses_tbl c
            where c.course_id = :new.stud_standard_id;

    elsif updating('stud_standard_id') then
        insert into stud_fees_details(stud_id, fees_balance, total_fees) 
            select stud_id, course_fees, course_fees
            from courses_tbl c
            where c.course_id = :new.stud_standard_id;
    end if;
    commit;
end;

注意事项:

  • select 语句应具有表别名,以区分来自:new 和courses_tbl 的列。
  • if 的两个子句在我看来是一样的,所以我不明白其中的逻辑。
  • join 介于 course_id 和 stud_standard_id 之间的条件看起来很可疑。我建议您在它们引用的主键之后命名外键。

【讨论】:

  • 此答案中的任何内容都无法解决问题。您的触发器也会引发同样的错误。
  • @miracle173 。 . .此代码应防止变异表错误,这可能是失败的原因。此代码不再引用正在修改的表。为什么你认为这不能解决问题?
  • 因为问题是既不提交也不回滚的自治事务
  • @miracle173 - 我敢打赌,编译指示只是首先放在那里,以避免发生变异表错误,这只是因为对表进行了不必要的查询。我不相信这个版本不再需要那个编译指示,或者因此提交;但它确实需要是for each row 触发器才能引用:new。 (它也不需要分支,因为两者都做同样的事情,但这完全是另一个问题。
  • @AlexPoole 在我的回答中,我推测自治事务也是不必要的。然而,此错误消息的原因是未正确完成的自治事务..
【解决方案2】:

Database Error Messages

ORA-06519:检测到活动的自治事务并回滚
原因:在从自治 PL/SQL 块返回之前,所有自治事务都在该块内启动必须完成(提交或回滚)。如果不是,则活动的自治事务被隐式回滚并引发此错误。
操作:确保在从自治 PL/SQL 块返回之前,任何活动的自治事务都被显式提交或回滚返回。

来自Database PL/SQL Language Reference的示例

-- Autonomous trigger on emp table:

CREATE OR REPLACE TRIGGER log_sal
  BEFORE UPDATE OF salary ON emp FOR EACH ROW
DECLARE
  PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
  INSERT INTO log (
    log_id,
    up_date,
    new_sal,
    old_sal
  )
  VALUES (
    :old.employee_id,
    SYSDATE,
    :new.salary,
    :old.salary
  );
  COMMIT;
END;
/

但是@a_horse_with_no_name 已经说过,自治事务可能在这里不合适。

删除自治事务编译指示后,您可能会遇到@GordonLinoff 使用his post 解决的问题。

【讨论】:

    猜你喜欢
    • 2023-03-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-07
    • 2021-12-27
    • 1970-01-01
    • 2017-12-15
    • 2020-11-05
    相关资源
    最近更新 更多