sql >> Base de Datos >  >> RDS >> PostgreSQL

Argumento opcional en la función PL/pgSQL

Desde PostgreSQL 8.4 (que parece estar ejecutando), existen valores predeterminados para los parámetros de función . Si coloca su parámetro en último lugar y proporciona un valor predeterminado, simplemente puede omitirlo de la llamada:

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

Puntos principales:

  • La palabra clave DEFAULT se utiliza para declarar valores predeterminados de parámetros. Alternativa corta:= .

  • Eliminé el param1 redundante del ejemplo desordenado.

  • Ya que devuelves SELECT * FROM foobar , declara el tipo de retorno como RETURNS SETOF foobar en lugar de RETURNS SETOF record . La última forma con registros anónimos es muy difícil de manejar, tendría que proporcionar una lista de definición de columna con cada llamada.

  • Uso una matriz de enteros (int[] ) como parámetro de función. Adaptado el IF expresión y el WHERE cláusula en consecuencia.

  • IF Las declaraciones no están disponibles en SQL simple. Tiene que ser LANGUAGE plpgsql por eso.

Llamar con o sin _ids :

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

Efectivamente lo mismo:

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

Tienes que asegurarte de que la llamada no sea ambigua. Si tiene otra función con el mismo nombre y dos parámetros, es posible que Postgres no sepa cuál elegir. El lanzamiento explícito (como lo demuestro) lo reduce. De lo contrario, los literales de cadena sin tipo también funcionan, pero ser explícito nunca está de más.

Llamar desde dentro de otra función:

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