2017-09-18 8 views
0

現在、2つのリストの値のバランスをとるPL/SQLプロシージャを実装しています。更新されたフィールドの条件付きカーソルをループする[PLSQL]

が背景として、この例を考えてみましょう:

  • Rec_1 | 2
  • Rec_2 | 1
  • Rec_3 | 2

  • Rec_A | -1
  • Rec_B | -3
  • Rec_C | -2

これらのすべての値を1つずつループしてできるだけ整理したい、つまり最初の決済後にRec_1を1にし、Rec_Aを0にする必要があります。その後、Rec_1が決済されます。 1を取得するようにRec_Bを使用し、-2を取得するなど。

私はこれを行うために2つのカーソルを使用し、この値を更新するよりももう少し多くのことがあるので、独自のプロシージャ(または必要な場合は関数)の値を更新したいと考えています。

ここに私の挑戦があります: 決済が行われた後にどのカーソルをフェッチするのかをどのように知っていますか?

は今のところ、この機能のための私のコードは次のようになります。整定プロシージャ内

PROCEDURE SettleLists (
    ListNegV SYS_REFCURSOR, 
    ListPosV SYS_REFCURSOR 
) IS 
    currentNegV TABLENAME%ROWTYPE; 
    currentPosV TABLENAME%ROWTYPE; 
BEGIN 
    FETCH ListNegV INTO currentNegV; 
    FETCH ListPosV INTO currentPosV; 
    LOOP 
    EXIT WHEN ListNegV%NOTFOUND; 
    EXIT WHEN ListPosV%NOTFOUND; 
    IF (currentNegV.NUMERICVALUE < 0) 
    THEN 
     IF (currentPosV.NUMERICVALUE > 0) 
     THEN 
     Settle(currentPosV, currentNegV); 
     ELSE 
     FETCH ListPosV INTO currentPosV; 
     END IF; 
    ELSE 
     FETCH ListNegV INTO currentNegV; 
    END IF; 
    END LOOP; 
END; 

、両方のレコードのUPDATEがあるでしょう。変数とカーソル値は更新されないため、無限ループが発生します。レコードがデータベース内で更新されたときに決済のパラメータを更新することもできますが、カーソルに慣れていないので、より良い考えがあるかもしれません。

カーソルが強く型付けされていると考えることができます。カーソルを使うよりも良い方法があれば、それを提案してください。

最後に、私はSELECT FOR UPDATEとWHERE CURRENT OFを更新していましたが、その間にプロシージャーにカーソルを渡すと機能していないようです。誰かがこれについていくつかのアイデアを持っている場合、私はあなたの助けにも感謝します。

答えて

1

ここに私がすることがあります。私は確かにいくつかのコメントを追加します。

これはOracle 11Gr2で正常に動作しています。これは7iでもうまく動作することを期待しています:)。

declare 
    cursor c1 is 
     select 'REC_1' HEader,2 Val from dual 
     union 
     select 'REC_2' HEader,1 Val from dual 
     union 
     select 'REC_3' HEader,2 Val from dual; 
    cursor c2 is 
     select 'REC_A' HEader,-1 Val from dual 
     union 
     select 'REC_B' HEader,-3 Val from dual 
     union 
     select 'REC_C' HEader,-2 Val from dual; 
    num_bal1 number; 
    num_bal2 number; 
    num_settle_amt number; 
    rec_type_c1 c1%rowtype; 
    rec_type_c2 c2%rowtype; 
begin 

    Open c1; 
    open c2; 
    fetch c1 into rec_type_c1; 
    fetch c2 into rec_type_c2; 
    num_bal1 := nvl(rec_type_c1.val,0); 
    num_bal2 := rec_type_c2.val; 
    Loop 

     exit when c1%notfound or c2%notfound; 
     Loop 
      dbms_output.put_line('Processing ' || rec_type_c1.header || ' with ' || num_bal1); 
      --In your example there are only +ve for 1 and -ve for 2. But if that is not correct, check for signs and next 3 statements 
      num_settle_amt := least(abs(num_bal1), abs(num_bal2)); 
      num_bal1 := num_bal1 - num_settle_amt; 
      num_bal2 := num_bal2 + num_settle_amt; 
      dbms_output.put_line('Setteled ' || num_settle_amt || ' of ' || rec_type_c1.header || ' with ' || rec_type_c2.header); 
      if num_bal1 = 0 then 
       --Update in the table. It will not impact variable. 
       fetch c1 into rec_type_c1; 
       num_bal1 := nvl(rec_type_c1.val,0); 
      end if; 

      if num_bal2 = 0 then 
       --Update in the table. It will not impact variable. 
       fetch c2 into rec_type_c2; 
       num_bal2 := nvl(rec_type_c2.val,0); 
      end if; 

     End loop; 
    end loop; 
    close c1; 
    close c2; 
end; 
+0

これをコードする時間を割いてくれてありがとう。これはうまく動作し、私はちょうどテーブルと変数の両方を更新せずにこれを可能にする技術があると思った。 – user2083834

関連する問題