改成after
如果是在不行可以考虑使用临时表+表级触发器

解决方案 »

  1.   

    owner 问题?你讲的不清楚,详细点
      

  2.   

    to bzszp(SongZip): 改成after也不行!
    错误信息如下:
    ---------------------------
    Error
    ---------------------------
    ORA-04091: 表 PROJECT.GC_PHASE 发生了变化,触发器/函数不能读
    ORA-06512: 在"PROJECT.TRI_PROGRESS", line 15
    ORA-04088: 触发器 'PROJECT.TRI_PROGRESS' 执行过程中出错
    View program sources of error stack?
    ---------------------------
    是(Y)   否(N)   
    ---------------------------
    出错语句:
    select sum(downpercent*downworkload) into intitemprogress from gc_phase where itemcode='LS20040112030K';
    不知leborety(那只螃蟹) 所说的owner问题是什么意思??
      

  3.   

    我去掉逐行触发在应用的时候出现“NEW或OLD引用不允许在表层触发器中”的错误
      

  4.   

    触发器可以包括任何合法的PL/sQL语句,假有以下例外
    1.触发器不可以执行COMMIT、ROLLBACK或SAVEPOINT语句,而且不可以调用执行这些语句之一的函数或过程。
    2.触发器不可以声明long或LONG RAW变量。
    3.触发器不可以在定义它的表上执行DML操作。
      

  5.   

    to bzszp(SongZip) :能把你所说的临时表+表级触发器说得详细点吗??
      

  6.   

    用:old和;new就可以了,
    create table gc_phase_temp as select * from gc_phase where 某字段名=随便一个现在没有的值
    这就建了一个空的临时表了,和gc_phase一模一样的,就是没有相应的索引对表gc_phase做行级触发,目的是把新的值insert到gc_phase_temp,用insert into gc_phase_temp
    valuse(:new.字段1,:new.字段2....)
      

  7.   

    大体思路,创建一个包用来存放需要处理的数据行,创建一个行级触发器t1,一个语句级触发器t2
    t1用来将处理的数据行存到包中变量中,t2用来执行对表的操作:
    eg:
    select sum(downpercent*downworkload) into intitemprogress from gc_phase where itemcode='LS20040112030K';
      

  8.   

    参考:
    http://community.csdn.net/Expert/topic/3420/3420871.xml?temp=.7411463
      

  9.   

    to wylwyl1130(落雪山林):听你的思路好像可行,能否给写个包,简单点也行,我没写过包!!
      

  10.   

    to bzszp(SongZip) :
    下边创建临时表的语句要写在触发器中吗?如果写在触发器中每次触发器被触发的时候都要建一次名为Tmp的临时表,这样会不会出问题呢?
    11:04:36 SQL> CREATE GLOBAL TEMPORARY TABLE Tmp(
    11:04:39   2  rid varchar2(20))ON COMMIT DELETE ROWS;
      

  11.   

    不是在触发器中执行
    在sql*plus里面创建一次就可以了
    当commit时自动晴空临时表中的数据。
      

  12.   

    CREATE OR REPLACE PACKAGE Studentdata AS
    TYPE t_Majors IS TABLE OF students.major%TYPE
    INDEX BY BINARY_INTEGER;
    TYPE t_IDS IS TABLE OF students.ID%TYPE
    INDEX BY BINARY_INTEGER;V_studentsmajors t_majors;
    V_studentsIDs t_Ids;
    V_numEntries BINARY_INTEGER :=0;
    END Studentdata;CREATE OR REPLACE TRIGGER RlimitMajors
    BEFORE INSERT OR UPDATE OF major ON students FOR EACH ROW
    BEGIN
    Studentdata.v_numEntries := studentsdata.v_numEntries + 1;
    Studentdata.v-studentMajors(studentdata.v_numEntries) := :new.major;
    Studentdata.v_studentIDs (studentdata.v_numEntries) := :new.id;
    END RlimitMajors;CREATE OR REPLACE TRIGGER SlimitMajors
    BEFORE INSERT OR UPDATE OF major ON students
    BEGIN
    v_MaxStudents CONSTANT NUMBER := 5;
    v_CurrentStudents  NUMBER;v_studentID students.ID%TYPE;
    v_Major student.major%TYPE;BEGIN
    FOR v_loopindex  IN  1 .. studentdata.V_numEntries  loop 
    v_studentID := studentdata.v_stidentIDs(v_loopindex);
    v_major := studentdata.v_studentmajors(v_loopindex);SELECT count(*) INTO v_currentstudents FROM students
    WHERE major = v_major;IF v_currentstudents > v_maxstudents  THEN
    RAISE_APPLICATION_ERROR(-20000,'Too many students for major '||v_major||
    'because of student '|| v_studentID);
    END IF;
    END LOOP;END SlimitMajors;
      

  13.   

    高手啊,bzszp(SongZip)
    http://community.csdn.net/Expert/topic/3420/3420871.xml?temp=.7411463
    该贴提供的方法应能够解决你的问题了,佩服,向高手学习
      

  14.   

    to bzszp(SongZip):你的意思是说把两个触发器都写在A表上吗?可是我不光是要往临时表中插入修改的那条记录,还要从A表中查出其他部分记录插入到临时表中,以便select sum(downpercent*downworkload) into intitemprogress from Tmp where itemcode='LS20040112030K';
    能汇总出满足条件的数据来!这样我不是还要读取A表,出现老问题了吗!!
      

  15.   

    首先你要确定,
    这里的downpercent,downworkload的值是你更新前还是更新后的值,应,'LS20040112030K'有可能是你要更新的那一条记录的,
    是吗?临时表的设计可以按你的需求要做,应可以的,
      

  16.   

    --创建临时表
    CREATE GLOBAL TEMPORARY TABLE gc_phase_temp
    (
    fvaritemcode varchar2(20)
    )ON COMMIT DELETE ROWS;--创建行级触发器,目的是保存varitemcode,
    CREATE OR REPLACE TRIGGER "TRI_PROGRESS" after
    UPDATE
    OR DELETE ON "GC_PHASE" FOR EACH ROW 
    declare begininsert into gc_phase_temp values (:old.itemcode);end;--创建语句表触发器,也称表级触发器,主要的逻辑在这里
    CREATE OR REPLACE TRIGGER "TRI_PROGRESS2" after
    UPDATE
    OR DELETE ON "GC_PHASE" 
    declare 
    varitemcode varchar2(20);
    introws number;
    intitemprogress int;
    varparentcode varchar(20);
    beginselect fvaritemcode into varitemcode from gc_phase_temp;--varitemcode:=:old.itemcode;
    --是否末级项目,如果有子项目,不计算
    select count(*) into introws from gc_item_child where parentcode=varitemcode;
    if(introws>0) then
      return;
    end if;
    --计算本级项目的进度--select sum(downpercent*downworkload) into intitemprogress from gc_phase where itemcode=varitemcode;
    select sum(downpercent*downworkload) into intitemprogress from gc_phase where itemcode='LS20040112030K';
    procselect(intitemprogress);-- from gc_phase;
    if(intitemprogress < 1) then 
      intitemprogress:=0.000;
    end if;
    update gc_item_date set progress=intitemprogress where itemcode=varitemcode;
    select parentcode into varparentcode from gc_item_date where itemcode=varitemcode;
    --计算上级项目的进度
    gc_calProgress(varparentcode);
    end;--如果你的gc_calprogress里没有用到:new,:old的值的话,这样应该就可以了.