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.