2

PostgreSQLでエラーが発生します:

ERROR: argument for function "exp" too big
SQL state: 22003

Exponentialの保存されたプロシージャを次のように記述する必要があります。

  • 関数exp(value)「exp」の引数が大きすぎる場合
  • 次に0を返します
  • それ以外の場合は戻りますexp(value)

このストアドプロシージャの処理方法を教えてください。

4

1 に答える 1

2

これが起こっていることです:

regress=# SELECT exp(NUMERIC '6000');
ERROR:  argument for function "exp" too big

に非現実的に大きな値を渡していますexp()。(double)をオーバーフローするには大きすぎてfloat8、 としてしか表現できませんNUMERIC。そこにも限界があり、上に行くと当たるexp(5999)

難しい数学については、言語PL/Rのデータベース内埋め込みバージョンであるを試してみてください。R

何をすべきかを言うのは難しいです。なぜなら、クエリが何のためにあるのか、何への入力expが想定されているのかなどを実際に説明していないからです.

大きすぎる指数に対して 0 を返すのはちょっとおかしなことです。なんで?


例外をトラップするには、PL/PgSQL でBEGIN ... EXCEPTIONを使用します。

NaNゼロを返すのはまったく間違っていると思うので、ゼロの代わりに(「数値ではない」)を返す以下の関数を作成しました。必要に応じて変更してください。返すのも少し意味があるかもしれませんNULL

CREATE OR REPLACE FUNCTION exp_if_possible(numeric) RETURNS numeric as $$
BEGIN
    RETURN exp($1);
EXCEPTION
    WHEN numeric_value_out_of_range THEN
        RETURN 'NaN';
END;
$$ LANGUAGE 'plpgsql' IMMUTABLE;

エラーコードは、Pg マニュアルの付録 A. PostgreSQL エラー コードで範囲から取得したものを参照して取得numeric_value_out_of_rangeされました。に関するドキュメントにリンクが表示されます。SQLSTATE 22003expBEGIN ... EXCEPTION


私は当初、それを行うのであれば、入力をテストすることによって行うべきだと言いましたが、それは間違っていたと思います。制限が になるという保証はないexp(6000)ので、遅くてぎこちなくても、例外処理を使用するのは正しいことです。すぐに例外処理バージョンでこの応答を更新します。

CREATE OR REPLACE FUNCTION crazy_exp(numeric) RETURNS numeric AS $$
-- exp(6000) and above will throw 'argument for function "Exp" too big
-- For such cases, return zero because [insert explanation here]
SELECT CASE WHEN $1 < 6000 THEN exp($1) ELSE 0 END;
$$ LANGUAGE 'sql' IMMUTABLE;

CREATE OR REPLACE FUNCTION crazy_exp(float8) RETURNS float8 AS $$
-- float8 goes out-of-range above about exp(600)
SELECT CASE WHEN $1 <= 600 THEN exp($1) ELSE 0 END;
$$ LANGUAGE 'sql' IMMUTABLE;

これは、PL/ PgSQLで「範囲外」の例外をトラップするよりもはるかに効率的であり、意図もより明確になります。

于 2012-08-30T06:22:19.623 に答える