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

Restituisce più campi come record in PostgreSQL con PL/pgSQL

Non utilizzare CREATE TYPE per restituire un risultato polimorfico. Usa e abusa invece del tipo RECORD. Dai un'occhiata:

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;

Presta attenzione al fatto che può facoltativamente restituire due o tre colonne a seconda dell'input.

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)

Questo crea scompiglio nel codice, quindi usa un numero coerente di colonne, ma è ridicolmente utile per restituire messaggi di errore facoltativi con il primo parametro che restituisce il successo dell'operazione. Riscritto utilizzando un numero consistente di colonne:

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;

Quasi al calore epico:

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)

Ma come lo suddividi in più righe in modo che il tuo livello ORM preferito possa convertire i valori nei tipi di dati nativi della tua lingua preferita? Il calore:

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)

Questa è una delle funzionalità più interessanti e sottoutilizzate di PostgreSQL. Per favore, spargi la voce.