0

他の処理のための予備情報を取得するために使用されるカーソルがあります。カーソルをサポートするクエリが行を返さない可能性があります。これらのまれなケースでは、特別な例外を発生させて (処理が完全に停止しないように別の場所で処理およびログを記録します)、ユーザーが何が最も可能性が高いかを知ることができます。入力が悪い。外観は次のとおりです。

open c_getPrs(in_pnum);
loop

    fetch c_getPrs
        into r_rpmRecord;            

     if c_getPrs%NOTFOUND then
       raise X_INVALID_PNUM;
    end if;

    exit when c_getPrs%rowcount > 1 /*or c_getPrs%NOTFOUND*/;           
end loop;
close c_getPrs;

問題は、if ステートメントが常に実行されるため、行が返された場合でも常に例外が発生することです。理由はわかりません。この種のロジックを処理するためのより良い方法があれば、私もそれを受け入れます ;)

4

2 に答える 2

7

コードは常にループを 2 周するため、カーソルによって返される行が 2 つ未満の場合は失敗します。おそらくループはまったく必要ありません。

open c_getPrms(in_pnum);

fetch c_getPrms
 into r_prmRecord;

if c_getPrms%NOTFOUND then
  raise X_INVALID_PNUM;
end if;

close c_getPrms;

私はカーソルを完全に避け、代わりに「select into」を使用したいと思います:

begin
   select ...
   into   r_prmRecord
   from   ...
   where  ...
exception
   when no_data_found then
      raise X_INVALID_PNUM;
end;

選択が複数の行を返す場合、これは TOO_MANY_ROWS を発生させます。これが発生したくない場合、つまり複数の行が問題ない場合は、クエリに「AND ROWNUM = 1」を追加するだけです。

于 2009-11-10T16:18:34.757 に答える
5

問題は終了条件にあります。最初のパスで c_getPrms%rowcount が 1 であるため、例外を発生させる別のパスを取得します。

フェッチが 1 つだけ必要なため、次の構成をお勧めします。

OPEN c_getPrms(l_input);

FETCH c_getPrms
   INTO r_prmRecord;

IF c_getPrms%NOTFOUND THEN
   RAISE X_INVALID_PNUM;
END IF;

CLOSE c_getPrms;

私は明示的なカーソルがあまり好きではないので、次のシンタックスも提案します。

BEGIN
   SELECT ... 
     INTO r_prmRecord 
     FROM ... 
    WHERE ... AND rownum = 1; -- your cursor query
EXCEPTION
   WHEN no_data_found THEN
      RAISE X_INVALID_PNUM;
END;
于 2009-11-10T16:16:03.420 に答える