線上訂房服務-台灣趴趴狗聯合訂房中心
發文 回覆 瀏覽次數:2133
推到 Plurk!
推到 Facebook!

請問觸發器與函數不能讀的錯誤訊息

尚未結案
zzmbeyond01
中階會員


發表:98
回覆:167
積分:53
註冊:2003-09-07

發送簡訊給我
#1 引用回覆 回覆 發表時間:2004-12-15 22:39:54 IP:222.183.xxx.xxx 未訂閱
触发器/函数不能读的错误 错误吗如下:请问怎么解决啊!! --------------------------- Error --------------------------- ORA-04091: 表 STUDY.FD 发生了变化,触发器/函数不能读 ORA-06512: 在"STUDY.FD_INSERT_UPDATE_TRG", line 29 ORA-04088: 触发器 'STUDY.FD_INSERT_UPDATE_TRG' 执行过程中出错 View program sources of error stack? --------------------------- 是(Y) 否(N) ---------------------------
    ;触发器代码
CREATE OR REPLACE TRIGGER  FD_Insert_Update_Trg
BEFORE INSERT OR UPDATE ON  FD 
For EACH ROW
declare
  CURSOR C_ZL(p_zlh zlgk.zlh03%type) IS SELECT t.dm,t.dw,t.zlh01,t.zlh02,t.zlh03,t.zdb001,t.zdb002  FROM ZL t WHERE t.zlh03=p_zlh;
  V_ZL C_ZL%ROWTYPE;
begin    IF UPDATING THEN
  --如果坐落号或栋号发生变化
    IF (:old.zlh03<>:new.zlh03) or (:old.dh02<>:new.dh02)  THEN
       OPEN C_ZL(:new.zlh03);
       FETCH C_ZL INTO V_ZL;  
       IF C_ZL%FOUND THEN
          UPDATE FD SET                 dm=V_ZL.dm,dw=V_ZL.dw,Zlh01=V_ZL.zlh01,Zlh02=V_ZL.zlh02,Zlh03=V_ZL.zlh03,
                 Zdb001=V_ZL.zdb001,Zdb002=V_ZL.zdb002,dh01=:new.dh01,dh02=:new.dh02
      
           WHERE zlh03=:old.zlh03 and dh02=:old.dh02;
       END IF;
       CLOSE C_ZL;        
    END IF;       end;
發表人 - zzmbeyond01 於 2004/12/15 22:58:08
zzmbeyond01
中階會員


發表:98
回覆:167
積分:53
註冊:2003-09-07

