1

insertupdate、から来るトリガーがありますdelete

このアップデートでは、 が実行されるたびにスタックの深さの制限を超えupdateて、無限ループに陥ります。(無限再帰)

誰にもヒントはありますか?

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'
4

1 に答える 1

1

トリガーで間違ったことをしていると思います。トリガーが再帰することはほとんどありません。再帰する場合は、無限に再帰できないことを確認する必要があります。

操作が行われる対象を単に変更するのではなく、操作を再度実行しようとするため、無限再帰が発生します。null を返します。これは、意図したことをすべて実行済みであることを示します。

更新ステートメントなどをやり直す代わりに、変更されたデータを含む NEW 値を返すだけです。元の要求で変更されていないテーブル (またはどうしても必要な場合は行) を変更する場合にのみ、UPDATE または DELETE を使用してください。

于 2013-11-28T09:08:47.217 に答える