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

Establecer un valor de retorno predeterminado para una función de Postgres

Debe cambiar el idioma de sql a plpgsql si desea utilizar las funciones de procedimiento de PL/pgSQL. El cuerpo de la función también cambia.

Tenga en cuenta que todos los nombres de los parámetros están visibles en el cuerpo de la función , incluidos todos los niveles de sentencias SQL. Si crea un conflicto de nombres, es posible que deba calificar los nombres de las columnas como este:table.col , para evitar confusión. Dado que se refiere a los parámetros de función por referencia posicional ($n ) de todos modos, simplemente eliminé los nombres de los parámetros para que funcione.

Finalmente, THEN faltaba en el IF instrucción:la causa inmediata del mensaje de error .

Se podría usar COALESCE para sustituir NULL valores. Pero eso solo funciona si hay al menos una fila resultante. COALESCE no puede corregir "sin fila", solo puede reemplazar NULL real valores.

Hay varias formas de cubrir todos los NULL casos. En funciones plpgsql :

CREATE OR REPLACE FUNCTION point_total(integer, date, OUT result bigint)
  RETURNS bigint AS
$func$
BEGIN

SELECT sum(p.points)          -- COALESCE would make sense ...
INTO   result
FROM   picks p
WHERE  p.user_id = $1
AND    p.gametime > $2
AND    p.points IS NOT NULL;  -- ... if NULL values were not ruled out

IF NOT FOUND THEN             -- If no row was found ...
   result := 0;               -- ... set to 0 explicitly
END IF;

END
$func$  LANGUAGE plpgsql;

O puede encerrar toda la consulta en un COALESCE expresión en un SELECT externo . "Sin fila" desde el interior SELECT da como resultado un NULL en la expresión. Trabaje como SQL simple, o puede envolverlo en una función sql :

CREATE OR REPLACE FUNCTION point_total(integer, date)
  RETURNS bigint AS
$func$
SELECT COALESCE(
  (SELECT sum(p.points)
   FROM   picks p
   WHERE  p.user_id = $1
   AND    p.gametime > $2
   -- AND    p.points IS NOT NULL  -- redundant here
  ), 0)
$func$  LANGUAGE sql;

Respuesta relacionada:

Sobre los conflictos de nombres

Un problema era probablemente el conflicto de nombres. Ha habido cambios importantes en la versión 9.0 . Cito las notas de la versión :

Las versiones posteriores han refinado el comportamiento. En lugares obvios, la alternativa correcta se elige automáticamente. Reduce el potencial de conflictos, pero sigue ahí. El consejo aún se aplica en Postgres 9.3.