web-dev-qa-db-fra.com

Comment écrire une fonction pour les paramètres optionnels dans postgresql?

Mon exigence est d'écrire des paramètres facultatifs dans une fonction.Les paramètres sont facultatifs parfois j'ajouterai ou je ne transmettrai pas de paramètres à la fonction.Peut-on m'aider à écrire une fonction.

J'écris comme

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);

je passe des paramètres à Query, mais ma sortie n'est pas attendue.Lorsque je passe les trois paramètres, ma sortie est correcte, sinon ce n'est pas la sortie attendue.

25
indu

Vous pouvez définir des paramètres facultatifs en fournissant une valeur par défaut.

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;

Vous pouvez "laisser de côté" les paramètres à la fin, donc foo(), foo(1) ou foo(1,2) sont valides. Si vous souhaitez uniquement fournir un paramètre qui n'est pas le premier, vous devez utiliser la syntaxe qui spécifie les noms des paramètres.

select foo(); 

renvoie: p_one=, p_two=42, p_three=foo

select foo(1); 

renvoie: p_one=1, p_two=42, p_three=foo

select foo(p_three => 'bar')

renvoie: p_one=, p_two=42, p_three=bar

50

En dehors de l'option VARIADIC pointée par @a_horse_with_no_name, qui n'est qu'un sucre de syntaxe pour passer un tableau avec un certain nombre d'éléments du même type , vous ne peut pas définir une fonction avec des paramètres optionnels car, en postgres, les fonctions sont identifiées non seulement par son nom mais aussi par ses arguments et leurs types.

C'est-à-dire: create function foo (int) [...] et create function foo (varchar) [...] créeront différentes fonctions .

Qui est appelée lorsque vous exécutez, par exemple, select foo(bar) dépend du type de données bar lui-même. C'est-à-dire: s'il s'agit d'un entier, vous appellerez le premier et s'il s'agit de varchar, alors le second sera appelé.

Plus que cela: si vous exécutez, par exemple, select foo(now()), alors une exception la fonction n'existe pas sera déclenchée.

Donc, comme je l'ai dit, vous ne pouvez pas implémenter des fonctions avec des arguments variables, mais vous pouvez implémenter plusieurs fonctions avec le même nom et des ensembles d'arguments distincts (un/ou type) retournant le même type de données .

Si vous (évidemment) ne voulez pas implémenter la fonction deux fois, la seule chose que vous devez faire est d'implémenter une fonction "maître" avec tous les paramètres possibles et les autres (qui ont moins de paramètres) n'appelant que celle "maître" avec des valeurs par défaut pour les paramètres non reçus.

6
bitifet

En option, j'ai obtenu une fonction que j'ai testée avec Navicat App: CREATE OR REPLACE FUNCTION "public"."for_loop_through_query"(sponsor_name varchar default 'Save the Children') Cela me génère cela. (Remarque: veuillez regarder la différence de paramètre) 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