2013-10-15 61 views
1

每當運行update我已經超過了在此更新腳麻棧深度限制來自insertupdatedelete堆棧深度超出限制的PostgreSQL

一個觸發器,它進入無限循環。 (無限遞歸)

任何人有任何提示?

CREATE OR REPLACE FUNCTION saldolinear() RETURNS TRIGGER AS 
' 
DECLARE 
    IDS INTEGER:= 0; MIN integer:= 0; MIN1 integer:= 0; valor1 float;saldo float; saldoini float; saldoini1 float;i integer:=0;j integer:= 0; 
    l integer:=0; m integer:=0;var2 integer:=0;countid integer:=0;coun integer:=0;DATADB date;IDMAX integer:=0;dataup date; 
    coundata date; res boolean; res1 boolean; mov TB_MOV_BANCARIA%rowtype; registro integer; 
BEGIN 
    IF (TG_OP = ''INSERT'') THEN 
     SELECT INTO registro count(TB_MOV_BANCARIA.data) FROM TB_MOV_BANCARIA where TB_MOV_BANCARIA.data<NEW.data group by TB_MOV_BANCARIA.data; 
    saldoini:=0;   
    IF (registro>0) THEN  
     res:= true; 
     SELECT INTO DATADB MAX(TB_MOV_BANCARIA.data) FROM TB_MOV_BANCARIA where TB_MOV_BANCARIA.data<NEW.data; 
     FOR mov IN select tb_mov_bancaria.id from tb_mov_bancaria where tb_mov_bancaria.data = DATADB order by tb_mov_bancaria.data, tb_mov_bancaria.id LOOP 
      SELECT INTO saldoini saldo_linha FROM TB_MOV_BANCARIA where id = mov.id; 
     END LOOP; 
    END IF;  
      FOR mov IN select * from tb_mov_bancaria where tb_mov_bancaria.data>=NEW.data order by tb_mov_bancaria.data, tb_mov_bancaria.id LOOP 
       saldoini := saldoini + mov.valor; 
      UPDATE tb_mov_bancaria set saldo_linha=saldoini where id = mov.id; 
     END LOOP; 
    END IF; 
    IF (TG_OP = ''UPDATE'') THEN 
     IF(OLD.data<NEW.data)THEN 
     dataup:= OLD.data; 
    ELSE 
     dataup:= NEW.data; 
     END IF; 
     IF (NOT dataup is null) THEN 
      SELECT INTO DATADB MAX(TB_MOV_BANCARIA.data) FROM TB_MOV_BANCARIA where TB_MOV_BANCARIA.data<dataup; 
     FOR mov IN select tb_mov_bancaria.id from tb_mov_bancaria where tb_mov_bancaria.data = DATADB order by tb_mov_bancaria.data, tb_mov_bancaria.id LOOP 
      SELECT INTO saldoini saldo_linha FROM TB_MOV_BANCARIA where id = mov.id; 
     END LOOP; 
     --RAISE EXCEPTION ''%'',dataup; 
     FOR mov IN select * from tb_mov_bancaria where tb_mov_bancaria.data>=dataup order by tb_mov_bancaria.data, tb_mov_bancaria.id LOOP 
       saldoini := saldoini + mov.valor; 
       --RAISE EXCEPTION ''UPDATE tb_mov_bancaria set saldo_linha=% where id = %;'',saldoini,mov.id; 
      UPDATE tb_mov_bancaria set saldo_linha=saldoini where id = mov.id; 
     END LOOP; 
     END IF; 
    END IF; 
     IF (TG_OP = ''DELETE'') THEN 
     res:= true; 
     SELECT INTO DATADB MAX(TB_MOV_BANCARIA.data) FROM TB_MOV_BANCARIA where TB_MOV_BANCARIA.data<OLD.data; 
     FOR mov IN select tb_mov_bancaria.id from tb_mov_bancaria where tb_mov_bancaria.data = DATADB order by tb_mov_bancaria.data, tb_mov_bancaria.id LOOP 
      SELECT INTO saldoini saldo_linha FROM TB_MOV_BANCARIA where id = mov.id; 
     END LOOP; 

      FOR mov IN select * from tb_mov_bancaria where tb_mov_bancaria.data>=OLD.data   order by tb_mov_bancaria.data, tb_mov_bancaria.id LOOP 
       saldoini := saldoini + mov.valor; 
      UPDATE tb_mov_bancaria set saldo_linha=saldoini where id = mov.id; 
     END LOOP; 
     END IF; 
      RETURN NULL; 
    END 
    ' 
    LANGUAGE 'plpgsql' 
+0

該觸發器是否運行,用於表「tb_mov_bancaria」的任何插入/更新/刪除? – Mauren

+1

這是充滿了循環和SQL可怕的線性邏輯...如果這是每個插入/更新運行,你會使這個表幾乎不可能插入/更新。只有我可以提供的技巧是重新審視邏輯,看看你是否可以在沒有循環的情況下做到這一點 – Twelfth

+0

是的它有一個觸發器saldoinsert,saldoupdate,saldodelete。 –

回答

1

我認爲你是用你的觸發器做錯了事。一個觸發器應該幾乎從來沒有遞歸,如果它遞歸,你必須確保它無法無限遞歸。

發生無限遞歸是因爲您嘗試再次執行操作而不是僅僅修改操作發生的位置。你返回null,這表明你已經完成了你打算做的一切。

而不是重做更新語句等,只是返回一個新值,包括修改後的數據。只有使用UPDATE或DELETE才能修改未被原始請求修改的表(或者如果您絕對必須,行)。