發送簡訊給我
#2 引用回覆 回覆 發表時間:2004-12-15 22:46:57 IP:222.183.xxx.xxx 未訂閱
找了份英文解决方法,但是还是不知道应该怎么写。,[(] 请大大指点 Hello, This problem as you might be knowing occurs when you try to select the data from the same table on which the trigger is written. Also this problem is only with the row level trigger and not with the statement level trigger. However the limitation of the statement level trigger is it can not refer to :NEW or :OLD. So now the solution is to capture the value of :NEW or :OLD in the row level trigger (no select statement here) and store it in some global variable. And how do you get the global variable? Using package specification ! a variable declared in a package specification is global in nature. Then use the value so stored in the statement level trigger in the select statement. It will work. Other solution is to use pragma autonomous transaction. Try and let us know. All the best. Regards
Fishman
尊榮會員


發表:120
回覆:1949
積分:2163
註冊:2006-10-28

發送簡訊給我
#3 引用回覆 回覆 發表時間:2004-12-16 08:20:40 IP:210.65.xxx.xxx 未訂閱
Hi zzmbeyond01,    你針對 Table FD 寫 Trigger,該 Trigger 中不能在 Select,Insert,Update 該 Table,否則就會產生該錯誤訊息!!    你是要 Update 同一筆資料嗎?如果是 可以用 :New.FieldName := NewValue; 或是 :New.FieldName := :Old.FieldName; 這種方式給值即可! ---------------------------------- 小弟才疏學淺,若有謬誤尚請不吝指教 ----------------------------------
------
Fishman
zzmbeyond01
中階會員


發表:98
回覆:167
積分:53
註冊:2003-09-07

發送簡訊給我
#4 引用回覆 回覆 發表時間:2004-12-16 12:40:54 IP:222.183.xxx.xxx 未訂閱
请问Fishman大大: (1)如果我不加where条件的话,该语句是不是更新的当前记录吧。如果要是一次变更很多条记录呢,会不会出问题? :New.FieldName := NewValue; (2)我想在该触发器trigger中级联更新另一个表,另一个表的数据为什么没有变化耶    
 IF (:old.zlh03<>:new.zlh03) or (:old.dh02<>:new.dh02)  THEN
       OPEN C_ZL(:new.zlh03);
       FETCH C_ZL INTO V_ZL;              
         IF C_ZL%FOUND THEN
            :new.dm:=V_ZL.dm;
            :new.dw:=V_ZL.dw;           
            :new.zlh03:=V_ZL.zlh03; 
            :new.dh01:=:new.dh02;            
           --更新分户      当dh02或zlh03变化后,希望更新fh表,但是triger后发现fh并没有变化
            update fh set dh02=:new.dh02,zlh03=:New.zlh03 where dh02=:old.dh02 and zlh03=:old.zlh03;    
發表人 - zzmbeyond01 於 2004/12/16 13:03:29
Fishman
尊榮會員


發表:120
回覆:1949
積分:2163
註冊:2006-10-28

發送簡訊給我
#5 引用回覆 回覆 發表時間:2004-12-16 13:23:31 IP:210.65.xxx.xxx 未訂閱
Hi zzmbeyond01,    1. :new.FieldName := NewValue 代表更新目前此筆資料的 fieldName 欄為值為 NewValue,並不會有多筆資料的問題,因為你的 Trigger 是設定為 FOR Each Row,所以每一筆資料異動皆會被觸發    2. 也許 Corsor 是空的,所以沒也進入迴圈執行 update 動作 你得程式好像是在更新目前紀錄與 Table fh update 指令忘了加 where Condition,會異動為最後一筆資料     ---------------------------------- 小弟才疏學淺,若有謬誤尚請不吝指教 ----------------------------------
------
Fishman
zzmbeyond01
中階會員


發表:98
回覆:167
積分:53
註冊:2003-09-07

發送簡訊給我
#6 引用回覆 回覆 發表時間:2004-12-16 13:38:54 IP:222.183.xxx.xxx 未訂閱
引言: Hi zzmbeyond01, 1. :new.FieldName := NewValue 代表更新目前此筆資料的 fieldName 欄為值為 NewValue,並不會有多筆資料的問題,因為你的 Trigger 是設定為 FOR Each Row,所以每一筆資料異動皆會被觸發 2. 也許 Corsor 是空的,所以沒也進入迴圈執行 update 動作 你得程式好像是在更新目前紀錄與 Table fh update 指令忘了加 where Condition,會異動為最後一筆資料 ---------------------------------- 小弟才疏學淺,若有謬誤尚請不吝指教 ---------------------------------- < face="Verdana, Arial, Helvetica"> 大大: Cursor中我测试存在记录,当我更新一条记录时候,正确更新了相关字段。 update 指令忘了加 where Condition,我不明白是什么意思,fh表更新不了,会不会是:old.dh02 :old.zlh03的问题呢? 我测试数据 fd表: dh02=10 zlh03=100012 fh表: dh02=10 zlh03=10012 fhid=1 dh02=10 zlh03=10012 fhid=2 發表人 - zzmbeyond01 於 2004/12/16 13:47:05
Fishman
尊榮會員


發表:120
回覆:1949
積分:2163
註冊:2006-10-28

發送簡訊給我
#7 引用回覆 回覆 發表時間:2004-12-16 14:48:13 IP:210.65.xxx.xxx 未訂閱
Hi zzmbeyond01,    Sorry !! 漏看了 where condition !!    有無可能是 :old.dh02 or :old.zlh03 是 Null 值?    若是此原因, update fh set dh02=:new.dh02,zlh03=:New.zlh03 where dh02=:old.dh02 and zlh03=:old.zlh03; 不會有任何作用,因為在 Oracle 中 NULL <> NULL ---------------------------------- 小弟才疏學淺,若有謬誤尚請不吝指教 ----------------------------------
------
Fishman
zzmbeyond01
中階會員


發表:98
回覆:167
積分:53
註冊:2003-09-07

發送簡訊給我
#8 引用回覆 回覆 發表時間:2004-12-16 17:21:41 IP:222.183.xxx.xxx 未訂閱
Fh是FD的从表, 
我加了一句,并没有抱错,说明不是空
  if :old.dh02=NULL  or  :old.zlh03=NULL then
   raise_application_error(-20000,'NULL');
  end if;
 update fh set dh02=:new.dh02,zlh03=:New.zlh03 where dh02=:old.dh02 and zlh03=:old.zlh03;
          
数据更改成功了,原来是fh表需要重新登陆数据库后就可以正确显示,怎么这么慢??
Fishman
尊榮會員


發表:120
回覆:1949
積分:2163
註冊:2006-10-28

發送簡訊給我
#9 引用回覆 回覆 發表時間:2004-12-16 17:45:40 IP:210.65.xxx.xxx 未訂閱
Hi zzmbeyond01,    更正你一個觀念:
  if :old.dh02=NULL  or  :old.zlh03=NULL then
   raise_application_error(-20000,'NULL');
  end if;
該程式是無用的,因為先前已提到,在 Oracle 中 NULL 不等於任何值,因此 raise_application_error 永遠沒有機會被觸發,你必須改成
  if :old.dh02 is NULL  or  :old.zlh03 is NULL then
   raise_application_error(-20000,'NULL');
  end if;
方有作用!! ---------------------------------- 小弟才疏學淺,若有謬誤尚請不吝指教 ----------------------------------
------
Fishman
zzmbeyond01
中階會員


發表:98
回覆:167
積分:53
註冊:2003-09-07

發送簡訊給我
#10 引用回覆 回覆 發表時間:2004-12-16 18:48:43 IP:222.183.xxx.xxx 未訂閱
多谢Fishman大大! if :old.dh02 is NULL or :old.zlh03 is NULL then 我说怎么想插入的时候,进行变更不行呢。
 IF INSERTING THEN
/*这以前写的  if :new.zlh03 <>NULL ,始终下面的值插不进去*/
    if :new.zlh03 is not NULL thenthen 
      :new.dh01:=:new.dh02;
end if;
end if;
我现在正在想是否能用orcle包解决
zzmbeyond01
中階會員


發表:98
回覆:167
積分:53
註冊:2003-09-07

發送簡訊給我
#11 引用回覆 回覆 發表時間:2004-12-16 23:37:21 IP:222.183.xxx.xxx 未訂閱
这样的触发器该如何写??折腾死人了 主表 class="code"> CREATE OR REPLACE TRIGGER ZL_UPDATE_TRG BEFORE UPDATE ON ZL FOR EACH ROW BEGIN IF :new.dm<>:old.dm or :new.dw<>:old.dw or :new.zlh01<>:old.zlh01 or :new.zlh02<>:old.zlh02 or :new.zlh03<>:old.zlh03 or :new.zdb001<>:old.zdb001 then --ZL表数据变化,同步更新FD表,但是执行fd的更新触发器出错 UPDATE fd SET dm=:new.dm,dw=:new.dw,zlh01=:new.zlh01,zlh02=:new.zlh02,zlh03=:new.zlh03,zdb001=:new.zdb001,zdb002=:new.zdb002 where dm=:old.dm and zlh01=:old.zlh01; END IF; END; CREATE OR REPLACE TRIGGER FD_Insert_Update_Trg BEFORE INSERT OR UPDATE ON FD For EACH ROW BEGIN IF (:old.zlh03<>:new.zlh03) or (:old.dh02<>:new.dh02) THEN --当FD表的zlh03值变化,则需要同时更新dm,dw,zlh01的值(从对应zlh03的ZL表中获得) --为避免ORA-4091错误,我用了一个包 --用包存储全局变量,使用after update语句级触发器处理 FDData.v_NumEntries:=FDData.v_NumEntries 1; FDData.v_zlh03(FDData.v_NumEntries):=:new.zlh03; FDData.v_dh02(FFDData.v_NumEntries):=:new.dh02; FDData.v_old_zlh03(FDData.v_NumEntries):=:old.zlh03; FDData.v_old_dh02(FDData.v_NumEntries):=:old.dh02; END IF; END; Create Or Replace Trigger FD_After_Update_Trg after update on fd begin --如果zlh01,zlh03或dh02发生变化 FOR v_loop IN 1..FDData.v_NumEntries LOOP --获得zl信息 当使用ZL_UPDATE_TRG触发器更新FD表时,执行到这里又抱错了 这类问题怎么解决??急急急 SELECT t.dm,t.dw,t.zlh01,t.zlh02 INTO FDData.v_dm(FDData.v_NumEntries),FDData.v_dw(FDData.v_NumEntries), FDData.v_zlh01(FDData.v_NumEntries),FDData.v_zlh02(FDData.v_NumEntries) FROM ZL t WHERE t.zlh03=FDData.v_zlh03(FDData.v_NumEntries); --更新FD表相关字段值dm dw zlh01 zlh02 zlh03 UPDATE FD SET dm= FDData.v_dm(FFDData.v_NumEntries), dw=FDData.v_dw(FDData.v_NumEntries), zlh01=FDData.v_zlh01(FDData.v_NumEntries), zlh02=FDData.v_zlh02(FDData.v_NumEntries), zlh03=FDData.v_zlh03(FDData.v_NumEntries), dh02=FDData.v_dh02(FDData.v_NumEntries) , dh01=FDData.v_dh02(FFDData.v_NumEntries) WHERE zlh03= FDData.v_zlh03(FDData.v_NumEntries) and dh02= FDData.v_dh02(FDData.v_NumEntries); END LOOP; FDData.v_NumEntries:=0; end FD_After_Update_Trg; 包定义如下: create or replace package FDData is TYPE t_dm IS TABLE OF ZL.Dm%type INDEX BY BINARY_INTEGER; TYPE t_dw IS TABLE OF ZL.Dw%type INDEX BY BINARY_INTEGER; TYPE t_zlh01 IS TABLE OF GK.Zlh01%type INDEX BY BINARY_INTEGER; TYPE t_zlh02 IS TABLE OF GK.Zlh02%type INDEX BY BINARY_INTEGER; TYPE t_zlh03 IS TABLE OF GK.Zlh03%type INDEX BY BINARY_INTEGER; TYPE t_dh02 IS TABLE OF FD.Dh02%type INDEX BY BINARY_INTEGER; /*用于防止发生mutationg table变化表错误*/ --变更后的信息 v_dm t_dm; v_dw t_dw; v_zlh01 t_zlh01; v_zlh02 t_zlh02; v_zlh03 t_zlh03; v_dh02 t_dh02; --存储更新前的 值 v_old_zlh01 t_zlh01; v_old_zlh03 t_zlh03; v_old_dh02 t_dh02; --用于标识更新的记录数 v_NumEntries BINARY_INTEGER:=0; end FDData; 發表人 - zzmbeyond01 於 2004/12/16 23:49:52 發表人 - zzmbeyond01 於 2004/12/16 23:55:29
zzmbeyond01
中階會員


發表:98
回覆:167
積分:53
註冊:2003-09-07

發送簡訊給我
#12 引用回覆 回覆 發表時間:2004-12-17 11:06:01 IP:222.183.xxx.xxx 未訂閱
ZL_UPDATE_TRG行级触发器更新ZL表时,先更新FD表, 触发FD_Insert_Update_Trg行级触发器去做更新FD表的动作, FD_Insert_Update_Trg行级触发器在语句级触发器 FD_After_Update_Trg中使用了ZL表的select语句,而此时ZL表是(mutating table)变化表,oracle就抱错了,怎么解决??? 已经用了一个Oracle包,但是不行耶 發表人 - zzmbeyond01 於 2004/12/17 11:19:30
系統時間:2024-06-25 14:54:02
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!