4

pl/sql 関数に次のような for ループがあります。

FOR i IN min..max LOOP

変数 i、min、max は次のように宣言されます。NUMERIC

私の場合、最小値と最大値はしばしば非常に大きくなりますが、範囲自体は小さいです。つまり:

min = 3232236033
max = 3232236286

ご覧のとおり、範囲は約 256 ですが、この値を使用するとオラクルは数値オーバーフロー エラーをスローし、それを機能させる方法に固執しました。

これらの値をどのように反復処理する必要がありますか?

編集

OK、最大/最小差分のループを使用して有効な答えがありますが、オラクルで大きな値をループすることは本当に不可能ですか?

編集私が取得したエラーは次のとおりです。

SQL Error: ORA-01426: nadmiar numeryczny
ORA-06512: przy "PS.DHCP", linia 88
01426. 00000 -  "numeric overflow"
*Cause:    Evaluation of an value expression causes an overflow/underflow.
*Action:   Reduce the operands.

コードの 88 行目は次のとおりです。

FOR client_ip IN min_host..max_host

min_host、max_host、client_ip はinet_aton(IP の数値表現)の結果です。

4

2 に答える 2

7

問題は、私が小さすぎる数としてキャストされていることに起因しているようです(これはpl/sqlの欠点のようです)。ループタイプを変更できます:

While ループは正常に動作します

set serveroutput on
/
declare
 min_val number;
 max_val number ;
 iterator number ;
begin
    min_val := 3232236033 ;
    max_val := 3232236286 ;

    iterator := min_val;
    while iterator<=max_val loop
        dbms_output.put_line(iterator);
        iterator  := iterator  + 1;
    end loop ;

end;
/

ここから: http://download.oracle.com/docs/cd/E11882_01/appdev.112/e17126/controlstatements.htm#BABEFFDC

FOR LOOP インデックス

FOR LOOP ステートメントのインデックスは、ループに対してローカルな INTEGER 型の変数として暗黙的に宣言されます。ループ内のステートメントは、インデックスの値を読み取ることはできますが、変更することはできません。ループ外のステートメントはインデックスを参照できません。FOR LOOP ステートメントの実行後、インデックスは未定義です。(ループ インデックスは、ループ カウンターと呼ばれることもあります。)

例4-17では、 FOR LOOP 文がその索引の値を変更しようとして、エラーが発生しています。

これに進む: http://download.oracle.com/docs/cd/B28359_01/appdev.111/b28370/loop_statement.htm

インデックス名

ループ インデックスに名前を付ける宣言されていない識別子 (ループ カウンターと呼ばれることもあります)。そのスコープはループ自体です。ループの外でインデックスを参照することはできません。

index_name の暗黙的な宣言は、ループ外の他の宣言をオーバーライドします。同じ名前の別の変数を参照するには、ラベルを使用します。例4-22「ループ・カウンタと同じ名前のグローバル変数の参照」を参照してください。

ループ内では、インデックスは定数のように扱われます。インデックスは式に表示できますが、値を割り当てることはできません。

したがって、宣言で「インデックス」を宣言しても、それはループ内で使用されておらず、代わりに暗黙的に作成された INDEX を使用しています (ニーズに対して精度が小さすぎるようです)。

于 2011-02-18T18:02:37.827 に答える
3

minループ変数を 0 からとの差まで実行できますmax。以下は、数値を DBMS_OUTPUT に書き込むだけの例です。

DECLARE
  v_min     INTEGER := 3232236033;
  v_max     INTEGER := 3232236286;
  v_diff    PLS_INTEGER;
BEGIN
  v_diff := v_max - v_min;
  FOR i IN 0..v_diff
  LOOP
    -- Use v_min + i where you would have used i.
    dbms_output.put_line(v_min + i);
  END LOOP;
END;
/

EDIT : 残念ながら、範囲演算子を使用して多数を反復処理することはできません。範囲演算子..は、範囲 +/- 2 31に制限されています。PL/SQL ドキュメントから:

内部的に、PL/SQLは境界の値を一時的な PLS_INTEGER 変数に割り当て、必要に応じて値を最も近い整数に丸めます。PLS_INTEGER の大きさの範囲は -2**31 .. 2**31 です。境界がその範囲外の数値に評価されると、PL/SQL が代入を試みるときに数値オーバーフロー エラーが発生します。

于 2011-02-18T17:35:00.253 に答える