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

Legen Sie einen Standardrückgabewert für eine Postgres-Funktion fest

Sie müssen die Sprache von sql ändern zu plpgsql wenn Sie die prozeduralen Features von PL/pgSQL nutzen möchten. Der Funktionskörper ändert sich ebenfalls.

Beachten Sie, dass alle Parameternamen im Funktionskörper sichtbar sind , einschließlich aller Ebenen von SQL-Anweisungen. Wenn Sie einen Namenskonflikt erzeugen, müssen Sie möglicherweise Spaltennamen wie folgt tabellenqualifizieren:table.col , um Verwirrung zu vermeiden. Da Sie auf Funktionsparameter durch Positionsreferenz verweisen ($n ) trotzdem habe ich nur Parameternamen entfernt, damit es funktioniert.

Zum Schluss THEN fehlte im IF -Anweisung - die unmittelbare Ursache der Fehlermeldung .

Man könnte COALESCE um NULL zu ersetzen Werte. Das funktioniert aber nur, wenn es mindestens eine resultierende Zeile gibt. COALESCE kann "keine Zeile" nicht beheben, es kann nur das tatsächliche NULL ersetzen Werte.

Es gibt mehrere Möglichkeiten, alle NULL abzudecken Fälle. In plpgsql-Funktionen :

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;

Oder Sie können die gesamte Abfrage in ein COALESCE einschließen Ausdruck in einem äußeren SELECT . "Keine Zeile" aus dem inneren SELECT ergibt einen NULL im Ausdruck. Arbeiten Sie als einfaches SQL, oder Sie können es in eine sql-Funktion packen :

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;

Zugehörige Antwort:

In Bezug auf Namenskonflikte

Ein Problem war höchstwahrscheinlich der Namenskonflikt. In Version 9.0 wurden wichtige Änderungen vorgenommen . Ich zitiere die Versionshinweise :

Spätere Versionen haben das Verhalten verfeinert. An offensichtlichen Stellen wird automatisch die richtige Alternative ausgewählt. Reduziert das Konfliktpotenzial, ist aber immer noch da. Der Rat gilt weiterhin in Postgres 9.3.