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

Mehrere Felder als Datensatz in PostgreSQL mit PL/pgSQL zurückgeben

Verwenden Sie CREATE TYPE nicht, um ein polymorphes Ergebnis zurückzugeben. Verwenden und missbrauchen Sie stattdessen den RECORD-Typ. Probieren Sie es aus:

CREATE FUNCTION test_ret(a TEXT, b TEXT) RETURNS RECORD AS $$
DECLARE 
  ret RECORD;
BEGIN
  -- Arbitrary expression to change the first parameter
  IF LENGTH(a) < LENGTH(b) THEN
      SELECT TRUE, a || b, 'a shorter than b' INTO ret;
  ELSE
      SELECT FALSE, b || a INTO ret;
  END IF;
RETURN ret;
END;$$ LANGUAGE plpgsql;

Beachten Sie, dass es optional zwei zurückgeben kann oder drei Spalten abhängig von der Eingabe.

test=> SELECT test_ret('foo','barbaz');
             test_ret             
----------------------------------
 (t,foobarbaz,"a shorter than b")
(1 row)

test=> SELECT test_ret('barbaz','foo');
             test_ret             
----------------------------------
 (f,foobarbaz)
(1 row)

Dies richtet Chaos im Code an, verwenden Sie also eine konsistente Anzahl von Spalten, aber es ist lächerlich praktisch, um optionale Fehlermeldungen zurückzugeben, wobei der erste Parameter den Erfolg der Operation zurückgibt. Umgeschrieben unter Verwendung einer konsistenten Anzahl von Spalten:

CREATE FUNCTION test_ret(a TEXT, b TEXT) RETURNS RECORD AS $$
DECLARE 
  ret RECORD;
BEGIN
  -- Note the CASTING being done for the 2nd and 3rd elements of the RECORD
  IF LENGTH(a) < LENGTH(b) THEN
      ret := (TRUE, (a || b)::TEXT, 'a shorter than b'::TEXT);
  ELSE
      ret := (FALSE, (b || a)::TEXT, NULL::TEXT);
   END IF;
RETURN ret;
END;$$ LANGUAGE plpgsql;

Fast zu epischer Schärfe:

test=> SELECT test_ret('foobar','bar');
   test_ret    
----------------
 (f,barfoobar,)
(1 row)

test=> SELECT test_ret('foo','barbaz');
             test_ret             
----------------------------------
 (t,foobarbaz,"a shorter than b")
(1 row)

Aber wie teilen Sie das in mehrere Zeilen auf, damit Ihre bevorzugte ORM-Schicht die Werte in die nativen Datentypen Ihrer bevorzugten Sprache konvertieren kann? Die Schärfe:

test=> SELECT a, b, c FROM test_ret('foo','barbaz') AS (a BOOL, b TEXT, c TEXT);
 a |     b     |        c         
---+-----------+------------------
 t | foobarbaz | a shorter than b
(1 row)

test=> SELECT a, b, c FROM test_ret('foobar','bar') AS (a BOOL, b TEXT, c TEXT);
 a |     b     | c 
---+-----------+---
 f | barfoobar | 
(1 row)

Dies ist eine der coolsten und am wenigsten genutzten Funktionen in PostgreSQL. Bitte weitersagen.