2

例として、postgres で 2 つの数値を安全に除算するカスタム関数を書きたいとします。つまり、どちらかの引数が null であるか、除数がゼロであるかをチェックする必要があります。これらのエラー条件を適切に処理する必要があり、それ以外の場合は期待される商を返す必要があります。

現在のコードは、2 つの引数が同じ数値型 (両方とも整数、両方とも数値など) である限りうまく機能します。

CREATE OR REPLACE FUNCTION safe_divide(anyelement, anyelement) RETURNS numeric AS $$
  SELECT CASE 
     WHEN $1 IS NULL OR $2 IS NULL OR $2 = 0 THEN NULL 
     ELSE $1::numeric / $2::numeric
     END;
$$ LANGUAGE SQL;

私の質問: さまざまな数値型を提供できるように、この関数を記述する方法はありますか?

私は避けたい:

  • 関数を呼び出すときに引数を明示的にキャストする必要がある (例safe_divide(x::numeric, y::numeric))

  • 可能なすべてのデータ型に対して関数を定義する必要がある

ありがとう!

4

3 に答える 3

4

数値パラメーターと倍精度で関数を定義すると、すべての数値パラメーターに使用できます。

  CREATE OR REPLACE FUNCTION safe_divide(numeric, numeric) RETURNS numeric AS $$
   SELECT CASE 
     WHEN $1 IS NULL OR $2 IS NULL OR $2 = 0 THEN NULL ELSE $1 / $2 END;
  $$ LANGUAGE SQL;

  CREATE OR REPLACE FUNCTION safe_divide(double precision, double precision)
  RETURNS numeric AS $$
   SELECT CASE 
     WHEN $1 IS NULL OR $2 IS NULL OR $2 = 0 THEN NULL 
                                             ELSE $1::numeric / $2::numeric END;
  $$ LANGUAGE SQL;

他の種類のデータ型には意味がありません

 postgres=# select safe_divide(10::float,10::int);
       safe_divide       
 ------------------------
  1.00000000000000000000
 (1 row)

 postgres=# select safe_divide(10::numeric,10::int);
       safe_divide       
 ------------------------
  1.00000000000000000000
 (1 row)

 postgres=# select safe_divide(10::int,10::int);
       safe_divide       
 ------------------------
  1.00000000000000000000
 (1 row)

 postgres=# select safe_divide(10,10.0);
       safe_divide       
 ------------------------
  1.00000000000000000000
 (1 row)

これはPostgreSQLの典型的なパターンです

于 2013-04-23T05:54:26.390 に答える
0

私はそれが不可能であることを恐れています:

anyelement として宣言された各位置 (引数または戻り値のいずれか) は、特定の実際のデータ型を持つことができますが、特定の呼び出しでは、それらはすべて同じ実際の型である必要があります。 http://www.postgresql.org/docs/current/static/extend-type-system.html

引数を数値にキャストするのが最善の方法だと思います。

于 2013-04-22T09:18:12.083 に答える