zoukankan      html  css  js  c++  java
  • 解决ORA04091行触发器中访问变异表的难题


    核心思路就是:在第一次插入时保存值到包变量中,第二次插入时不再读取表本身,转而读取包变量,可以成功解决这类难题。

    在工作中,需要为各个BOM的每个ITEM依次自动编号,不同BOM的ITEM的SEQ_NUMBER列都要 按1.2.3…自动生成序号。
    第一次,我这样写,

    CREATE OR REPLACE TRIGGER TR_BOM_AUTONUMBER_SEQNUMBER
    BEFORE 
    INSERT
    ON BOM 
    REFERENCING NEW 
    AS NEW OLD AS OLD
    FOR EACH ROW
    DECLARE
        tmpVar 
    number;
    BEGIN
        tmpVar :
    = 0;
       
    SELECT GREATEST(nvl(Max(to_number(SEQ_NUMBER)),0), Count(*)) + 1 INTO tmpVar FROM BOM Where BOMID=:New.BOMID;
       :NEW. SEQ_NUMBER:
    = nvl(tmpVar,1);
    END TR_BOM_AUTONUMBER_SEQNUMBER;

    由于Insert操作会修改表数据,所以Insert…Select插入多行数据时,会报ORA-04091: table string.string is mutating, trigger/function may not see it错误,原因在于插入第2条数据时表已修改不能再访问。

    查阅了很多文章,有提示在其中使用 PRAGMA AUTONOMOUS_TRANSACTION来保证每行插入动作为自治事务。但实际上,经过我的测试,虽然DML不会出错,但实际SEQ_NUMBER全部为1,没有达到依次自动编号的目的。

    经过多次试验后,我使用保存于包中的索引表保存各个BOM的最大SEQ_NUMBER,可以防止BOM之间及用户之间的并发冲突。

    核心思路就是:在第一次插入时保存值到包变量中,第二次插入时不再读取表本身,转而读取包变量,可以成功解决这类难题。

    详细代码如下:

    CREATE OR REPLACE PACKAGE BOM_AUTONUMBER
    IS
    TYPE t_MAX_SEQNUMBER 
    is table of number INDEX BY PLS_INTEGER;
    v_MAX_SEQNUMBER t_MAX_SEQNUMBER;
    end BOM_AUTONUMBER;
    /
    CREATE OR REPLACE TRIGGER TR_BOM_AUTONUMBER_SEQNUMBER
    BEFORE 
    INSERT
    ON BOM 
    REFERENCING NEW 
    AS NEW OLD AS OLD
    FOR EACH ROW
    DECLARE
        vNumber 
    number;
        vBOMID 
    number;
    BEGIN
        vNumber:
    = 0;
        vBOMID:
    = :New.BOMID;
        
    if not BOM_AUTONUMBER.v_MAX_SEQNUMBER.EXISTS(vBOMID) then
            
    SELECT GREATEST(nvl(Max(to_number(SEQ_NUMBER)),0), Count(*)) INTO vNumber FROM BOM Where ITEM = vBOMID;
            BOM_AUTONUMBER.v_MAX_SEQNUMBER(vBOMID) :
    = nvl(vNumber, 0);
        
    end if;
        BOM_AUTONUMBER.v_MAX_SEQNUMBER(vBOMID) :
    = BOM_AUTONUMBER.v_MAX_SEQNUMBER(vBOMID) + 1;
       :NEW.SEQ_NUMBER :
    = BOM_AUTONUMBER.v_MAX_SEQNUMBER(vBOMID);
    END TR_BOM_ AUTONUMBER_SEQNUMBER;
    /


    专注数据库技术,学以致用。
  • 相关阅读:
    子类调用父类被重写的方法
    Linux下编译出现undefined reference to ‘pthread_create’问题解决
    CRC校验8
    嵌入式C语言查表法
    Static关键字,遇到的问题_1
    java中方法的参数传递机制_一个对象被当作参数传递到一个方法后
    String使用equals和==比较的区别
    如何导入XML数据 (python3.6.6区别于python2 环境)
    0xx_PHP核心01
    PHP_MVC设计模式02
  • 原文地址:https://www.cnblogs.com/drc/p/1183456.html
Copyright © 2011-2022 走看看