PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

Imposta un valore di ritorno predefinito per una funzione Postgres

Devi cambiare la lingua da sql a plpgsql se si desidera utilizzare le funzionalità procedurali di PL/pgSQL. Anche il corpo della funzione cambia.

Tieni presente che tutti i nomi dei parametri sono visibili nel corpo della funzione , inclusi tutti i livelli di istruzioni SQL. Se crei un conflitto di nomi, potresti dover qualificare come tabella i nomi delle colonne in questo modo:table.col , evitare la confusione. Poiché si fa riferimento ai parametri di funzione tramite riferimento posizionale ($n ) comunque, ho appena rimosso i nomi dei parametri per farlo funzionare.

Infine, THEN mancava nel IF dichiarazione - la causa immediata del messaggio di errore .

Si potrebbe usare COALESCE per sostituire NULL i valori. Ma funziona solo se c'è almeno una riga risultante. COALESCE non è possibile correggere "nessuna riga" può solo sostituire NULL effettivo valori.

Esistono diversi modi per coprire tutti i NULL casi. Nelle funzioni 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;

Oppure puoi racchiudere l'intera query in un COALESCE espressione in un SELECT esterno . "Nessuna riga" dal SELECT interno risulta in un NULL nell'espressione. Funziona come un semplice SQL oppure puoi racchiuderlo in una funzione 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;

Risposta correlata:

Riguardo ai conflitti di denominazione

Un problema era il conflitto di denominazione molto probabilmente. Sono state apportate importanti modifiche alla versione 9.0 . Cito le note sulla versione :

Le versioni successive hanno perfezionato il comportamento. In punti ovvi viene selezionata automaticamente l'alternativa giusta. Riduce il potenziale di conflitti, ma è ancora lì. Il consiglio si applica ancora in Postgres 9.3.