PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

Argument optionnel dans la fonction PL/pgSQL

Depuis PostgreSQL 8.4 (que vous semblez exécuter), il existe des valeurs par défaut pour les paramètres de fonction . Si vous placez votre paramètre en dernier et fournissez une valeur par défaut, vous pouvez simplement l'omettre de l'appel :

CREATE OR REPLACE FUNCTION foofunc(_param1 integer
                                 , _param2 date
                                 , _ids    int[] DEFAULT '{}')
  RETURNS SETOF foobar         -- declare return type!
  LANGUAGE plpgsql AS
$func$
BEGIN  -- required for plpgsql
   IF _ids <> '{}'::int[] THEN  -- exclude empty array and NULL
      RETURN QUERY
      SELECT *
      FROM   foobar
      WHERE  f1 = _param1
      AND    f2 = _param2
      AND    id = ANY(_ids);    -- "IN" is not proper syntax for arrays
   ELSE
      RETURN QUERY
      SELECT *
      FROM   foobar
      WHERE  f1 = _param1
      AND    f2 = _param2;
   END IF;
END  -- required for plpgsql
$func$;

Principaux points :

  • Le mot clé DEFAULT est utilisé pour déclarer les paramètres par défaut. Alternative courte := .

  • J'ai supprimé le param1 redondant de l'exemple désordonné.

  • Depuis que vous retournez SELECT * FROM foobar , déclarez le type de retour comme RETURNS SETOF foobar au lieu de RETURNS SETOF record . Ce dernier formulaire avec des enregistrements anonymes est très peu maniable, vous devez fournir une liste de définitions de colonnes à chaque appel.

  • J'utilise un tableau d'entiers (int[] ) comme paramètre de fonction. Adapté le IF expression et le WHERE clause en conséquence.

  • IF les instructions ne sont pas disponibles en SQL brut. Doit être LANGUAGE plpgsql pour ça.

Appel avec ou sans _ids :

SELECT * FROM foofunc(1, '2012-1-1'::date);

Effectivement le même :

SELECT * FROM foofunc(1, '2012-1-1'::date, '{}'::int[]);

Vous devez vous assurer que l'appel est sans ambiguïté. Si vous avez une autre fonction du même nom et deux paramètres, Postgres ne saura peut-être pas lequel choisir. Le casting explicite (comme je le démontre) le réduit. Sinon, les littéraux de chaîne non typés fonctionnent également, mais être explicite ne fait jamais de mal.

Appel depuis une autre fonction :

CREATE FUNCTION foofuncwrapper(_param1 integer, _param2 date)
  RETURNS SETOF foobar
  LANGUAGE plgpsql AS
$func$
DECLARE
   _ids int[] := '{1,2,3}';
BEGIN
   -- whatever

   RETURN QUERY
   SELECT * FROM foofunc(_param1, _param2, _ids);
END
$func$;