首页 文章

java.sql.BatchUpdateException:BEFORE INSERT TRIGGER上的ORA-04091

提问于
浏览
0

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

无法处理“方法”:category_id ='foo'和request_id ='99'错误:java.sql.BatchUpdateException:ORA-04091:表SCHEMA.ANIMAL_TABLE正在变异,触发器/函数可能看不到它ORA-06512:at “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的新手 .

1 回答

  • 0

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

    唯一的解决方法是将新行写入行级触发器的中间表中 . 然后创建一个语句级触发器,它处理已写入中间表的所有行(很可能只有一个带有子选择的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列表中的两列)

相关问题