web-dev-qa-db-ja.com

postgresqlのオプションパラメータの関数を書く方法は?

私の要件は、オプションのパラメーターを関数に書き込むことです。パラメーターはオプションである場合がありますが、関数にパラメーターを追加したり、パラメーターを渡したりしない場合があります。

私は次のように書いています

select * 
from test 
where field3 in ('value1','value2') 
 and ($1 is null or field1 = $1) 
 and ($2 is null or field2 = $2) 
 and ($3 is null or field3 = $3);

私はクエリにパラメータを渡しますが、出力は期待されていません。3つのパラメータすべてを渡すと、出力は正しいです。そうでない場合、出力は期待されません。

25
indu

デフォルト値を指定することにより、オプションのパラメーターを定義できます。

_create function foo(p_one integer default null, 
                    p_two integer default 42, 
                    p_three varchar default 'foo')
  returns text
as
$$
begin
    return format('p_one=%s, p_two=%s, p_three=%s', p_one, p_two, p_three);
end;
$$
language plpgsql;
_

パラメーターを最後から「除外」できるため、foo()foo(1)、またはfoo(1,2)が有効です。最初ではないパラメーターのみを指定する場合は、パラメーター名を指定する構文を使用する必要があります。

_select foo(); 
_

戻り値:_p_one=, p_two=42, p_three=foo_

_select foo(1); 
_

戻り値:_p_one=1, p_two=42, p_three=foo_

_select foo(p_three => 'bar')
_

戻り値:_p_one=, p_two=42, p_three=bar_

50

@a_horse_with_no_nameが指す [〜#〜] variadic [〜#〜] オプションの一部。これは、任意の数の要素を持つ配列を渡すための構文シュガーのみです同じタイプ、postgresでは、関数は名前だけでなく、引数とその型によっても識別されるため、オプションのパラメーターで関数を定義することはできません。

つまり、create function foo (int) [...]およびcreate function foo (varchar) [...]は、different関数を作成します。

実行時に呼び出されます。たとえば、select foo(bar)は、barデータ型自体に依存します。つまり、整数の場合は最初の関数を呼び出し、varcharの場合は2番目の関数を呼び出します。

それ以上:select foo(now())などを実行すると、function not exists例外がトリガーされます。

したがって、私が言ったように、可変引数を持つ関数を実装することはできませんただし、同じデータ型を返す同じ名前と異なる引数(または型)セットを持つ複数の関数を実装できます

(明らかに)関数を2回実装したくない場合、必要なことは、可能なすべてのパラメーターと「マスター」関数のみを呼び出す他のパラメーター(パラメーターが少ない)で「マスター」関数を実装することだけです。非受信パラメーターのデフォルト値を使用します。

6
bitifet

オプションとして、Navicat Appでテストした関数がありました:CREATE OR REPLACE FUNCTION "public"."for_loop_through_query"(sponsor_name varchar default 'Save the Children')これは私にこれを生成します。 (注:パラメーターの違いを確認してください)CREATE OR REPLACE FUNCTION "public"."for_loop_through_query"("sponsor_name" varchar='Save the Children'::character varying)

 CREATE OR REPLACE FUNCTION "public"."for_loop_through_query"("sponsor_name" varchar='Save the Children'::character varying)
  RETURNS "pg_catalog"."void" AS $BODY$
DECLARE
    rec RECORD;
BEGIN
    FOR rec IN SELECT
      companies."name" AS org_name,
      "sponsors"."name" AS sponsor_name
      FROM
      "donor_companies"
      JOIN "sponsors"
      ON "donor_companies"."donor_id" = "sponsors"."id" 
      JOIN companies
      ON "donor_companies"."organization_id" = companies."id"
      WHERE
      "public"."sponsors"."name" = sponsor_name
    LOOP
    RAISE NOTICE '%', rec.org_name;
  END LOOP;
END;
$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100;
0
Kiry Meas