PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

Renvoyer plusieurs champs sous forme d'enregistrement dans PostgreSQL avec PL/pgSQL

N'utilisez pas CREATE TYPE pour renvoyer un résultat polymorphe. Utilisez et abusez plutôt du type RECORD. Vérifiez-le :

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;

Faites attention au fait qu'il peut éventuellement retourner deux ou trois colonnes en fonction de l'entrée.

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)

Cela fait des ravages sur le code, utilisez donc un nombre constant de colonnes, mais c'est ridiculement pratique pour renvoyer des messages d'erreur facultatifs avec le premier paramètre renvoyant le succès de l'opération. Réécrit en utilisant un nombre constant de colonnes :

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;

Une chaleur presque épique :

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)

Mais comment divisez-vous cela en plusieurs lignes afin que la couche ORM de votre choix puisse convertir les valeurs dans les types de données natifs de la langue de votre choix ? La chaleur :

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)

C'est l'une des fonctionnalités les plus intéressantes et les moins utilisées de PostgreSQL. Merci de passer le mot.