PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Optionales Argument in der PL/pgSQL-Funktion

Seit PostgreSQL 8.4 (das Sie anscheinend ausführen) gibt es Standardwerte für Funktionsparameter . Wenn Sie Ihren Parameter an letzter Stelle setzen und einen Standard angeben, können Sie ihn einfach aus dem Aufruf weglassen:

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

Wichtige Punkte:

  • Das Schlüsselwort DEFAULT wird verwendet, um Parametervorgaben zu deklarieren. Kurze Alternative:= .

  • Ich habe den überflüssigen param1 entfernt aus dem chaotischen Beispiel.

  • Da Sie SELECT * FROM foobar zurückgeben , deklarieren Sie den Rückgabetyp als RETURNS SETOF foobar anstelle von RETURNS SETOF record . Letztere Form mit anonymen Datensätzen ist sehr unhandlich, man müsste bei jedem Aufruf eine Spaltendefinitionsliste angeben.

  • Ich verwende ein Integer-Array (int[] ) als Funktionsparameter. IF angepasst Ausdruck und das WHERE Klausel entsprechend.

  • IF Anweisungen sind in einfachem SQL nicht verfügbar. Muss LANGUAGE plpgsql sein dafür.

Aufruf mit oder ohne _ids :

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

Im Grunde dasselbe:

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

Sie müssen sicherstellen, dass der Aufruf eindeutig ist. Wenn Sie eine andere Funktion mit demselben Namen und zwei Parametern haben, weiß Postgres möglicherweise nicht, welche Sie auswählen sollen. Explizites Casting (wie ich demonstriere) grenzt es ein. Ansonsten funktionieren auch untypisierte String-Literale, aber es schadet nie, explizit zu sein.

Aufruf aus einer anderen Funktion heraus:

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