【问题标题】:java.sql.BatchUpdateException: ORA-04091 on BEFORE INSERT TRIGGERjava.sql.BatchUpdateException:在插入触发器之前出现 ORA-04091
【发布时间】:2011-11-18 19:32:51
【问题描述】:

我在 BEFORE INSERT TRIGGER 上遇到了一个奇怪的错误,我无法理解。即使在阅读了此处发布的多个具有类似问题的问题之后。

未能处理“方法”:category_id = 'foo' 和 request_id = '99' 错误:java.sql.BatchUpdateException:ORA-04091:表 SCHEMA.ANIMAL_TABLE 正在变异,触发器/函数可能看不到它 ORA-06512:在 “SCHEMA.TRIGGER_NAME”,第 7 行 ORA-04088:执行期间出错 触发“SCHEMA.TRIGGER_NAME”

这里是触发器:

CREATE OR REPLACE TRIGGER TRIGGER_NAME 
BEFORE INSERT ON animal_table FOR EACH ROW WHEN (NEW.animal_type = 'cats')

DECLARE    base_animal_id NUMBER(19,0);   base_amount NUMBER(19,0);

BEGIN

SELECT animal_nbr INTO base_animal_id 
FROM animal_table 
WHERE category_id = :NEW.category_id AND summary_id = :NEW.summary_id 
AND animal_type = 'special'; 

SELECT animal_amount INTO base_amount 
FROM animal_table 
WHERE category_id = :NEW.category_id AND summary_id = :NEW.summary_id 
AND animal_type = 'special';


IF :NEW.category_id = 'foo' THEN

  :NEW.animal_info1 := base_animal_id;   
  :NEW.animal_info2 := base_amount;   
  :NEW.animal_info3 := '00';

END IF;

END;

我知道有关在持有触发器的同一个表上进行修改的规则,但我也红色了一些在更改新列时它应该起作用的东西,并且仅适用于 :NEW 字段。我还认为它可能缺少 UPDATE 作为触发事件,但事实并非如此。任何人都可以帮助我吗?因为我是触发器和 PL/SQL 的新手。

【问题讨论】:

  • 谢谢你,Lukas...我正要这样做。

标签: oracle triggers ora-04091


【解决方案1】:

错误信息与更新表无关。您不能从 ROW 级别 触发器中当前正在更改的表中SELECT

解决此问题的唯一方法是将新行写入行级触发器中的中间表。然后创建一个 statement 级别的触发器来处理已写入中间表的所有行(很可能只有一个带有子选择的 UPDATE 语句)。

如果您可以在语句级触发器中识别要后处理的行,例如,您可能会在没有行级触发器和中间表的情况下侥幸逃脱。通过检查 animal_type = 'cats' 和 category_id = 'foo'。

如果是这种情况,以下触发器(未经测试!!!)可能会执行您想要的操作(而不是您拥有的触发器)

CREATE OR REPLACE TRIGGER TRIGGER_NAME 
AFTER INSERT ON animal_table 
BEGIN

  UPDATE animal_table
     SET (animal_info1, 
          animal_info2, 
          animal_info3) = (SELECT animal_nbr, animal_amount, '00'
                           FROM animal_table t2
                           WHERE t2.category_id = animal_table.category_id
                             AND t2.sumary_id = animal_table.summary_id
                             AND t2.animal_type = 'special'
                          )
  WHERE animal_type = 'cats'
    AND category_id = 'foo'

END;

另一个更通用的 PL/SQL 事情:您不需要为要检索的每一列运行一个 SELECT,如果条件相同,您可以在单个 select 语句中执行此操作:

SELECT animal_nbr, animal_amount
    INTO base_animal_id, base_amount 
FROM animal_table 
WHERE category_id = :NEW.category_id 
  AND summary_id = :NEW.summary_id 
  AND animal_type = 'special';

(注意 select 和 into 列表中的两列)

【讨论】:

  • 不错的答案...我添加了一项。
猜你喜欢
  • 2020-02-21
  • 1970-01-01
  • 2013-05-13
  • 2010-12-09
  • 2017-12-15
  • 1970-01-01
  • 2018-11-30
  • 1970-01-01
  • 2011-05-21
相关资源
最近更新 更多